diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp index ae3c1f29e2..77906d1857 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -29,33 +29,40 @@ bool StereoDisplayPlugin::isSupported() const { // FIXME make this into a setting that can be adjusted const float DEFAULT_IPD = 0.064f; -const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; + +// Default physical display width (50cm) +const float DEFAULT_SCREEN_WIDTH = 0.5f; + +// Default separation = ipd / screenWidth +const float DEFAULT_SEPARATION = DEFAULT_IPD / DEFAULT_SCREEN_WIDTH; + +// Default convergence depth: where is the screen plane in the virtual space (which depth) +const float DEFAULT_CONVERGENCE = 0.5f; glm::mat4 StereoDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { // Refer to http://www.nvidia.com/content/gtc-2010/pdfs/2010_gtc2010.pdf on creating // stereo projection matrices. Do NOT use "toe-in", use translation. + // Updated version: http://developer.download.nvidia.com/assets/gamedev/docs/Siggraph2011-Stereoscopy_From_XY_to_Z-SG.pdf if (eye == Mono) { // FIXME provide a combined matrix, needed for proper culling return baseProjection; } - float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - float screenZ = 0.25f; // screen projection plane - // FIXME verify this is the right calculation - float frustumshift = HALF_DEFAULT_IPD * nearZ / screenZ; + float frustumshift = DEFAULT_SEPARATION; if (eye == Right) { frustumshift = -frustumshift; } - return glm::translate(baseProjection, vec3(frustumshift, 0, 0)); + + + auto eyeProjection = baseProjection; + eyeProjection[2][0] += frustumshift; + eyeProjection[3][0] += frustumshift * DEFAULT_CONVERGENCE; // include the eye offset here + return eyeProjection; } glm::mat4 StereoDisplayPlugin::getEyePose(Eye eye) const { - float modelviewShift = HALF_DEFAULT_IPD; - if (eye == Left) { - modelviewShift = -modelviewShift; - } - return glm::translate(mat4(), vec3(modelviewShift, 0, 0)); + return mat4(); } std::vector _screenActions; diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 36fa9dccad..e1dc94fcd7 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -56,6 +56,15 @@ void Context::setStereoViews(const mat4 eyeViews[2]) { _backend->setStereoViews(eyeViews); } +void Context::getStereoProjections(mat4* eyeProjections) const { + _backend->getStereoProjections(eyeProjections); +} + +void Context::getStereoViews(mat4* eyeViews) const { + _backend->getStereoViews(eyeViews); +} + + void Context::syncCache() { PROFILE_RANGE(__FUNCTION__); _backend->syncCache(); diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index bda4110921..e0d6c08af6 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -61,6 +61,18 @@ public: } } + void getStereoProjections(mat4* eyeProjections) const { + for (int i = 0; i < 2; ++i) { + eyeProjections[i] = _stereo._eyeProjections[i]; + } + } + + void getStereoViews(mat4* eyeViews) const { + for (int i = 0; i < 2; ++i) { + eyeViews[i] = _stereo._eyeViews[i]; + } + } + virtual void syncCache() = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; @@ -176,6 +188,8 @@ public: bool isStereo(); void setStereoProjections(const mat4 eyeProjections[2]); void setStereoViews(const mat4 eyeViews[2]); + void getStereoProjections(mat4* eyeProjections) const; + void getStereoViews(mat4* eyeViews) const; void syncCache(); // Downloading the Framebuffer is a synchronous action that is not efficient. diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index bd55dee38b..89b8b26a4f 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -11,7 +11,6 @@ <@if not DEFERRED_BUFFER_SLH@> <@def DEFERRED_BUFFER_SLH@> -uniform bool stereoMode = false; // the diffuse texture uniform sampler2D diffuseMap; @@ -25,17 +24,38 @@ uniform sampler2D specularMap; // the depth texture uniform sampler2D depthMap; -// the distance to the near clip plane -uniform float near; -// scale factor for depth: (far - near) / far -uniform float depthScale; +struct DeferredTransform { + mat4 projection; + mat4 viewInverse; -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; + vec4 stereoSide_spareABC; +}; + +layout(std140) uniform deferredTransformBuffer { + DeferredTransform _deferredTransform; +}; +DeferredTransform getDeferredTransform() { + return _deferredTransform; +} -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; +bool getStereoMode(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide_spareABC.x != 0.0); +} +float getStereoSide(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide_spareABC.x); +} + +vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { + vec3 nPos = vec3(texcoord.xy * 2.0f - 1.0f, depthVal * 2.0f - 1.0f); + + // compute the view space position using the depth + // basically manually pick the proj matrix components to do the inverse + float Ze = -deferredTransform.projection[3][2] / (nPos.z + deferredTransform.projection[2][2]); + float Xe = (-Ze * nPos.x - Ze * deferredTransform.projection[2][0] - deferredTransform.projection[3][0]) / deferredTransform.projection[0][0]; + float Ye = (-Ze * nPos.y - Ze * deferredTransform.projection[2][1] - deferredTransform.projection[3][1]) / deferredTransform.projection[1][1]; + return vec4(Xe, Ye, Ze, 1.0f); +} struct DeferredFragment { float depthVal; @@ -50,22 +70,20 @@ struct DeferredFragment { float gloss; }; -DeferredFragment unpackDeferredFragment(vec2 texcoord) { +DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) { DeferredFragment frag; frag.depthVal = texture(depthMap, texcoord).r; frag.normalVal = texture(normalMap, texcoord); frag.diffuseVal = texture(diffuseMap, texcoord); frag.specularVal = texture(specularMap, texcoord); - if (stereoMode) { + if (getStereoMode(deferredTransform)) { if (texcoord.x > 0.5) { texcoord.x -= 0.5; } texcoord.x *= 2.0; } - // compute the view space position using the depth - float z = near / (frag.depthVal * depthScale - 1.0); - frag.position = vec4((depthTexCoordOffset + texcoord * depthTexCoordScale) * z, z, 1.0); + frag.position = evalEyePositionFromZ(deferredTransform, frag.depthVal, texcoord); // Unpack the normal from the map frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); @@ -78,4 +96,5 @@ DeferredFragment unpackDeferredFragment(vec2 texcoord) { return frag; } + <@endif@> diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index fe8e74361a..e3ea1287d9 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -13,6 +13,8 @@ <@include DeferredLighting.slh@> +<@func declareSkyboxMap()@> + uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { @@ -22,6 +24,9 @@ vec4 evalSkyboxLight(vec3 direction, float lod) { return skytexel; } +<@endfunc@> + +<@func declareSphericalHarmonics()@> struct SphericalHarmonics { vec4 L00; vec4 L1m1; @@ -59,13 +64,13 @@ vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { // Need one SH uniform SphericalHarmonics ambientSphere; +<@endfunc@> + // Everything about light <@include model/Light.slh@> -// The view Matrix -uniform mat4 invViewMat; - -vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { +<@func declareEvalAmbientGlobalColor()@> +vec3 evalAmbienGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); @@ -82,7 +87,13 @@ vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, return color; } -vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { +<@endfunc@> + +<@func declareEvalAmbientSphereGlobalColor()@> + +<$declareSphericalHarmonics()$> + +vec3 evalAmbienSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); @@ -99,8 +110,14 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no return color; } +<@endfunc@> -vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { +<@func declareEvalSkyboxGlobalColor()@> + +<$declareSkyboxMap()$> +<$declareSphericalHarmonics()$> + +vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); @@ -116,8 +133,10 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, return color; } +<@endfunc@> -vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { +<@func declareEvalLightmappedColor()@> +vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); @@ -141,5 +160,6 @@ vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, ve return diffuse * (ambientLight + diffuseLight); } +<@endfunc@> <@endif@> diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index bb37a9e3e8..888742bb18 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -11,6 +11,8 @@ <@if not DEFERRED_LIGHTING_SLH@> <@def DEFERRED_LIGHTING_SLH@> + +<@func declareEvalPBRShading()@> // Frag Shading returns the diffuse amount as W and the specular rgb as xyz vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { // Diffuse Lighting @@ -33,6 +35,9 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 sp return vec4(reflect, diffuse); } +<@endfunc@> + +<@func declareEvalBlinnRShading()@> vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { // Diffuse Lighting @@ -49,6 +54,12 @@ vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 return vec4(reflect, diffuse); } +<@endfunc@> + + +<$declareEvalPBRShading()$> + + vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { /*if (gl_FragCoord.x > 1000) { diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 67ad3483c7..0ec8b4ad24 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -53,18 +53,13 @@ static const std::string glowIntensityShaderHandle = "glowIntensity"; struct LightLocations { int shadowDistances; int shadowScale; - int nearLocation; - int depthScale; - int depthTexCoordOffset; - int depthTexCoordScale; int radius; int ambientSphere; int lightBufferUnit; int atmosphereBufferUnit; - int invViewMat; int texcoordMat; int coneParam; - int stereo; + int deferredTransformBuffer; }; static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); @@ -277,6 +272,13 @@ gpu::FramebufferPointer _copyFBO; void DeferredLightingEffect::render(RenderArgs* args) { gpu::Batch batch; + // Allocate the parameters buffer used by all the deferred shaders + if (!_deferredTransformBuffer[0]._buffer) { + DeferredTransform parameters; + _deferredTransformBuffer[0] = gpu::BufferView(std::make_shared(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters)); + _deferredTransformBuffer[1] = gpu::BufferView(std::make_shared(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters)); + } + // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); @@ -289,296 +291,289 @@ void DeferredLightingEffect::render(RenderArgs* args) { _copyFBO = framebufferCache->getFramebuffer(); batch.setFramebuffer(_copyFBO); + // Clearing it batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); - - batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); + // BInd the G-Buffer surfaces + batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); batch.setResourceTexture(1, framebufferCache->getPrimaryNormalTexture()); - batch.setResourceTexture(2, framebufferCache->getPrimarySpecularTexture()); - batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture()); - + + // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) + auto monoViewport = args->_viewport; float sMin = args->_viewport.x / (float)framebufferSize.width(); float sWidth = args->_viewport.z / (float)framebufferSize.width(); float tMin = args->_viewport.y / (float)framebufferSize.height(); float tHeight = args->_viewport.w / (float)framebufferSize.height(); - bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap()); + // The view frustum is the mono frustum base + auto viewFrustum = args->_viewFrustum; - // Fetch the ViewMatrix; - glm::mat4 invViewMat; - invViewMat = args->_viewFrustum->getView(); + // Eval the mono projection + mat4 monoProjMat; + viewFrustum->evalProjectionMatrix(monoProjMat); - auto& program = _directionalLight; - LightLocationsPtr locations = _directionalLightLocations; + // The mono view transform + Transform monoViewTransform; + viewFrustum->evalViewTransform(monoViewTransform); - // FIXME: Note: we've removed the menu items to enable shadows, so this will always be false for now. - // When we add back shadow support, this old approach may likely be removed and completely replaced - // but I've left it in for now. - bool shadowsEnabled = false; - bool cascadeShadowsEnabled = false; - - if (shadowsEnabled) { - batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer()); - - program = _directionalLightShadowMap; - locations = _directionalLightShadowMapLocations; - if (cascadeShadowsEnabled) { - program = _directionalLightCascadedShadowMap; - locations = _directionalLightCascadedShadowMapLocations; - if (useSkyboxCubemap) { - program = _directionalSkyboxLightCascadedShadowMap; - locations = _directionalSkyboxLightCascadedShadowMapLocations; - } else if (_ambientLightMode > -1) { - program = _directionalAmbientSphereLightCascadedShadowMap; - locations = _directionalAmbientSphereLightCascadedShadowMapLocations; - } - batch.setPipeline(program); - batch._glUniform3fv(locations->shadowDistances, 1, (const float*) &_viewState->getShadowDistances()); - - } else { - if (useSkyboxCubemap) { - program = _directionalSkyboxLightShadowMap; - locations = _directionalSkyboxLightShadowMapLocations; - } else if (_ambientLightMode > -1) { - program = _directionalAmbientSphereLightShadowMap; - locations = _directionalAmbientSphereLightShadowMapLocations; - } - batch.setPipeline(program); + // THe mono view matrix coming from the mono view transform + glm::mat4 monoViewMat; + monoViewTransform.getMatrix(monoViewMat); + + // Running in stero ? + bool isStereo = args->_context->isStereo(); + int numPasses = 1; + + mat4 projMats[2]; + Transform viewTransforms[2]; + ivec4 viewports[2]; + vec4 clipQuad[2]; + vec2 screenBottomLeftCorners[2]; + vec2 screenTopRightCorners[2]; + vec4 fetchTexcoordRects[2]; + + DeferredTransform deferredTransforms[2]; + auto geometryCache = DependencyManager::get(); + + if (isStereo) { + numPasses = 2; + + mat4 eyeViews[2]; + args->_context->getStereoProjections(projMats); + args->_context->getStereoViews(eyeViews); + + float halfWidth = 0.5 * sWidth; + + for (int i = 0; i < numPasses; i++) { + // In stereo, the 2 sides are layout side by side in the mono viewport and their width is half + int sideWidth = monoViewport.z >> 1; + viewports[i] = ivec4(monoViewport.x + (i * sideWidth), monoViewport.y, sideWidth, monoViewport.w); + + deferredTransforms[i].projection = projMats[i]; + + auto sideViewMat = eyeViews[i] * monoViewMat; + viewTransforms[i].evalFromRawMatrix(sideViewMat); + deferredTransforms[i].viewInverse = sideViewMat; + + deferredTransforms[i].stereoSide = (i == 0 ? -1.0f : 1.0f); + + clipQuad[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight); + screenBottomLeftCorners[i] = glm::vec2(-1.0f + i * 1.0f, -1.0f); + screenTopRightCorners[i] = glm::vec2(i * 1.0f, 1.0f); + + fetchTexcoordRects[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight); } - batch._glUniform1f(locations->shadowScale, 1.0f / framebufferCache->getShadowFramebuffer()->getWidth()); - } else { - if (useSkyboxCubemap) { - program = _directionalSkyboxLight; - locations = _directionalSkyboxLightLocations; - } else if (_ambientLightMode > -1) { - program = _directionalAmbientSphereLight; - locations = _directionalAmbientSphereLightLocations; - } - batch.setPipeline(program); + + viewports[0] = monoViewport; + projMats[0] = monoProjMat; + + deferredTransforms[0].projection = monoProjMat; + deferredTransforms[0].viewInverse = monoViewMat; + deferredTransforms[0].stereoSide = 0.0f; + + clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight); + screenBottomLeftCorners[0] = glm::vec2(-1.0f, -1.0f); + screenTopRightCorners[0] = glm::vec2(1.0f, 1.0f); + + fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight); } - { // Setup the global lighting - auto globalLight = _allocatedLights[_globalLights.front()]; - - if (locations->ambientSphere >= 0) { - gpu::SphericalHarmonics sh = globalLight->getAmbientSphere(); - if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) { - sh = (*_skybox->getCubemap()->getIrradiance()); - } - for (int i =0; i ambientSphere + i, 1, (const float*) (&sh) + i * 4); - } - } - - if (useSkyboxCubemap) { - batch.setResourceTexture(5, _skybox->getCubemap()); - } + auto eyePoint = viewFrustum->getPosition(); + float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft()); - if (locations->lightBufferUnit >= 0) { - batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); - } - - if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { - batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); - } - batch._glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); - } - float left, right, bottom, top, nearVal, farVal; - glm::vec4 nearClipPlane, farClipPlane; - args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + for (int side = 0; side < numPasses; side++) { + // Render in this side's viewport + batch.setViewportTransform(viewports[side]); + batch.setStateScissorRect(viewports[side]); - batch._glUniform1f(locations->nearLocation, nearVal); + // Sync and Bind the correct DeferredTransform ubo + _deferredTransformBuffer[side]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[side]); + batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, _deferredTransformBuffer[side]); - float depthScale = (farVal - nearVal) / farVal; - batch._glUniform1f(locations->depthScale, depthScale); - - float nearScale = -1.0f / nearVal; - float depthTexCoordScaleS = (right - left) * nearScale / sWidth; - float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; - float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; - float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; - batch._glUniform2f(locations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); - batch._glUniform2f(locations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - bool stereo = args->_context->isStereo(); - batch._glUniform1f(locations->stereo, stereo ? 1 : 0); - - { - Transform model; - model.setTranslation(glm::vec3(sMin, tMin, 0.0)); - model.setScale(glm::vec3(sWidth, tHeight, 1.0)); - batch.setModelTransform(model); - - batch.setProjectionTransform(glm::mat4()); - batch.setViewTransform(Transform()); - - glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); glm::vec2 topLeft(-1.0f, -1.0f); glm::vec2 bottomRight(1.0f, 1.0f); - glm::vec2 texCoordTopLeft(sMin, tMin); - glm::vec2 texCoordBottomRight(sMin + sWidth, tMin + tHeight); + glm::vec2 texCoordTopLeft(clipQuad[side].x, clipQuad[side].y); + glm::vec2 texCoordBottomRight(clipQuad[side].x + clipQuad[side].z, clipQuad[side].y + clipQuad[side].w); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); - } + // First Global directional light and ambient pass + { + bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap()); - if (useSkyboxCubemap) { - batch.setResourceTexture(5, nullptr); - } + auto& program = _directionalLight; + LightLocationsPtr locations = _directionalLightLocations; - if (shadowsEnabled) { - batch.setResourceTexture(4, nullptr); - } - - glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); - glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); - auto texcoordMat = glm::mat4(); - texcoordMat[0] = glm::vec4(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); - texcoordMat[1] = glm::vec4(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); - texcoordMat[2] = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); - texcoordMat[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - - // enlarge the scales slightly to account for tesselation - const float SCALE_EXPANSION = 0.05f; - - auto eyePoint = args->_viewFrustum->getPosition(); - float nearRadius = glm::distance(eyePoint, args->_viewFrustum->getNearTopLeft()); - - auto geometryCache = DependencyManager::get(); - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - if (!_pointLights.empty()) { - batch.setPipeline(_pointLight); - batch._glUniform1f(_pointLightLocations->nearLocation, nearVal); - batch._glUniform1f(_pointLightLocations->depthScale, depthScale); - batch._glUniform2f(_pointLightLocations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); - batch._glUniform2f(_pointLightLocations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - - batch._glUniformMatrix4fv(_pointLightLocations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); - - batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); - - for (auto lightID : _pointLights) { - auto& light = _allocatedLights[lightID]; - // IN DEBUG: light->setShowContour(true); - if (_pointLightLocations->lightBufferUnit >= 0) { - batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); + // TODO: At some point bring back the shadows... + // Setup the global directional pass pipeline + { + if (useSkyboxCubemap) { + program = _directionalSkyboxLight; + locations = _directionalSkyboxLightLocations; + } else if (_ambientLightMode > -1) { + program = _directionalAmbientSphereLight; + locations = _directionalAmbientSphereLightLocations; + } + batch.setPipeline(program); } - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, - // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { - Transform model; - model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); - batch.setModelTransform(model); - batch.setViewTransform(Transform()); + { // Setup the global lighting + auto globalLight = _allocatedLights[_globalLights.front()]; + + if (locations->ambientSphere >= 0) { + gpu::SphericalHarmonics sh = globalLight->getAmbientSphere(); + if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) { + sh = (*_skybox->getCubemap()->getIrradiance()); + } + for (int i =0; i ambientSphere + i, 1, (const float*) (&sh) + i * 4); + } + } + + if (useSkyboxCubemap) { + batch.setResourceTexture(5, _skybox->getCubemap()); + } + + if (locations->lightBufferUnit >= 0) { + batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); + } + + if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { + batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); + } + } + + { + batch.setModelTransform(Transform()); batch.setProjectionTransform(glm::mat4()); + batch.setViewTransform(Transform()); glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - glm::vec2 topLeft(-1.0f, -1.0f); - glm::vec2 bottomRight(1.0f, 1.0f); - glm::vec2 texCoordTopLeft(sMin, tMin); - glm::vec2 texCoordBottomRight(sMin + sWidth, tMin + tHeight); + geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); + } - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - } else { - Transform model; - model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); - batch.setModelTransform(model); - geometryCache->renderSphere(batch, expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + if (useSkyboxCubemap) { + batch.setResourceTexture(5, nullptr); } } - _pointLights.clear(); - } - - if (!_spotLights.empty()) { - batch.setPipeline(_spotLight); - batch._glUniform1f(_spotLightLocations->nearLocation, nearVal); - batch._glUniform1f(_spotLightLocations->depthScale, depthScale); - batch._glUniform2f(_spotLightLocations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); - batch._glUniform2f(_spotLightLocations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - - batch._glUniformMatrix4fv(_spotLightLocations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat)); - batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); + auto texcoordMat = glm::mat4(); + /* texcoordMat[0] = glm::vec4(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); + texcoordMat[1] = glm::vec4(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); + */ texcoordMat[0] = glm::vec4(fetchTexcoordRects[side].z / 2.0f, 0.0f, 0.0f, fetchTexcoordRects[side].x + fetchTexcoordRects[side].z / 2.0f); + texcoordMat[1] = glm::vec4(0.0f, fetchTexcoordRects[side].w / 2.0f, 0.0f, fetchTexcoordRects[side].y + fetchTexcoordRects[side].w / 2.0f); + texcoordMat[2] = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); + texcoordMat[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - for (auto lightID : _spotLights) { - auto light = _allocatedLights[lightID]; - // IN DEBUG: light->setShowContour(true); + // enlarge the scales slightly to account for tesselation + const float SCALE_EXPANSION = 0.05f; - batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); - auto eyeLightPos = eyePoint - light->getPosition(); - auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection()); + batch.setProjectionTransform(projMats[side]); + batch.setViewTransform(viewTransforms[side]); - const float TANGENT_LENGTH_SCALE = 0.666f; - glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f); + // Splat Point lights + if (!_pointLights.empty()) { + batch.setPipeline(_pointLight); - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, - // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... - if ((eyeHalfPlaneDistance > -nearRadius) && - (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) { - coneParam.w = 0.0f; - batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); + batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); - Transform model; - model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); - batch.setModelTransform(model); - batch.setViewTransform(Transform()); - batch.setProjectionTransform(glm::mat4()); + for (auto lightID : _pointLights) { + auto& light = _allocatedLights[lightID]; + // IN DEBUG: light->setShowContour(true); + if (_pointLightLocations->lightBufferUnit >= 0) { + batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); + } + + float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); + // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, + // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... + if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { + Transform model; + model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); + batch.setModelTransform(model); + batch.setViewTransform(Transform()); + batch.setProjectionTransform(glm::mat4()); + + glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); - glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - glm::vec2 topLeft(-1.0f, -1.0f); - glm::vec2 bottomRight(1.0f, 1.0f); - glm::vec2 texCoordTopLeft(sMin, tMin); - glm::vec2 texCoordBottomRight(sMin + sWidth, tMin + tHeight); - - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - } else { - coneParam.w = 1.0f; - batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); - - Transform model; - model.setTranslation(light->getPosition()); - model.postRotate(light->getOrientation()); - model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); - - batch.setModelTransform(model); - auto mesh = getSpotLightMesh(); - - - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputBuffer(0, mesh->getVertexBuffer()); - batch.setInputFormat(mesh->getVertexFormat()); - - auto& part = mesh->getPartBuffer().get(); - - batch.drawIndexed(model::Mesh::topologyToPrimitive(part._topology), part._numIndices, part._startIndex); + batch.setProjectionTransform(projMats[side]); + batch.setViewTransform(viewTransforms[side]); + } else { + Transform model; + model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); + batch.setModelTransform(model); + geometryCache->renderSphere(batch, expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + } } } - _spotLights.clear(); - } + // Splat spot lights + if (!_spotLights.empty()) { + batch.setPipeline(_spotLight); + + batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); + + for (auto lightID : _spotLights) { + auto light = _allocatedLights[lightID]; + // IN DEBUG: light->setShowContour(true); + + batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); + + auto eyeLightPos = eyePoint - light->getPosition(); + auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection()); + + const float TANGENT_LENGTH_SCALE = 0.666f; + glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f); + + float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); + // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, + // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... + if ((eyeHalfPlaneDistance > -nearRadius) && + (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) { + coneParam.w = 0.0f; + batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); + + Transform model; + model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); + batch.setModelTransform(model); + batch.setViewTransform(Transform()); + batch.setProjectionTransform(glm::mat4()); + + glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); + + batch.setProjectionTransform( projMats[side]); + batch.setViewTransform(viewTransforms[side]); + } else { + coneParam.w = 1.0f; + batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); + + Transform model; + model.setTranslation(light->getPosition()); + model.postRotate(light->getOrientation()); + model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); + + batch.setModelTransform(model); + auto mesh = getSpotLightMesh(); + + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + + auto& part = mesh->getPartBuffer().get(); + + batch.drawIndexed(model::Mesh::topologyToPrimitive(part._topology), part._numIndices, part._startIndex); + } + } + } + } + // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target batch.setResourceTexture(0, nullptr); batch.setResourceTexture(1, nullptr); @@ -588,6 +583,12 @@ void DeferredLightingEffect::render(RenderArgs* args) { args->_context->render(batch); // End of the Lighting pass + if (!_pointLights.empty()) { + _pointLights.clear(); + } + if (!_spotLights.empty()) { + _spotLights.clear(); + } } @@ -648,23 +649,22 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo const int ATMOSPHERE_GPU_SLOT = 4; slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), DeferredLightingEffect::DEFERRED_TRANSFORM_BUFFER_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); - locations->stereo = program->getUniforms().findLocation("stereoMode"); locations->shadowDistances = program->getUniforms().findLocation("shadowDistances"); locations->shadowScale = program->getUniforms().findLocation("shadowScale"); - locations->nearLocation = program->getUniforms().findLocation("near"); - locations->depthScale = program->getUniforms().findLocation("depthScale"); - locations->depthTexCoordOffset = program->getUniforms().findLocation("depthTexCoordOffset"); - locations->depthTexCoordScale = program->getUniforms().findLocation("depthTexCoordScale"); + locations->radius = program->getUniforms().findLocation("radius"); locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); - locations->invViewMat = program->getUniforms().findLocation("invViewMat"); + locations->texcoordMat = program->getUniforms().findLocation("texcoordMat"); locations->coneParam = program->getUniforms().findLocation("coneParam"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); locations->atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit"); + locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer"); auto state = std::make_shared(); if (lightVolume) { diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 8f25782308..ea6f2f0ce0 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -32,6 +32,7 @@ class DeferredLightingEffect : public Dependency { public: static const int NORMAL_FITTING_MAP_SLOT = 10; + static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; void init(AbstractViewStateInterface* viewState); @@ -78,7 +79,7 @@ public: void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } void setGlobalSkybox(const model::SkyboxPointer& skybox); - + private: DeferredLightingEffect() {} virtual ~DeferredLightingEffect() { } @@ -151,6 +152,19 @@ private: int _ambientLightMode = 0; model::AtmospherePointer _atmosphere; model::SkyboxPointer _skybox; + + // Class describing the uniform buffer with all the parameters common to the deferred shaders + class DeferredTransform { + public: + glm::mat4 projection; + glm::mat4 viewInverse; + float stereoSide{ 0.f }; + float spareA, spareB, spareC; + + DeferredTransform() {} + }; + typedef gpu::BufferView UniformBufferView; + UniformBufferView _deferredTransformBuffer[2]; }; class SimpleProgramKey { diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index decb434177..525abf60b7 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -111,7 +111,7 @@ float evalShadowAttenuation(vec4 shadowTexcoord) { return evalShadowAttenuationBasic(shadowTexcoord); } - + <@endif@> diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 10de6a1101..52ecc71a14 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -17,30 +17,34 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientSphereGlobalColor()$> + in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); - + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, 1.0, frag.normal, frag.diffuse, frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienSphereGlobalColor(1.0, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - + vec3 color = evalAmbienSphereGlobalColor( + deferredTransform.viewInverse, + 1.0, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf index ff8e6aa91c..8b0212636e 100755 --- a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf @@ -17,6 +17,9 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientSphereGlobalColor()$> + // Everything about shadow <@include Shadow.slh@> @@ -24,7 +27,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -32,20 +36,22 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, shadowAttenuation, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - + vec3 color = evalAmbienSphereGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf index d446d4edb2..2dee8bf9b9 100755 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf @@ -16,6 +16,8 @@ <@include DeferredBuffer.slh@> <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientSphereGlobalColor()$> // Everything about shadow <@include Shadow.slh@> @@ -24,7 +26,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -32,20 +35,22 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, shadowAttenuation, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - + vec3 color = evalAmbienSphereGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 2e0334406e..22b0157762 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -17,28 +17,34 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientGlobalColor()$> + in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4( evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, 1.0, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienGlobalColor(1.0, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); - + vec3 color = evalAmbienGlobalColor( + deferredTransform.viewInverse, + 1.0, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index bfc42db9bc..4abe8e2e9d 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -17,6 +17,9 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientGlobalColor()$> + // Everything about shadow <@include Shadow.slh@> @@ -24,7 +27,9 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -32,14 +37,17 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, shadowAttenuation, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienGlobalColor(shadowAttenuation, + vec3 color = evalAmbienGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, frag.position.xyz, frag.normal, frag.diffuse, diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf index 951aeab122..b3362a2040 100644 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_shadow_map.slf @@ -17,6 +17,9 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientGlobalColor()$> + // Everything about shadow <@include Shadow.slh@> @@ -24,7 +27,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -32,19 +36,22 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, shadowAttenuation, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienGlobalColor(shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); + vec3 color = evalAmbienGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index cd95369395..ca3efef047 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -3,43 +3,48 @@ // Generated on <$_SCRIBE_DATE$> // // directional_light.frag -// fragment shader + // Everything about deferred buffer <@include DeferredBuffer.slh@> <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalSkyboxGlobalColor()$> + in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); - + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, 1.0, frag.normal, frag.diffuse, frag.specularVal.xyz); - _fragColor = vec4(color, 1.0); } else { - vec3 color = evalSkyboxGlobalColor(1.0, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); + vec3 color = evalSkyboxGlobalColor( + deferredTransform.viewInverse, + 1.0, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf index 171d3fa996..3c09bf62b6 100755 --- a/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf @@ -17,6 +17,9 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalSkyboxGlobalColor()$> + // Everything about shadow <@include Shadow.slh@> @@ -24,7 +27,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); @@ -32,19 +36,23 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( - shadowAttenuation, - frag.normal, - frag.diffuse, - frag.specularVal.xyz), - 1.0); + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz); + + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalSkyboxGlobalColor(shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); + vec3 color = evalSkyboxGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf index aa4206bce9..632270476b 100755 --- a/libraries/render-utils/src/directional_skybox_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow_map.slf @@ -17,6 +17,9 @@ <@include DeferredGlobalLight.slh@> +<$declareEvalLightmappedColor()$> +<$declareEvalSkyboxGlobalColor()$> + // Everything about shadow <@include Shadow.slh@> @@ -24,7 +27,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { - DeferredFragment frag = unpackDeferredFragment(_texCoord0); + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); // Eval shadow Texcoord and then Attenuation vec4 shadowTexcoord = evalShadowTexcoord(frag.position); @@ -32,19 +36,22 @@ void main(void) { // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { - _fragColor = vec4(evalLightmappedColor( + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, shadowAttenuation, frag.normal, frag.diffuse, - frag.specularVal.xyz), - 1.0); + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); } else { - vec3 color = evalSkyboxGlobalColor(shadowAttenuation, - frag.position.xyz, - frag.normal, - frag.diffuse, - frag.specular, - frag.gloss); + vec3 color = evalSkyboxGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 528e6e9d96..e9045e18c5 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -21,17 +21,19 @@ // Everything about light <@include model/Light.slh@> -// The view Matrix -uniform mat4 invViewMat; in vec4 _texCoord0; out vec4 _fragColor; void main(void) { + DeferredTransform deferredTransform = getDeferredTransform(); + // Grab the fragment data from the uv vec2 texCoord = _texCoord0.st / _texCoord0.q; - DeferredFragment frag = unpackDeferredFragment(texCoord); - + DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + + mat4 invViewMat = deferredTransform.viewInverse; + // Kill if in front of the light volume float depth = frag.depthVal; if (depth < gl_FragCoord.z) { diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 6510ee612c..73b081260e 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -21,16 +21,17 @@ // Everything about light <@include model/Light.slh@> -// The view Matrix -uniform mat4 invViewMat; - in vec4 _texCoord0; out vec4 _fragColor; void main(void) { + DeferredTransform deferredTransform = getDeferredTransform(); + // Grab the fragment data from the uv vec2 texCoord = _texCoord0.st / _texCoord0.q; - DeferredFragment frag = unpackDeferredFragment(texCoord); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + + mat4 invViewMat = deferredTransform.viewInverse; // Kill if in front of the light volume float depth = frag.depthVal;