From b81dfefbebea104da9a02b0461301f0e4853f00a Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 3 Sep 2016 12:08:53 -0700 Subject: [PATCH] pack all the lights in a single buffer and shade the opaque with a single full screen path --- libraries/model/src/model/Light.slh | 5 + .../src/DeferredLightingEffect.cpp | 62 +++++++++++-- .../render-utils/src/DeferredLightingEffect.h | 2 + .../render-utils/src/deferred_light_spot.slv | 8 +- libraries/render-utils/src/spot_light.slf | 92 +++++++++++-------- 5 files changed, 123 insertions(+), 46 deletions(-) diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 59e986e14a..2b6e55cf7e 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -60,6 +60,11 @@ struct Light { SphericalHarmonics _ambientSphere; }; +const int LIGHT_SPOT = 2; + +bool light_isSpot(Light l) { + return bool(l._control.y >= 2.f); +} vec3 getLightPosition(Light l) { return l._position.xyz; } vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 30b7f83072..b7e34095c1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -97,7 +97,7 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); - loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); + loadLightProgram(deferred_light_vert, spot_light_frag, false, _spotLight, _spotLightLocations); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _allocatedLights.push_back(std::make_shared()); @@ -571,6 +571,11 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c } +RenderDeferredLocals::RenderDeferredLocals() : +_spotLightsBuffer(std::make_shared()) { + +} + void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, @@ -585,6 +590,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } auto args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + // Framebuffer copy operations cannot function as multipass stereo operations. + batch.enableStereo(false); // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto viewport = args->_viewport; @@ -609,9 +616,46 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewTransform, true); + // batch.setProjectionTransform(projMat); + // batch.setViewTransform(viewTransform, true); + // gather lights + auto& srcPointLights = deferredLightingEffect->_pointLights; + auto& srcSpotLights = deferredLightingEffect->_spotLights; + std::vector lightIndices(srcPointLights.size() + srcSpotLights.size() + 1); + lightIndices[0] = 0; + + if (points && !srcPointLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int)); + lightIndices[0] += srcPointLights.size(); + } + if (spots && !srcSpotLights.empty()) { + memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int)); + lightIndices[0] += srcSpotLights.size(); + } + + if (lightIndices[0] > 0) { + _spotLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); + _spotLightsBuffer._size = lightIndices.size() * sizeof(int); + + // Spot light pipeline + batch.setPipeline(deferredLightingEffect->_spotLight); + batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); + + // Spot mesh + auto mesh = deferredLightingEffect->getSpotLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& conePart = mesh->getPartBuffer().get(0); + + + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); + // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + /* // Splat Point lights if (points && !deferredLightingEffect->_pointLights.empty()) { // POint light pipeline @@ -645,9 +689,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, // Splat spot lights if (spots && !deferredLightingEffect->_spotLights.empty()) { - - - _spotLightsBuffer._buffer->setData(deferredLightingEffect->_spotLights.size() * sizeof(int), (const gpu::Byte*) deferredLightingEffect->_spotLights.data()); + std::vector again(deferredLightingEffect->_spotLights.size() + 1); + again[0] = deferredLightingEffect->_spotLights.size(); + memcpy(again.data() + 1, deferredLightingEffect->_spotLights.data(), deferredLightingEffect->_spotLights.size() * sizeof(int)); + _spotLightsBuffer._buffer->setData(again.size() * sizeof(int), (const gpu::Byte*) again.data()); + _spotLightsBuffer._size = again.size() * sizeof(int); // Spot light pipeline batch.setPipeline(deferredLightingEffect->_spotLight); @@ -663,7 +709,9 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer); - batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + // batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); + + batch.draw(gpu::TRIANGLE_STRIP, 4); /* for (auto lightID : deferredLightingEffect->_spotLights) { auto light = deferredLightingEffect->getLightStage().getLight(lightID); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 018ff698eb..1d0eb1cb15 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -161,6 +161,8 @@ public: gpu::BufferView _spotLightsBuffer; + RenderDeferredLocals(); + }; diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index b05e9719f4..e99142d8ea 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -21,12 +21,16 @@ <@include model/Light.slh@> <$declareLightBuffer(32)$> +uniform lightIndexBuffer { + int lightIndex[32]; +}; out vec4 _texCoord0; +flat out int instanceID; void main(void) { vec4 coneVertex = inPosition; - - Light light = getLight(gl_InstanceID); + instanceID = lightIndex[gl_InstanceID]; + Light light = getLight(instanceID); vec3 lightPos = getLightPosition(light); vec4 coneParam = getLightVolumeGeometry(light); diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 08d8589706..7e1ed9d01e 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -20,75 +20,93 @@ // Everything about light <@include model/Light.slh@> <$declareLightBuffer(32)$> - +uniform lightIndexBuffer { + int lightIndex[32]; +}; <@include LightingModel.slh@> +<@include LightPoint.slh@> +<$declareLightingPoint(supportScattering)$> <@include LightSpot.slh@> <$declareLightingSpot(supportScattering)$> -uniform vec4 texcoordFrameTransform; +//uniform vec4 texcoordFrameTransform; in vec4 _texCoord0; +//flat in int instanceID; out vec4 _fragColor; void main(void) { // DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); // Grab the fragment data from the uv - vec2 texCoord = _texCoord0.st / _texCoord0.q; + vec2 texCoord = _texCoord0.st;/* / _texCoord0.q; texCoord *= texcoordFrameTransform.zw; - texCoord += texcoordFrameTransform.xy; + texCoord += texcoordFrameTransform.xy;*/ vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord); - - // Need the light now - Light light = getLight(0); - - // Frag pos in world - mat4 invViewMat = getViewInverse(); - vec4 fragPos = invViewMat * fragPosition; - - // 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 (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { - discard; - } - - // _fragColor.rgb = vec3(0.0, 1.0, 1.0); - // return; - DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord); - // frag.depthVal = depthValue; - frag.position = fragPosition; if (frag.mode == FRAG_MODE_UNLIT) { discard; } - // Frag to eye vec - vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); - vec3 fragEyeDir = normalize(fragEyeVector.xyz); + // frag.depthVal = depthValue; + frag.position = fragPosition; - vec3 diffuse; - vec3 specular; vec4 midNormalCurvature; vec4 lowNormalCurvature; if (frag.mode == FRAG_MODE_SCATTERING) { unpackMidLowNormalCurvature(texCoord, 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); - _fragColor.rgb += diffuse; - _fragColor.rgb += specular; + // Frag pos in world + mat4 invViewMat = getViewInverse(); + vec4 fragPos = invViewMat * fragPosition; - // _fragColor.rgb = vec3(0.0, 1.0, 1.0); + // Frag to eye vec + vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); + vec3 fragEyeDir = normalize(fragEyeVector.xyz); + + int numLights = lightIndex[0]; + for (int i = 0; i < numLights; i++) { + // Need the light now + Light light = getLight(lightIndex[i + 1]); + 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 (isSpot) { + if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) { + continue; + } + } else { + if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) { + continue; + } + } + + 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); + } + + _fragColor.rgb += diffuse; + _fragColor.rgb += specular; + } }