diff --git a/libraries/graphics/src/graphics/Light.slh b/libraries/graphics/src/graphics/Light.slh index 6b24f89c3c..e1202ed6a0 100644 --- a/libraries/graphics/src/graphics/Light.slh +++ b/libraries/graphics/src/graphics/Light.slh @@ -56,10 +56,10 @@ Light getLight(int index) { } <@else@> -uniform lightBuffer { +uniform keyLightBuffer { Light light; }; -Light getLight() { +Light getKeyLight() { return light; } diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 2901b4796e..fae645fdbc 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -21,21 +21,25 @@ <@include LightDirectional.slh@> -<@func prepareGlobalLight(isScattering)@> - // prepareGlobalLight - // Transform directions to worldspace - vec3 fragNormal = vec3((normal)); - vec3 fragEyeVector = vec3(invViewMat * vec4(-1.0*position, 0.0)); - vec3 fragEyeDir = normalize(fragEyeVector); - +<@func fetchGlobalLight()@> // Get light - Light light = getLight(); + Light light = getKeyLight(); LightAmbient lightAmbient = getLightAmbient(); vec3 lightDirection = getLightDirection(light); vec3 lightIrradiance = getLightIrradiance(light); vec3 color = vec3(0.0); +<@endfunc@> + +<@func prepareGlobalLight(isScattering)@> + // prepareGlobalLight + // Transform directions to worldspace + vec3 fragNormal = vec3((normal)); + vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + + <$fetchGlobalLight()$> <@endfunc@> @@ -147,7 +151,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu <@func declareEvalLightmappedColor()@> vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { - Light light = getLight(); + Light light = getKeyLight(); LightAmbient ambient = getLightAmbient(); // Catch normals perpendicular to the projection plane, hence the magic number for the threshold @@ -175,11 +179,12 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <$declareLightingAmbient(1, 1, 1)$> <$declareLightingDirectional()$> -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { +vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) { <$prepareGlobalLight()$> SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + color = prevLighting; color += emissive * isEmissiveEnabled(); // Ambient @@ -238,6 +243,44 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( return color; } + +vec3 evalGlobalLightingAlphaBlendedWithHaze( + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) +{ + <$fetchGlobalLight()$> + + color = prevLighting; + color += emissive * isEmissiveEnabled(); + + // Ambient + vec3 ambientDiffuse; + vec3 ambientSpecular; + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance); + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); + + color += ambientDiffuse + directionalDiffuse; + color += (ambientSpecular + directionalSpecular) / opacity; + + // Haze + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 colorV4 = computeHazeColor( + vec4(color, 1.0), // fragment original color + position, // fragment position in eye coordinates + surface.eyeDir, // fragment eye vector in world coordinates + invViewMat[3].y, // eye height in world coordinates + lightDirection // keylight direction vector + ); + + color = colorV4.rgb; + } + + return color; +} <@endfunc@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 61965940fd..d0d9708c04 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -45,6 +45,7 @@ using namespace render; struct LightLocations { int radius{ -1 }; + int keyLightBufferUnit{ -1 }; int lightBufferUnit{ -1 }; int ambientBufferUnit { -1 }; int lightIndexBufferUnit { -1 }; @@ -147,6 +148,29 @@ void DeferredLightingEffect::unsetKeyLightBatch(gpu::Batch& batch, int lightBuff } } +void DeferredLightingEffect::setupLocalLightsBatch(gpu::Batch& batch, + int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit, + const LightClustersPointer& lightClusters) { + // Bind the global list of lights and the visible lights this frame + batch.setUniformBuffer(_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer()); + + batch.setUniformBuffer(frustumGridBufferUnit, lightClusters->_frustumGridBuffer); + batch.setUniformBuffer(clusterGridBufferUnit, lightClusters->_clusterGridBuffer); + batch.setUniformBuffer(clusterContentBufferUnit, lightClusters->_clusterContentBuffer); +} + +void DeferredLightingEffect::unsetLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit) { + if (clusterGridBufferUnit >= 0) { + batch.setUniformBuffer(clusterGridBufferUnit, nullptr); + } + if (clusterContentBufferUnit >= 0) { + batch.setUniformBuffer(clusterContentBufferUnit, nullptr); + } + if (frustumGridBufferUnit >= 0) { + batch.setUniformBuffer(frustumGridBufferUnit, nullptr); + } +} + static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* fragSource, LightLocationsPtr& locations) { auto VS = gpu::Shader::createVertex(std::string(vertSource)); auto PS = gpu::Shader::createPixel(std::string(fragSource)); @@ -189,6 +213,7 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); + locations->keyLightBufferUnit = program->getUniformBuffers().findLocation("keyLightBuffer"); locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); locations->ambientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightIndexBufferUnit = program->getUniformBuffers().findLocation("lightIndexBuffer"); @@ -561,7 +586,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); // Setup the global lighting - deferredLightingEffect->setupKeyLightBatch(args, batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); + deferredLightingEffect->setupKeyLightBatch(args, batch, locations->keyLightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); // Haze if (haze) { @@ -570,7 +595,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch.draw(gpu::TRIANGLE_STRIP, 4); - deferredLightingEffect->unsetKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); + deferredLightingEffect->unsetKeyLightBatch(batch, locations->keyLightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { batch.setResourceTexture(SHADOW_MAP_UNIT+i, nullptr); @@ -625,12 +650,8 @@ void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext auto& lightIndices = lightClusters->_visibleLightIndices; if (!lightIndices.empty() && lightIndices[0] > 0) { - // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer()); - - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); - batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); + deferredLightingEffect->setupLocalLightsBatch(batch, LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, + lightClusters); // Local light pipeline batch.setPipeline(deferredLightingEffect->_localLight); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 6d2c0a6819..1b776e6409 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -51,6 +51,9 @@ public: void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); + void setupLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit, const LightClustersPointer& lightClusters); + void unsetLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit); + void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 64a106a09c..8cb2d41723 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -147,7 +147,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), HazeEffect_LightingMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), HazeEffect_LightingMapSlot)); gpu::Shader::makeProgram(*program, slotBindings); _hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh index e86f0c7fe3..a55e2ea651 100644 --- a/libraries/render-utils/src/ForwardGlobalLight.slh +++ b/libraries/render-utils/src/ForwardGlobalLight.slh @@ -29,7 +29,7 @@ vec3 fragEyeDir = normalize(fragEyeVector); // Get light - Light light = getLight(); + Light light = getKeyLight(); LightAmbient lightAmbient = getLightAmbient(); vec3 lightDirection = getLightDirection(light); @@ -143,7 +143,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu <@func declareEvalLightmappedColor()@> vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { - Light light = getLight(); + Light light = getKeyLight(); LightAmbient ambient = getLightAmbient(); // Catch normals perpendicular to the projection plane, hence the magic number for the threshold diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 2d7daf1f98..e254266350 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -53,7 +53,7 @@ void main(void) { vec4 worldFragPos = viewInverse * eyeFragPos; vec4 worldEyePos = viewInverse[3]; - Light light = getLight(); + Light light = getKeyLight(); vec3 lightDirection = getLightDirection(light); outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y, lightDirection); diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 722d37814d..709e8c0f70 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -86,4 +86,24 @@ int clusterGrid_getClusterLightId(int index, int offset) { return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; } + +<@func fetchClusterInfo(fragWorldPos)@> + + // From frag world pos find the cluster + vec4 clusterEyePos = frustumGrid_worldToEye(<$fragWorldPos$>); + ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); + + ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); + int numLights = cluster.x + cluster.y; + ivec3 dims = frustumGrid.dims.xyz; + +<@endfunc@> + +bool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) { + return numLights>0 + && all(greaterThanEqual(clusterPos, ivec3(0))) + && all(lessThan(clusterPos.xy, dims.xy)) + && clusterPos.z <= dims.z; +} + <@endif@> diff --git a/libraries/render-utils/src/LightLocal.slh b/libraries/render-utils/src/LightLocal.slh new file mode 100644 index 0000000000..515a065d2e --- /dev/null +++ b/libraries/render-utils/src/LightLocal.slh @@ -0,0 +1,148 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 15/01/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Everything about light +<@include graphics/Light.slh@> +<$declareLightBuffer(256)$> +<@include LightingModel.slh@> + + +<@include LightPoint.slh@> +<$declareLightingPoint(supportScattering)$> +<@include LightSpot.slh@> +<$declareLightingSpot(supportScattering)$> + +<@include LightClusterGrid.slh@> + +vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface, + float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, + vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) { + vec4 fragColor = vec4(0.0); + vec3 fragSpecular = vec3(0.0); + vec3 fragDiffuse = vec3(0.0); + int lightClusterOffset = cluster.z; + + // Compute the rougness into gloss2 once: + bool withScattering = (fragScattering * isScatteringEnabled() > 0.0); + + int numLightTouching = 0; + for (int i = 0; i < cluster.x; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); + 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; + + if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) { + 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; + + updateSurfaceDataWithLight(surface, fragLightDir); + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); + + // Eval shading + if (withScattering) { + evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo, + fragScattering, midNormalCurvature, lowNormalCurvature ); + } else { + evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo); + } + + diffuse *= lightEnergy; + specular *= lightEnergy; + + fragDiffuse.rgb += diffuse; + fragSpecular.rgb += specular; + } + + for (int i = cluster.x; i < numLights; i++) { + // Need the light now + int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); + 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, fragWorldPos.xyz, fragLightVecLen2)) { + continue; + } + + // Allright we re in the light sphere volume + fragLightDirLen.w = length(fragLightVecLen2.xyz); + fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; + if (dot(surface.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; + + updateSurfaceDataWithLight(surface, fragLightDir); + + // Eval attenuation + float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); + float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); + vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light); + + // Eval shading + if (withScattering) { + evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo, + fragScattering, midNormalCurvature, lowNormalCurvature ); + } else { + evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo); + } + + diffuse *= lightEnergy; + specular *= lightEnergy; + + fragDiffuse.rgb += diffuse; + fragSpecular.rgb += specular; + } + + fragDiffuse *= isDiffuseEnabled(); + fragSpecular *= isSpecularEnabled(); + + fragColor.rgb += fragDiffuse; + fragColor.rgb += fragSpecular / opacity; + return fragColor; +} \ No newline at end of file diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index be8330f198..ddcbf8229c 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -289,9 +289,8 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, - float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo - ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -) { + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo, + float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) { vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); float NdotL = surface.ndotl; diffuse = mix(vec3(NdotL), brdf, scattering); @@ -305,8 +304,7 @@ void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, } void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, - float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo -) { + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) { vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a3c01f7fb3..f262307944 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -12,6 +12,8 @@ #include "RenderDeferredTask.h" +#include + #include #include #include @@ -168,7 +170,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawHazeDeferred", drawHazeInputs); // Render transparent objects forward in LightingBuffer - const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); + const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel, lightClusters).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); // Light Cluster Grid Debuging job @@ -298,6 +300,8 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); + const auto& lightClusters = inputs.get2(); + auto deferredLightingEffect = DependencyManager::get(); RenderArgs* args = renderContext->args; @@ -319,7 +323,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& // Setup lighting model for all items; batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); - // Setup haze iff current zone has haze + deferredLightingEffect->setupLocalLightsBatch(batch, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, + lightClusters); + + // Setup haze if current zone has haze auto hazeStage = args->_scene->getStage(); if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); @@ -341,6 +351,11 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& args->_batch = nullptr; args->_globalShapeKey = 0; + + deferredLightingEffect->unsetLocalLightsBatch(batch, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, + render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT); }); config->setNumDrawn((int)inItems.size()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 00804f7e7b..1b57c88768 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -15,6 +15,7 @@ #include #include #include "LightingModel.h" +#include "LightClusters.h" class DrawDeferredConfig : public render::Job::Config { Q_OBJECT @@ -40,7 +41,7 @@ protected: class DrawDeferred { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3 ; using Config = DrawDeferredConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index b6458ea80a..1c828c3d06 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -29,6 +29,8 @@ #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" +#include "model_translucent_vert.h" +#include "model_translucent_fade_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" @@ -188,6 +190,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); + auto modelTranslucentVertex = gpu::Shader::createVertex(std::string(model_translucent_vert)); + auto modelTranslucentFadeVertex = gpu::Shader::createVertex(std::string(model_translucent_fade_vert)); auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); @@ -196,6 +200,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelLightmapNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_fade_vert)); auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert)); auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert)); + auto skinModelTranslucentVertex = skinModelFadeVertex; // We use the same because it ouputs world position per vertex + auto skinModelNormalMapTranslucentVertex = skinModelNormalMapFadeVertex; // We use the same because it ouputs world position per vertex auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); @@ -289,7 +295,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Translucents addPipeline( Key::Builder().withMaterial().withTranslucent(), - modelVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withTranslucent(), simpleVertex, simpleTranslucentPixel, nullptr, nullptr); @@ -301,21 +307,21 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular(), - modelVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), - modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), - modelVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withTranslucent().withFade(), - modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withTranslucent().withFade(), simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter); @@ -396,16 +402,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Skinned and Translucent addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent(), - skinModelVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), - skinModelVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), @@ -571,9 +577,9 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderAr batchSetter(pipeline, batch, args); // Set the light - if (pipeline.locations->lightBufferUnit >= 0) { + if (pipeline.locations->keyLightBufferUnit >= 0) { DependencyManager::get()->setupKeyLightBatch(args, batch, - pipeline.locations->lightBufferUnit, + pipeline.locations->keyLightBufferUnit, pipeline.locations->lightAmbientBufferUnit, pipeline.locations->lightAmbientMapUnit); } diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index 1786898e57..2183f95565 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -463,7 +463,7 @@ gpu::PipelinePointer DebugSubsurfaceScattering::getScatteringPipeline() { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ScatteringTask_FrameTransformSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringParamsBuffer"), ScatteringTask_ParamSlot)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ScatteringTask_LightSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), ScatteringTask_LightSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), ScatteringTask_ScatteringTableSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), ScatteringTask_CurvatureMapSlot)); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index c39e6068b7..11e5b8d2f5 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -83,7 +83,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ZONE_DEFERRED_TRANSFORM_BUFFER)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ZONE_KEYLIGHT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), ZONE_KEYLIGHT_BUFFER)); gpu::Shader::makeProgram(*program, slotBindings); diff --git a/libraries/render-utils/src/local_lights_drawOutline.slf b/libraries/render-utils/src/local_lights_drawOutline.slf index 56ce1e61a5..38dd383459 100644 --- a/libraries/render-utils/src/local_lights_drawOutline.slf +++ b/libraries/render-utils/src/local_lights_drawOutline.slf @@ -54,26 +54,8 @@ void main(void) { mat4 invViewMat = getViewInverse(); vec4 fragPos = invViewMat * fragPosition; - // From frag world pos find the cluster - vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); - ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - - ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x + cluster.y; - if (numLights <= 0) { - discard; - } - int lightClusterOffset = cluster.z; - - ivec3 dims = frustumGrid.dims.xyz; - if (clusterPos.x < 0 || clusterPos.x >= dims.x) { - discard; - } - - if (clusterPos.y < 0 || clusterPos.y >= dims.y) { - discard; - } - if (clusterPos.z < 0 || clusterPos.z > dims.z) { + <$fetchClusterInfo(fragPos)$>; + if (!hasLocalLights(numLights, clusterPos, dims)) { discard; } @@ -82,6 +64,7 @@ void main(void) { vec3 fragEyeDir = normalize(fragEyeVector.xyz); int numLightTouching = 0; + int lightClusterOffset = cluster.z; for (int i = 0; i < cluster.x; i++) { // Need the light now int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index c3208de726..8ae8f3fb5b 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -17,18 +17,7 @@ <$declareDeferredCurvature()$> -// Everything about light -<@include graphics/Light.slh@> -<$declareLightBuffer(256)$> -<@include LightingModel.slh@> - - -<@include LightPoint.slh@> -<$declareLightingPoint(supportScattering)$> -<@include LightSpot.slh@> -<$declareLightingSpot(supportScattering)$> - -<@include LightClusterGrid.slh@> +<@include LightLocal.slh@> in vec2 _texCoord0; out vec4 _fragColor; @@ -49,28 +38,10 @@ void main(void) { // Frag pos in world mat4 invViewMat = getViewInverse(); - vec4 fragPos = invViewMat * fragPosition; + vec4 fragWorldPos = invViewMat * fragPosition; - // From frag world pos find the cluster - vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); - ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz); - - ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos)); - int numLights = cluster.x + cluster.y; - if (numLights <= 0) { - discard; - } - int lightClusterOffset = cluster.z; - - ivec3 dims = frustumGrid.dims.xyz; - if (clusterPos.x < 0 || clusterPos.x >= dims.x) { - discard; - } - - if (clusterPos.y < 0 || clusterPos.y >= dims.y) { - discard; - } - if (clusterPos.z < 0 || clusterPos.z > dims.z) { + <$fetchClusterInfo(fragWorldPos)$>; + if (!hasLocalLights(numLights, clusterPos, dims)) { discard; } @@ -84,117 +55,11 @@ void main(void) { // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir); - bool withScattering = (frag.scattering * isScatteringEnabled() > 0.0); - int numLightTouching = 0; - for (int i = 0; i < cluster.x; i++) { - // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); - 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; - - 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; - } - - 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; - - updateSurfaceDataWithLight(surface, fragLightDir); - - // Eval attenuation - float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); - vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); - - // Eval shading - if (withScattering) { - evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo - ,frag.scattering, midNormalCurvature, lowNormalCurvature ); - } else { - evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo); - } - - diffuse *= lightEnergy * isDiffuseEnabled(); - specular *= lightEnergy * isSpecularEnabled(); - - _fragColor.rgb += diffuse; - _fragColor.rgb += specular; - } - - for (int i = cluster.x; i < numLights; i++) { - // Need the light now - int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); - 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; - - updateSurfaceDataWithLight(surface, fragLightDir); - - // Eval attenuation - float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); - float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); - vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light); - - // Eval shading - if (withScattering) { - evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo - ,frag.scattering, midNormalCurvature, lowNormalCurvature ); - } else { - evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo); - } - - diffuse *= lightEnergy * isDiffuseEnabled(); - specular *= lightEnergy * isSpecularEnabled(); - - _fragColor.rgb += diffuse; - _fragColor.rgb += specular; - } + _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface, + frag.metallic, frag.fresnel, frag.albedo, frag.scattering, + midNormalCurvature, lowNormalCurvature, 1.0); } diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 0924389dba..761e702595 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -18,6 +18,8 @@ <$declareEvalGlobalLightingAlphaBlended()$> +<@include LightLocal.slh@> + <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> @@ -27,6 +29,7 @@ in vec2 _texCoord0; in vec2 _texCoord1; in vec4 _position; +in vec4 _worldPosition; in vec3 _normal; in vec3 _color; in float _alpha; @@ -56,20 +59,32 @@ void main(void) { <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; vec3 fragPosition = _position.xyz; + // Lighting is done in world space vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, fragPosition, - fragNormal, albedo, fresnel, metallic, emissive, - roughness, opacity), + surface, opacity, localLighting.rgb), opacity); } diff --git a/libraries/render-utils/src/model_translucent.slv b/libraries/render-utils/src/model_translucent.slv new file mode 100644 index 0000000000..305aba06c3 --- /dev/null +++ b/libraries/render-utils/src/model_translucent.slv @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_translucent.slv +// vertex shader +// +// Created by Olivier Prat on 15/01/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out float _alpha; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; +out vec3 _color; + +void main(void) { + _color = colorToLinearRGB(inColor.xyz); + _alpha = inColor.w; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> +} diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index 8ac442476f..a2d271653c 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -18,6 +18,8 @@ <$declareEvalGlobalLightingAlphaBlended()$> +<@include LightLocal.slh@> + <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> @@ -66,20 +68,32 @@ void main(void) { <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; vec3 fragPosition = _position.xyz; + // Lighting is done in world space vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, fragPosition, - fragNormal, albedo, fresnel, metallic, emissive+fadeEmissive, - roughness, opacity), + surface, opacity, localLighting.rgb), opacity); } diff --git a/libraries/render-utils/src/model_translucent_fade.slv b/libraries/render-utils/src/model_translucent_fade.slv new file mode 100644 index 0000000000..3fb9ad2cb4 --- /dev/null +++ b/libraries/render-utils/src/model_translucent_fade.slv @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_translucent_fade.slv +// vertex shader +// +// Created by Olivier Prat on 15/01/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out float _alpha; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; +out vec3 _color; + +void main(void) { + _color = colorToLinearRGB(inColor.xyz); + _alpha = inColor.w; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> +} diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index dcded917b4..b6df71ccc3 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -27,7 +27,7 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { // Need the light now - Light light = getLight(); + Light light = getKeyLight(); vec3 lightDirection = getLightDirection(light); vec3 lightIrradiance = getLightIrradiance(light); diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 64035ac984..c247364a8c 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -27,7 +27,7 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { // Need the light now - Light light = getLight(); + Light light = getKeyLight(); vec3 lightDirection = getLightDirection(light); vec3 lightIrradiance = getLightIrradiance(light); diff --git a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf index ad6918d727..e66d881e11 100644 --- a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf +++ b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf @@ -42,7 +42,7 @@ vec3 evalScatteringBRDF(vec2 texcoord) { vec3 fragNormal = vec3((normal)); // Get light - Light light = getLight(); + Light light = getKeyLight(); vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin float metallic = 0.0; @@ -65,7 +65,7 @@ vec3 drawScatteringTableUV(vec2 cursor, vec2 texcoord) { float curvature = unpackCurvature(diffusedCurvature.w); // Get light - Light light = getLight(); + Light light = getKeyLight(); vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin vec3 fragLightDir = -normalize(getLightDirection(light)); diff --git a/libraries/render-utils/src/zone_drawKeyLight.slf b/libraries/render-utils/src/zone_drawKeyLight.slf index ea11c775b4..5f0f0265d3 100644 --- a/libraries/render-utils/src/zone_drawKeyLight.slf +++ b/libraries/render-utils/src/zone_drawKeyLight.slf @@ -25,7 +25,7 @@ void main(void) { <$evalGlobeWidget()$> - Light light = getLight(); + Light light = getKeyLight(); vec3 lightDirection = normalize(getLightDirection(light)); vec3 lightIrradiance = getLightIrradiance(light); vec3 color = vec3(0.0); diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index eb279f18af..fb58c21dde 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -70,6 +70,8 @@ void ShapePlumber::addPipeline(const Key& key, const gpu::ShaderPointer& program void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state, BatchSetter batchSetter, ItemSetter itemSetter) { + ShapeKey key{ filter._flags }; + gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL)); slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING)); @@ -82,6 +84,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::MAP::EMISSIVE_LIGHTMAP)); slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), Slot::BUFFER::KEY_LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); @@ -89,6 +92,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL)); + if (key.isTranslucent()) { + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + } + gpu::Shader::makeProgram(*program, slotBindings); auto locations = std::make_shared(); @@ -103,14 +112,23 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->skinClusterBufferUnit = program->getUniformBuffers().findLocation("skinClusterBuffer"); locations->materialBufferUnit = program->getUniformBuffers().findLocation("materialBuffer"); locations->texMapArrayBufferUnit = program->getUniformBuffers().findLocation("texMapArrayBuffer"); + locations->keyLightBufferUnit = program->getUniformBuffers().findLocation("keyLightBuffer"); locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer"); locations->hazeParameterBufferUnit = program->getUniformBuffers().findLocation("hazeParametersBuffer"); + if (key.isTranslucent()) { + locations->lightClusterGridBufferUnit = program->getUniformBuffers().findLocation("clusterGridBuffer"); + locations->lightClusterContentBufferUnit = program->getUniformBuffers().findLocation("clusterContentBuffer"); + locations->lightClusterFrustumBufferUnit = program->getUniformBuffers().findLocation("frustumGridBuffer"); + } else { + locations->lightClusterGridBufferUnit = -1; + locations->lightClusterContentBufferUnit = -1; + locations->lightClusterFrustumBufferUnit = -1; + } - ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter, itemSetter); addPipelineHelper(filter, key, 0, shapePipeline); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 9e05cfb81b..1dd9f5da49 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -235,10 +235,15 @@ public: MATERIAL, TEXMAPARRAY, LIGHTING_MODEL, + KEY_LIGHT, LIGHT, LIGHT_AMBIENT_BUFFER, HAZE_MODEL, FADE_PARAMETERS, + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, + LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, + LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, + }; enum MAP { @@ -266,12 +271,16 @@ public: int skinClusterBufferUnit; int materialBufferUnit; int texMapArrayBufferUnit; + int keyLightBufferUnit; int lightBufferUnit; int lightAmbientBufferUnit; int lightAmbientMapUnit; int fadeMaskTextureUnit; int fadeParameterBufferUnit; int hazeParameterBufferUnit; + int lightClusterGridBufferUnit; + int lightClusterContentBufferUnit; + int lightClusterFrustumBufferUnit; }; using LocationsPointer = std::shared_ptr;