From e72791233db1fd200ecee452bc99b34b4276101f Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Sep 2016 18:08:36 -0700 Subject: [PATCH] overall clean up of th elocal light drawing to avoid the in/out pipeline case, still seeing big cost on gpu from the spot lights --- libraries/model/src/model/Light.cpp | 2 +- .../src/DeferredLightingEffect.cpp | 130 +++++++++--------- .../render-utils/src/DeferredLightingEffect.h | 2 + libraries/render-utils/src/LightPoint.slh | 4 +- libraries/render-utils/src/LightSpot.slh | 2 +- .../src/deferred_light_limited.slv | 24 ++-- .../render-utils/src/deferred_light_spot.slv | 61 +++----- libraries/render-utils/src/spot_light.slf | 2 + 8 files changed, 107 insertions(+), 120 deletions(-) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 4421864569..c073e397dd 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -167,7 +167,7 @@ void Light::setAmbientMapNumMips(uint16_t numMips) { void Light::updateVolumeGeometry() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, 1.0f); // getMaximumRadius() * (1.0f + SCALE_EXPANSION)); + glm::vec4 volumeGeometry(0.0f, 0.0f, 0.0f, getMaximumRadius() * (1.0f + SCALE_EXPANSION)); if (getType() == SPOT) { const float TANGENT_LENGTH_SCALE = 0.666f; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index af98422b92..e8b50b61ce 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -245,11 +245,50 @@ void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { globalLight->setAmbientMap(light->getAmbientMap()); } +#include + +model::MeshPointer DeferredLightingEffect::getPointLightMesh() { + if (!_pointLightMesh) { + _pointLightMesh = std::make_shared(); + + // let's use a icosahedron + auto solid = geometry::icosahedron(); + solid.fitDimension(1.05f); // scaled to 1.05 meters, it will be scaled by the shader accordingly to the light size + + int verticesSize = solid.vertices.size() * 3 * sizeof(float); + float* vertexData = (float*) solid.vertices.data(); + + _pointLightMesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(verticesSize, (gpu::Byte*) vertexData), gpu::Element::VEC3F_XYZ)); + + auto nbIndices = solid.faces.size() * 3; + + gpu::uint16* indexData = new gpu::uint16[nbIndices]; + gpu::uint16* index = indexData; + for (auto face : solid.faces) { + *(index++) = face[0]; + *(index++) = face[1]; + *(index++) = face[2]; + } + + _pointLightMesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(sizeof(unsigned short) * nbIndices, (gpu::Byte*) indexData), gpu::Element::INDEX_UINT16)); + delete[] indexData; + + + std::vector parts; + parts.push_back(model::Mesh::Part(0, nbIndices, 0, model::Mesh::TRIANGLES)); + parts.push_back(model::Mesh::Part(0, nbIndices, 0, model::Mesh::LINE_STRIP)); // outline version + + + _pointLightMesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + } + return _pointLightMesh; +} + model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { if (!_spotLightMesh) { _spotLightMesh = std::make_shared(); - int slices = 32; + int slices = 16; int rings = 3; int vertices = 2 + rings * slices; int originVertex = vertices - 2; @@ -544,41 +583,30 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // 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; + auto viewport = args->_viewport; // The view frustum is the mono frustum base auto viewFrustum = args->getViewFrustum(); // Eval the mono projection - mat4 monoProjMat; - viewFrustum.evalProjectionMatrix(monoProjMat); + mat4 projMat; + viewFrustum.evalProjectionMatrix(projMat); - // The mono view transform - Transform monoViewTransform; - viewFrustum.evalViewTransform(monoViewTransform); + // The view transform + Transform viewTransform; + viewFrustum.evalViewTransform(viewTransform); - // THe mono view matrix coming from the mono view transform - glm::mat4 monoViewMat; - monoViewTransform.getMatrix(monoViewMat); - - auto geometryCache = DependencyManager::get(); - - auto eyePoint = viewFrustum.getPosition(); - float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft()); auto deferredLightingEffect = DependencyManager::get(); - // Render in this side's viewport - batch.setViewportTransform(monoViewport); - batch.setStateScissorRect(monoViewport); + // Render in this viewport + batch.setViewportTransform(viewport); + batch.setStateScissorRect(viewport); - // enlarge the scales slightly to account for tesselation - const float SCALE_EXPANSION = 0.05f; + auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport); - auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), monoViewport); - - batch.setProjectionTransform(monoProjMat); - batch.setViewTransform(monoViewTransform, true); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform, true); // Splat Point lights if (points && !deferredLightingEffect->_pointLights.empty()) { @@ -586,32 +614,26 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, batch.setPipeline(deferredLightingEffect->_pointLight); batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); + // Pojnt mesh + auto mesh = deferredLightingEffect->getPointLightMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputBuffer(0, mesh->getVertexBuffer()); + batch.setInputFormat(mesh->getVertexFormat()); + auto& spherePart = mesh->getPartBuffer().get(0); + for (auto lightID : deferredLightingEffect->_pointLights) { auto light = deferredLightingEffect->getLightStage().getLight(lightID); if (!light) { continue; } - // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); - - float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); - // glm::vec4 sphereParam(expandedRadius, 0.0f, 0.0f, 1.0f); - - // 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) { - sphereParam.w = 0.0f; - batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } else*/ { - // sphereParam.w = 1.0f; - // batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam)); - + { Transform model; model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); - batch.setModelTransform(model.postScale(expandedRadius)); - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - geometryCache->renderSphere(batch); + batch.setModelTransform(model); + + batch.drawIndexed(model::Mesh::topologyToPrimitive(spherePart._topology), spherePart._numIndices, spherePart._startIndex); + } } } @@ -634,34 +656,12 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, if (!light) { continue; } - // IN DEBUG: - // light->setShowContour(true); batch.setUniformBuffer(deferredLightingEffect->_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... - const float OVER_CONSERVATIVE_SCALE = 1.1f; - if ((eyeHalfPlaneDistance > -nearRadius) && - (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) { - coneParam.w = 0.0f; - batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } else*/ { - // coneParam.w = 1.0f; - // batch._glUniform4fv(deferredLightingEffect->_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); batch.drawIndexed(model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index ff0db1330f..9e53bd5cbc 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -73,6 +73,8 @@ private: bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; + model::MeshPointer _pointLightMesh; + model::MeshPointer getPointLightMesh(); model::MeshPointer _spotLightMesh; model::MeshPointer getSpotLightMesh(); diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 5c9e66dd24..767a96fb51 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -39,10 +39,10 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edge - float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0); + float edge = abs(2.0 * ((getLightCutoffRadius(light) - fragLightDistance) / (0.1)) - 1.0); if (edge < 1) { float edgeCoord = exp2(-8.0*edge*edge); - diffuse = vec3(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light)); + diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light)); } } } diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 8a17a5ef4d..65a417110a 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -40,7 +40,7 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, if (isShowLightContour() > 0.0) { // Show edges - float edgeDistR = (getLightRadius(light) - fragLightDistance); + float edgeDistR = (getLightCutoffRadius(light) - fragLightDistance); float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -getLightSpotOutsideNormal2(light)); float edgeDist = min(edgeDistR, edgeDistS); float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 7168d5386d..0284e12458 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -18,27 +18,27 @@ <$declareStandardTransform()$> -!> +<@include model/Light.slh@> out vec4 _texCoord0; void main(void) { vec4 sphereVertex = inPosition; - // vec4 sphereParam = getLightVolumeGeometry(getLight()); + vec4 sphereParam = getLightVolumeGeometry(getLight()); - // sphereVertex.xyz *= sphereParam.w; + sphereVertex.xyz *= sphereParam.w; // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, sphereVertex, gl_Position)$>; - vec4 projected = gl_Position / gl_Position.w; - projected.xy = (projected.xy + 1.0) * 0.5; + vec4 projected = gl_Position / gl_Position.w; + projected.xy = (projected.xy + 1.0) * 0.5; - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } - _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; + if (cam_isStereo()) { + projected.x = 0.5 * (projected.x + cam_getStereoSide()); + } + _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index e48f8ba907..ef019f5a16 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -20,53 +20,36 @@ <@include model/Light.slh@> - out vec4 _texCoord0; void main(void) { vec4 coneVertex = inPosition; - // if (coneParam.w != 0.0) { vec4 coneParam = getLightVolumeGeometry(getLight()); - if(coneVertex.z >= 0.0) { - // Evaluate the true position of the spot volume - vec2 dir = float(coneVertex.z < 0.5f) * (coneParam.xy - + vec2(coneParam.y, -coneParam.x) * coneParam.z * float(coneVertex.z > 0.0f)) - + float(coneVertex.z > 0.5f) * (vec2(1.0, 0.0) - + vec2(0.0, coneParam.z) * float(coneVertex.z < 1.0f)); - coneVertex.xy *= dir.y; - coneVertex.z = -dir.x; - } else { - coneVertex.z = 0.0; - } + if(coneVertex.z >= 0.0) { + // Evaluate the true position of the spot volume + vec2 dir = float(coneVertex.z < 0.5f) * (coneParam.xy + + vec2(coneParam.y, -coneParam.x) * coneParam.z * float(coneVertex.z > 0.0f)) + + float(coneVertex.z > 0.5f) * (vec2(1.0, 0.0) + + vec2(0.0, coneParam.z) * float(coneVertex.z < 1.0f)); - coneVertex.xyz *= coneParam.w; + coneVertex.xy *= dir.y; + coneVertex.z = -dir.x; + } else { + coneVertex.z = 0.0; + } - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; - vec4 projected = gl_Position / gl_Position.w; - projected.xy = (projected.xy + 1.0) * 0.5; + coneVertex.xyz *= coneParam.w; - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } - _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; - /* } else { - const float depth = -1.0; //Draw at near plane - const vec4 UNIT_QUAD[4] = vec4[4]( - vec4(-1.0, -1.0, depth, 1.0), - vec4(1.0, -1.0, depth, 1.0), - vec4(-1.0, 1.0, depth, 1.0), - vec4(1.0, 1.0, depth, 1.0) - ); - vec4 pos = UNIT_QUAD[gl_VertexID]; + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, coneVertex, gl_Position)$>; + vec4 projected = gl_Position / gl_Position.w; + projected.xy = (projected.xy + 1.0) * 0.5; - _texCoord0 = vec4((pos.xy + 1) * 0.5, 0.0, 1.0); - if (cam_isStereo()) { - _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); - } - gl_Position = pos; - }*/ + if (cam_isStereo()) { + projected.x = 0.5 * (projected.x + cam_getStereoSide()); + } + _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index c2d99259db..1c249e716f 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -77,5 +77,7 @@ void main(void) { _fragColor.rgb += diffuse; _fragColor.rgb += specular; + + // _fragColor.rgb = vec3(0.0, 1.0, 1.0); }