From e143c05ef83e9e798129a5afa38df31d9e4d28c7 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 30 Sep 2016 02:41:21 -0700 Subject: [PATCH] Keep on investigating the shading cost per light --- .../model/src/model/LightVolume.shared.slh | 41 ++---- .../render-utils/src/LightClusterGrid.slh | 7 +- libraries/render-utils/src/LightClusters.cpp | 29 +++-- libraries/render-utils/src/LightPoint.slh | 8 +- libraries/render-utils/src/LightingModel.slh | 39 +++++- .../src/lightClusters_drawClusterContent.slv | 4 +- .../lightClusters_drawClusterFromDepth.slf | 4 +- .../src/lightClusters_drawGrid.slv | 4 +- .../render-utils/src/local_lights_shading.slf | 121 ++++++++++++++---- 9 files changed, 173 insertions(+), 84 deletions(-) diff --git a/libraries/model/src/model/LightVolume.shared.slh b/libraries/model/src/model/LightVolume.shared.slh index ac75308c18..a78667ed6c 100644 --- a/libraries/model/src/model/LightVolume.shared.slh +++ b/libraries/model/src/model/LightVolume.shared.slh @@ -40,39 +40,24 @@ bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out ve return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv)); } - -bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { - fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz; - fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz); - - // Kill if too far from the light center - if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) { - return false; - } - - // Allright we re valid in the volume - fragLightDirLen.w = length(fragLightVecLen2.xyz); - fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - - // Kill if not in the spot light (ah ah !) - cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); - if (cosSpotAngle < lightVolume_getSpotAngleCos(lv)) { - return false; - } - - return true; -} - -bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { - // Allright we re valid in the volume - fragLightDirLen.w = length(fragLightVecLen2.xyz); - fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - +bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) { // Kill if not in the spot light (ah ah !) cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0); return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv)); } +bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) { + if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) { + return false; + } + + // Allright we re valid in the volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + + return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle); +} + #endif diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 3395f1be1a..14595c91a0 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -55,11 +55,12 @@ uniform clusterContentBuffer { int _clusterGridContent[16384]; }; -ivec2 clusterGrid_getCluster(int index) { +ivec3 clusterGrid_getCluster(int index) { int clusterDesc = _clusterGridTable[index]; - int numLights = 0xFFFF & (clusterDesc >> 16); + int numPointLights = 0xFF & (clusterDesc >> 16); + int numSpotLights = 0xFF & (clusterDesc >> 24); int contentOffset = 0xFFFF & (clusterDesc); - return ivec2(numLights, contentOffset); + return ivec3(numPointLights, numSpotLights, contentOffset); } int clusterGrid_getClusterLightId(int index, ivec2 cluster) { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index cf79e30630..870dccaeea 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -270,7 +270,8 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan void LightClusters::updateClusters() { // Clean up last info - std::vector< std::vector< LightIndex > > clusterGrid(_numClusters); + std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters); + std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters); _clusterGrid.resize(_numClusters, EMPTY_CLUSTER); uint32_t maxNumIndices = (uint32_t) _clusterContent.size(); @@ -289,6 +290,7 @@ void LightClusters::updateClusters() { auto worldOri = light->getPosition(); auto radius = light->getMaximumRadius(); + bool isSpot = light->isSpot(); // Bring into frustum eye space auto eyeOri = theFrustumGrid.frustumGrid_worldToEye(glm::vec4(worldOri, 1.0f)); @@ -395,6 +397,7 @@ void LightClusters::updateClusters() { } // now voxelize + auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint); numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid); } @@ -405,9 +408,13 @@ void LightClusters::updateClusters() { checkBudget = true; } uint16_t indexOffset = 0; - for (int i = 0; i < clusterGrid.size(); i++) { - auto& cluster = clusterGrid[i]; - uint16_t numLights = ((uint16_t)cluster.size()); + for (int i = 0; i < clusterGridPoint.size(); i++) { + auto& clusterPoint = clusterGridPoint[i]; + auto& clusterSpot = clusterGridSpot[i]; + + uint8_t numLightsPoint = ((uint8_t)clusterPoint.size()); + uint8_t numLightsSpot = ((uint8_t)clusterSpot.size()); + uint16_t numLights = numLightsPoint + numLightsSpot; uint16_t offset = indexOffset; // Check for overflow @@ -417,14 +424,18 @@ void LightClusters::updateClusters() { } } - _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + // _clusterGrid[i] = (uint32_t)((numLights << 16) | offset); + _clusterGrid[i] = (uint32_t)((numLightsSpot << 24) | (numLightsPoint << 16) | offset); - if (numLights) { - memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightIndex)); + if (numLightsPoint) { + memcpy(_clusterContent.data() + indexOffset, clusterPoint.data(), numLightsPoint * sizeof(LightIndex)); + indexOffset += numLightsPoint; + } + if (numLightsSpot) { + memcpy(_clusterContent.data() + indexOffset, clusterSpot.data(), numLightsSpot * sizeof(LightIndex)); + indexOffset += numLightsSpot; } - - indexOffset += numLights; } // update the buffers diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 362aac5298..5160396e8a 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -12,16 +12,16 @@ <@func declareLightingPoint(supportScattering)@> void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, - vec3 fragLightVec, vec3 fragEyeDir, vec3 normal, float roughness, + vec4 fragLightDirLen, vec3 fragEyeDir, vec3 normal, float roughness, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature <@endif@> ) { - + // Allright we re valid in the volume - float fragLightDistance = length(fragLightVec); - vec3 fragLightDir = fragLightVec / fragLightDistance; + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index f36b2d8131..9d5f78a581 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -82,12 +82,6 @@ float fetchSpecularBeckmann(float ndoth, float roughness) { return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0); } -float fresnelSchlickScalar(float fresnelColor, vec3 lightDir, vec3 halfDir) { - float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); - float exponential = pow(base, 5.0); - return (exponential)+fresnelColor * (1.0 - exponential); -} - vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { vec2 result = vec2(0.0, 1.0); float ndotl = dot(N, L); @@ -114,6 +108,11 @@ vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) { return vec3(exponential) + fresnelColor * (1.0 - exponential); } +float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) { + float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); + float exponential = pow(base, 5.0); + return (exponential) + fresnelScalar * (1.0 - exponential); +} float specularDistribution(float roughness, vec3 normal, vec3 halfDir) { @@ -144,6 +143,21 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float m return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x)); } + +// Frag Shading returns the diffuse amount as W and the specular rgb as xyz +vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness) { + // Diffuse Lighting + float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + + // Specular Lighting + vec3 halfDir = normalize(fragEyeDir + fragLightDir); + float fresnelScalar = fresnelSchlickScalar(0.03, fragLightDir, halfDir); + float power = specularDistribution(roughness, fragNormal, halfDir); + float specular = power * fresnelScalar * diffuse; + + return vec4(vec3(specular), diffuse * (1 - fresnelScalar)); +} + <@endfunc@> @@ -196,5 +210,18 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, } } +void evalFragShadingSimpler(out vec3 diffuse, out vec3 specular, + vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, + float metallic, vec3 fresnel, float roughness, vec3 albedo +/* + ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature +*/ +) { + vec4 shading = evalPBRShadingDielectric(fragNormal, fragLightDir, fragEyeDir, roughness); + // vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + diffuse = vec3(shading.w); + diffuse *= albedo; + specular = shading.xyz; +} <@endif@> diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 5bf6a0bf18..8b8bdd9c94 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -53,8 +53,8 @@ void main(void) { - ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0); diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index 1820d3113b..51d0faefa7 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -37,8 +37,8 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0); diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index 15fa8ac38a..a6590ada3f 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -54,8 +54,8 @@ void main(void) { vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - ivec2 cluster = clusterGrid_getCluster(gl_InstanceID); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(gl_InstanceID); + int numLights = cluster.x + cluster.y; ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID); diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index 3d85c0ccab..57068c4052 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -58,11 +58,13 @@ void main(void) { ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x; + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; if (numLights <= 0) { discard; } + int lightClusterOffset = cluster.z; + ivec2 clusterAddress = ivec2(numLights, lightClusterOffset); ivec3 dims = frustumGrid.dims.xyz; if (clusterPos.x < 0 || clusterPos.x >= dims.x) { @@ -76,7 +78,6 @@ void main(void) { discard; } - int lightClusterOffset = cluster.y; @@ -92,48 +93,112 @@ void main(void) { vec3 fragEyeDir = normalize(fragEyeVector.xyz); int numLightTouching = 0; - for (int i = 0; i < numLights && numLightTouching < 16; i++) { + for (int i = 0; i < cluster.x; i++) { // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, cluster); + int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); Light light = getLight(theLightIndex); - bool isSpot = light_isSpot(light); // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space vec4 fragLightVecLen2; vec4 fragLightDirLen; - float cosSpotAngle; + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { continue; } - if (isSpot && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { - continue; - } - if (dot(frag.normal, normalize(fragLightVecLen2.xyz)) < 0.0) { - //_fragColor.rgb += vec3(0.0, 0.0, 1.0 / 16.0); + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { continue; } numLightTouching++; - /* - vec3 diffuse; - vec3 specular; - if (isSpot) { - evalLightingSpot(diffuse, specular, light, - fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - } else { - evalLightingPoint(diffuse, specular, light, - fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness, - frag.metallic, frag.fresnel, frag.albedo, 1.0, - frag.scattering, midNormalCurvature, lowNormalCurvature); - } + vec3 diffuse = vec3(1.0); + vec3 specular = vec3(0.1); + + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); + + // Eval shading + evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature + ); + /* + evalLightingPoint(diffuse, specular, light, + fragLightDirLen.xyzw, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + */ + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); + _fragColor.rgb += diffuse; _fragColor.rgb += specular; - */ - _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); + } + + for (int i = cluster.x; i < numLights; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress); + Light light = getLight(theLightIndex); + + // Clip againgst the light volume and Make the Light vector going from fragment to light center in world space + vec4 fragLightVecLen2; + vec4 fragLightDirLen; + float cosSpotAngle; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) { + continue; + } + + // Check spot + if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) { + continue; + } + + numLightTouching++; + + vec3 diffuse = vec3(1.0); + vec3 specular = vec3(0.1); + + // Allright we re valid in the volume + float fragLightDistance = fragLightDirLen.w; + vec3 fragLightDir = fragLightDirLen.xyz; + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); + vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light); + + // Eval shading + evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo + ,frag.scattering, midNormalCurvature, lowNormalCurvature + ); + /* evalLightingSpot(diffuse, specular, light, + fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness, + frag.metallic, frag.fresnel, frag.albedo, 1.0, + frag.scattering, midNormalCurvature, lowNormalCurvature); + */ + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); + + _fragColor.rgb += diffuse; + _fragColor.rgb += specular; + + // _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0); } }