diff --git a/Compositor/ALS/als.xml b/Compositor/ALS/als.xml index 860627a89..84855f100 100644 --- a/Compositor/ALS/als.xml +++ b/Compositor/ALS/als.xml @@ -76,13 +76,13 @@ forward scene als-lighting - + + + 128 + 1 + 1 + + csm0 csm1 csm2 diff --git a/Compositor/Effects/model-default.eff b/Compositor/Effects/model-default.eff index aa3575b8b..72e1c2abc 100644 --- a/Compositor/Effects/model-default.eff +++ b/Compositor/Effects/model-default.eff @@ -481,6 +481,15 @@ Shaders/ALS/noise.frag Shaders/ALS/filters.frag Shaders/ALS/shadows-include.frag + Shaders/ALS/clustered-include.frag + + PointLightBlock + 5 + + + SpotLightBlock + 6 + visibility diff --git a/Compositor/Shaders/ALS/clustered-include.frag b/Compositor/Shaders/ALS/clustered-include.frag new file mode 100644 index 000000000..85d7ce45b --- /dev/null +++ b/Compositor/Shaders/ALS/clustered-include.frag @@ -0,0 +1,136 @@ +#version 120 + +#extension GL_ARB_uniform_buffer_object : enable +#extension GL_EXT_gpu_shader4 : enable + +uniform usampler3D fg_ClusteredLightGrid; +uniform usamplerBuffer fg_ClusteredLightIndices; +uniform int fg_ClusteredTileSize; +uniform float fg_ClusteredSliceScale; +uniform float fg_ClusteredSliceBias; + +const bool debug = true; +const float shininess = 16.0; + +struct PointLight { + vec4 position; + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 attenuation; +}; + +struct SpotLight { + vec4 position; + vec4 direction; + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 attenuation; + float cos_cutoff; + float exponent; +}; + +layout (std140) uniform PointLightBlock { + PointLight pointLights[256]; +}; +layout (std140) uniform SpotLightBlock { + SpotLight spotLights[256]; +}; + + +vec3 addColors(vec3 a, vec3 b) +{ + return 0.14 * log(exp(a/0.14) + exp(b/0.14)); +} + +// @param p Fragment position in view space. +// @param n Fragment normal in view space. +vec3 addClusteredLightsContribution(vec3 inputColor, vec3 p, vec3 n) +{ + int slice = int(max(log2(-p.z) * fg_ClusteredSliceScale + + fg_ClusteredSliceBias, 0.0)); + ivec3 clusterCoord = ivec3(gl_FragCoord.xy / fg_ClusteredTileSize, slice); + uvec3 cluster = texelFetch3D(fg_ClusteredLightGrid, + clusterCoord, + 0).rgb; + uint startIndex = cluster.r; + uint pointCount = cluster.g; + uint spotCount = cluster.b; + + vec3 color = vec3(0.0); + + for (uint i = uint(0); i < pointCount; ++i) { + uint lightListIndex = texelFetchBuffer(fg_ClusteredLightIndices, + int(startIndex + i)).r; + PointLight light = pointLights[lightListIndex]; + + float range = light.attenuation.w; + vec3 toLight = light.position.xyz - p; + // Ignore fragments outside the light volume + if (dot(toLight, toLight) > (range * range)) + continue; + + //////////////////////////////////////////////////////////////////////// + // Actual lighting + + float d = length(toLight); + float att = 1.0 / (light.attenuation.x // constant + + light.attenuation.y * d // linear + + light.attenuation.z * d * d); // quadratic + vec3 lightDir = normalize(toLight); + float NdotL = max(dot(n, lightDir), 0.0); + + vec3 Iamb = light.ambient.rgb; + vec3 Idiff = light.diffuse.rgb * NdotL; + vec3 Ispec = vec3(0.0); + + if (NdotL > 0.0) { + vec3 halfVector = normalize(lightDir + normalize(-p)); + float NdotHV = max(dot(n, halfVector), 0.0); + Ispec = light.specular.rgb * att * pow(NdotHV, shininess); + } + + color += addColors(color, (Iamb + Idiff + Ispec) * att); + } + + for (uint i = uint(0); i < spotCount; ++i) { + uint lightListIndex = texelFetchBuffer(fg_ClusteredLightIndices, + int(startIndex + i)).r; + SpotLight light = spotLights[lightListIndex]; + + vec3 toLight = light.position.xyz - p; + + //////////////////////////////////////////////////////////////////////// + // Actual lighting + + float d = length(toLight); + float att = 1.0 / (light.attenuation.x // constant + + light.attenuation.y * d // linear + + light.attenuation.z * d * d); // quadratic + + vec3 lightDir = normalize(toLight); + + float spotDot = dot(-lightDir, light.direction.xyz); + if (spotDot < light.cos_cutoff) + continue; + + att *= pow(spotDot, light.exponent); + + float NdotL = max(dot(n, lightDir), 0.0); + + vec3 Iamb = light.ambient.rgb; + vec3 Idiff = light.diffuse.rgb * NdotL; + vec3 Ispec = vec3(0.0); + + if (NdotL > 0.0) { + vec3 halfVector = normalize(lightDir + normalize(-p)); + float NdotHV = max(dot(n, halfVector), 0.0); + Ispec = light.specular.rgb * att * pow(NdotHV, shininess); + } + + color += (Iamb + Idiff + Ispec) * att; + } + + return clamp(color + inputColor, 0.0, 1.0); +} diff --git a/Compositor/Shaders/ALS/generic-base.vert b/Compositor/Shaders/ALS/generic-base.vert index cd1150e29..6895e834b 100644 --- a/Compositor/Shaders/ALS/generic-base.vert +++ b/Compositor/Shaders/ALS/generic-base.vert @@ -22,6 +22,7 @@ varying vec4 diffuse_term; varying vec3 normal; varying vec3 relPos; +varying vec4 ecPosition; varying float yprime_alt; varying float mie_angle; @@ -75,7 +76,7 @@ void main() // this code is copied from default.vert - //vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; + ecPosition = gl_ModelViewMatrix * gl_Vertex; gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; diff --git a/Compositor/Shaders/ALS/model-base.frag b/Compositor/Shaders/ALS/model-base.frag index ecd756ff1..437b924fe 100644 --- a/Compositor/Shaders/ALS/model-base.frag +++ b/Compositor/Shaders/ALS/model-base.frag @@ -6,7 +6,7 @@ varying vec4 diffuse_term; varying vec3 normal; varying vec3 relPos; - +varying vec4 ecPosition; uniform sampler2D texture; @@ -57,6 +57,7 @@ vec3 landing_light(in float offset, in float offsetv); vec3 filter_combined (in vec3 color) ; float getShadowing(); +vec3 addClusteredLightsContribution(vec3 inputColor, vec3 v, vec3 N); float luminance(vec3 color) { @@ -318,6 +319,7 @@ fragColor.rgb = mix(hazeColor + secondary_light * fog_backscatter(mvisibility), } +fragColor.rgb = addClusteredLightsContribution(fragColor.rgb, ecPosition.xyz, normal); fragColor.rgb = filter_combined(fragColor.rgb); gl_FragColor = fragColor;