mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 05:37:13 +02:00
pack all the lights in a single buffer and shade the opaque with a single full screen path
This commit is contained in:
parent
4bc8a83c08
commit
b81dfefbeb
5 changed files with 123 additions and 46 deletions
|
@ -60,6 +60,11 @@ struct Light {
|
||||||
|
|
||||||
SphericalHarmonics _ambientSphere;
|
SphericalHarmonics _ambientSphere;
|
||||||
};
|
};
|
||||||
|
const int LIGHT_SPOT = 2;
|
||||||
|
|
||||||
|
bool light_isSpot(Light l) {
|
||||||
|
return bool(l._control.y >= 2.f);
|
||||||
|
}
|
||||||
|
|
||||||
vec3 getLightPosition(Light l) { return l._position.xyz; }
|
vec3 getLightPosition(Light l) { return l._position.xyz; }
|
||||||
vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis
|
vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis
|
||||||
|
|
|
@ -97,7 +97,7 @@ void DeferredLightingEffect::init() {
|
||||||
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
|
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
|
||||||
|
|
||||||
loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations);
|
loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations);
|
||||||
loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations);
|
loadLightProgram(deferred_light_vert, spot_light_frag, false, _spotLight, _spotLightLocations);
|
||||||
|
|
||||||
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
|
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
|
||||||
_allocatedLights.push_back(std::make_shared<model::Light>());
|
_allocatedLights.push_back(std::make_shared<model::Light>());
|
||||||
|
@ -571,6 +571,11 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderDeferredLocals::RenderDeferredLocals() :
|
||||||
|
_spotLightsBuffer(std::make_shared<gpu::Buffer>()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
|
void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
|
||||||
const DeferredFrameTransformPointer& frameTransform,
|
const DeferredFrameTransformPointer& frameTransform,
|
||||||
const DeferredFramebufferPointer& deferredFramebuffer,
|
const DeferredFramebufferPointer& deferredFramebuffer,
|
||||||
|
@ -585,6 +590,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
|
||||||
}
|
}
|
||||||
auto args = renderContext->args;
|
auto args = renderContext->args;
|
||||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
|
// Framebuffer copy operations cannot function as multipass stereo operations.
|
||||||
|
batch.enableStereo(false);
|
||||||
|
|
||||||
// THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
|
// THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
|
||||||
auto viewport = args->_viewport;
|
auto viewport = args->_viewport;
|
||||||
|
@ -609,9 +616,46 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport);
|
auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport);
|
||||||
|
|
||||||
batch.setProjectionTransform(projMat);
|
// batch.setProjectionTransform(projMat);
|
||||||
batch.setViewTransform(viewTransform, true);
|
// batch.setViewTransform(viewTransform, true);
|
||||||
|
|
||||||
|
// gather lights
|
||||||
|
auto& srcPointLights = deferredLightingEffect->_pointLights;
|
||||||
|
auto& srcSpotLights = deferredLightingEffect->_spotLights;
|
||||||
|
std::vector<int> lightIndices(srcPointLights.size() + srcSpotLights.size() + 1);
|
||||||
|
lightIndices[0] = 0;
|
||||||
|
|
||||||
|
if (points && !srcPointLights.empty()) {
|
||||||
|
memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int));
|
||||||
|
lightIndices[0] += srcPointLights.size();
|
||||||
|
}
|
||||||
|
if (spots && !srcSpotLights.empty()) {
|
||||||
|
memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int));
|
||||||
|
lightIndices[0] += srcSpotLights.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lightIndices[0] > 0) {
|
||||||
|
_spotLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data());
|
||||||
|
_spotLightsBuffer._size = lightIndices.size() * sizeof(int);
|
||||||
|
|
||||||
|
// Spot light pipeline
|
||||||
|
batch.setPipeline(deferredLightingEffect->_spotLight);
|
||||||
|
batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform));
|
||||||
|
|
||||||
|
// Spot mesh
|
||||||
|
auto mesh = deferredLightingEffect->getSpotLightMesh();
|
||||||
|
batch.setIndexBuffer(mesh->getIndexBuffer());
|
||||||
|
batch.setInputBuffer(0, mesh->getVertexBuffer());
|
||||||
|
batch.setInputFormat(mesh->getVertexFormat());
|
||||||
|
auto& conePart = mesh->getPartBuffer().get<model::Mesh::Part>(0);
|
||||||
|
|
||||||
|
|
||||||
|
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer);
|
||||||
|
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer);
|
||||||
|
// batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex);
|
||||||
|
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
/*
|
||||||
// Splat Point lights
|
// Splat Point lights
|
||||||
if (points && !deferredLightingEffect->_pointLights.empty()) {
|
if (points && !deferredLightingEffect->_pointLights.empty()) {
|
||||||
// POint light pipeline
|
// POint light pipeline
|
||||||
|
@ -645,9 +689,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
// Splat spot lights
|
// Splat spot lights
|
||||||
if (spots && !deferredLightingEffect->_spotLights.empty()) {
|
if (spots && !deferredLightingEffect->_spotLights.empty()) {
|
||||||
|
std::vector<int> again(deferredLightingEffect->_spotLights.size() + 1);
|
||||||
|
again[0] = deferredLightingEffect->_spotLights.size();
|
||||||
_spotLightsBuffer._buffer->setData(deferredLightingEffect->_spotLights.size() * sizeof(int), (const gpu::Byte*) deferredLightingEffect->_spotLights.data());
|
memcpy(again.data() + 1, deferredLightingEffect->_spotLights.data(), deferredLightingEffect->_spotLights.size() * sizeof(int));
|
||||||
|
_spotLightsBuffer._buffer->setData(again.size() * sizeof(int), (const gpu::Byte*) again.data());
|
||||||
|
_spotLightsBuffer._size = again.size() * sizeof(int);
|
||||||
|
|
||||||
// Spot light pipeline
|
// Spot light pipeline
|
||||||
batch.setPipeline(deferredLightingEffect->_spotLight);
|
batch.setPipeline(deferredLightingEffect->_spotLight);
|
||||||
|
@ -663,7 +709,9 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
|
||||||
|
|
||||||
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer);
|
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer);
|
||||||
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer);
|
batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightIndexBufferUnit, _spotLightsBuffer);
|
||||||
batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex);
|
// batch.drawIndexedInstanced(deferredLightingEffect->_spotLights.size(), model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex);
|
||||||
|
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
/*
|
/*
|
||||||
for (auto lightID : deferredLightingEffect->_spotLights) {
|
for (auto lightID : deferredLightingEffect->_spotLights) {
|
||||||
auto light = deferredLightingEffect->getLightStage().getLight(lightID);
|
auto light = deferredLightingEffect->getLightStage().getLight(lightID);
|
||||||
|
|
|
@ -161,6 +161,8 @@ public:
|
||||||
|
|
||||||
gpu::BufferView _spotLightsBuffer;
|
gpu::BufferView _spotLightsBuffer;
|
||||||
|
|
||||||
|
RenderDeferredLocals();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,16 @@
|
||||||
<@include model/Light.slh@>
|
<@include model/Light.slh@>
|
||||||
<$declareLightBuffer(32)$>
|
<$declareLightBuffer(32)$>
|
||||||
|
|
||||||
|
uniform lightIndexBuffer {
|
||||||
|
int lightIndex[32];
|
||||||
|
};
|
||||||
out vec4 _texCoord0;
|
out vec4 _texCoord0;
|
||||||
|
flat out int instanceID;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 coneVertex = inPosition;
|
vec4 coneVertex = inPosition;
|
||||||
|
instanceID = lightIndex[gl_InstanceID];
|
||||||
Light light = getLight(gl_InstanceID);
|
Light light = getLight(instanceID);
|
||||||
vec3 lightPos = getLightPosition(light);
|
vec3 lightPos = getLightPosition(light);
|
||||||
vec4 coneParam = getLightVolumeGeometry(light);
|
vec4 coneParam = getLightVolumeGeometry(light);
|
||||||
|
|
||||||
|
|
|
@ -20,75 +20,93 @@
|
||||||
// Everything about light
|
// Everything about light
|
||||||
<@include model/Light.slh@>
|
<@include model/Light.slh@>
|
||||||
<$declareLightBuffer(32)$>
|
<$declareLightBuffer(32)$>
|
||||||
|
uniform lightIndexBuffer {
|
||||||
|
int lightIndex[32];
|
||||||
|
};
|
||||||
<@include LightingModel.slh@>
|
<@include LightingModel.slh@>
|
||||||
|
|
||||||
|
<@include LightPoint.slh@>
|
||||||
|
<$declareLightingPoint(supportScattering)$>
|
||||||
<@include LightSpot.slh@>
|
<@include LightSpot.slh@>
|
||||||
<$declareLightingSpot(supportScattering)$>
|
<$declareLightingSpot(supportScattering)$>
|
||||||
|
|
||||||
uniform vec4 texcoordFrameTransform;
|
//uniform vec4 texcoordFrameTransform;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
in vec4 _texCoord0;
|
in vec4 _texCoord0;
|
||||||
|
//flat in int instanceID;
|
||||||
out vec4 _fragColor;
|
out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
// DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
// DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
|
||||||
|
|
||||||
// Grab the fragment data from the uv
|
// Grab the fragment data from the uv
|
||||||
vec2 texCoord = _texCoord0.st / _texCoord0.q;
|
vec2 texCoord = _texCoord0.st;/* / _texCoord0.q;
|
||||||
texCoord *= texcoordFrameTransform.zw;
|
texCoord *= texcoordFrameTransform.zw;
|
||||||
texCoord += texcoordFrameTransform.xy;
|
texCoord += texcoordFrameTransform.xy;*/
|
||||||
|
|
||||||
vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);
|
vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);
|
||||||
|
|
||||||
// Need the light now
|
|
||||||
Light light = getLight(0);
|
|
||||||
|
|
||||||
// Frag pos in world
|
|
||||||
mat4 invViewMat = getViewInverse();
|
|
||||||
vec4 fragPos = invViewMat * fragPosition;
|
|
||||||
|
|
||||||
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
|
|
||||||
vec4 fragLightVecLen2;
|
|
||||||
vec4 fragLightDirLen;
|
|
||||||
float cosSpotAngle;
|
|
||||||
if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
// _fragColor.rgb = vec3(0.0, 1.0, 1.0);
|
|
||||||
// return;
|
|
||||||
|
|
||||||
DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord);
|
DeferredFragment frag = unpackDeferredFragmentNoPositionNoAmbient(texCoord);
|
||||||
// frag.depthVal = depthValue;
|
|
||||||
frag.position = fragPosition;
|
|
||||||
|
|
||||||
if (frag.mode == FRAG_MODE_UNLIT) {
|
if (frag.mode == FRAG_MODE_UNLIT) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frag to eye vec
|
|
||||||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
|
||||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
|
||||||
|
|
||||||
|
// frag.depthVal = depthValue;
|
||||||
|
frag.position = fragPosition;
|
||||||
|
|
||||||
vec3 diffuse;
|
|
||||||
vec3 specular;
|
|
||||||
vec4 midNormalCurvature;
|
vec4 midNormalCurvature;
|
||||||
vec4 lowNormalCurvature;
|
vec4 lowNormalCurvature;
|
||||||
if (frag.mode == FRAG_MODE_SCATTERING) {
|
if (frag.mode == FRAG_MODE_SCATTERING) {
|
||||||
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
|
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
|
||||||
}
|
}
|
||||||
evalLightingSpot(diffuse, specular, light,
|
|
||||||
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
|
|
||||||
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
|
||||||
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
|
||||||
|
|
||||||
_fragColor.rgb += diffuse;
|
// Frag pos in world
|
||||||
_fragColor.rgb += specular;
|
mat4 invViewMat = getViewInverse();
|
||||||
|
vec4 fragPos = invViewMat * fragPosition;
|
||||||
|
|
||||||
// _fragColor.rgb = vec3(0.0, 1.0, 1.0);
|
// Frag to eye vec
|
||||||
|
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||||
|
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||||
|
|
||||||
|
int numLights = lightIndex[0];
|
||||||
|
for (int i = 0; i < numLights; i++) {
|
||||||
|
// Need the light now
|
||||||
|
Light light = getLight(lightIndex[i + 1]);
|
||||||
|
bool isSpot = light_isSpot(light);
|
||||||
|
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
|
||||||
|
vec4 fragLightVecLen2;
|
||||||
|
vec4 fragLightDirLen;
|
||||||
|
float cosSpotAngle;
|
||||||
|
if (isSpot) {
|
||||||
|
if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 diffuse;
|
||||||
|
vec3 specular;
|
||||||
|
|
||||||
|
if (isSpot) {
|
||||||
|
evalLightingSpot(diffuse, specular, light,
|
||||||
|
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
|
||||||
|
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||||
|
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||||
|
} else {
|
||||||
|
evalLightingPoint(diffuse, specular, light,
|
||||||
|
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
|
||||||
|
frag.metallic, frag.fresnel, frag.albedo, 1.0,
|
||||||
|
frag.scattering, midNormalCurvature, lowNormalCurvature);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fragColor.rgb += diffuse;
|
||||||
|
_fragColor.rgb += specular;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue