mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 19:55:07 +02:00
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:
parent
0c0109e427
commit
e72791233d
8 changed files with 107 additions and 120 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -73,6 +73,8 @@ private:
|
|||
bool _shadowMapEnabled{ false };
|
||||
bool _ambientOcclusionEnabled{ false };
|
||||
|
||||
model::MeshPointer _pointLightMesh;
|
||||
model::MeshPointer getPointLightMesh();
|
||||
model::MeshPointer _spotLightMesh;
|
||||
model::MeshPointer getSpotLightMesh();
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -77,5 +77,7 @@ void main(void) {
|
|||
|
||||
_fragColor.rgb += diffuse;
|
||||
_fragColor.rgb += specular;
|
||||
|
||||
// _fragColor.rgb = vec3(0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue