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

This commit is contained in:
samcake 2016-09-01 18:08:36 -07:00
parent 0c0109e427
commit e72791233d
8 changed files with 107 additions and 120 deletions

View file

@ -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;

View file

@ -245,11 +245,50 @@ void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) {
globalLight->setAmbientMap(light->getAmbientMap());
}
#include <shared/Shapes.h>
model::MeshPointer DeferredLightingEffect::getPointLightMesh() {
if (!_pointLightMesh) {
_pointLightMesh = std::make_shared<model::Mesh>();
// 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<model::Mesh::Part> 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<model::Mesh>();
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<GeometryCache>();
auto eyePoint = viewFrustum.getPosition();
float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft());
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
// 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<model::Mesh::Part>(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);

View file

@ -73,6 +73,8 @@ private:
bool _shadowMapEnabled{ false };
bool _ambientOcclusionEnabled{ false };
model::MeshPointer _pointLightMesh;
model::MeshPointer getPointLightMesh();
model::MeshPointer _spotLightMesh;
model::MeshPointer getSpotLightMesh();

View file

@ -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));
}
}
}

View file

@ -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);

View file

@ -18,27 +18,27 @@
<$declareStandardTransform()$>
<!<@include model/Light.slh@>!>
<@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;
}

View file

@ -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;
}

View file

@ -77,5 +77,7 @@ void main(void) {
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
// _fragColor.rgb = vec3(0.0, 1.0, 1.0);
}