pack all the lights in a single buffer and shade the opaque with a single full screen path

This commit is contained in:
sam 2016-09-03 12:08:53 -07:00
parent 4bc8a83c08
commit b81dfefbeb
5 changed files with 123 additions and 46 deletions

View file

@ -60,6 +60,11 @@ struct Light {
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 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis

View file

@ -97,7 +97,7 @@ void DeferredLightingEffect::init() {
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_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
_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,
const DeferredFrameTransformPointer& frameTransform,
const DeferredFramebufferPointer& deferredFramebuffer,
@ -585,6 +590,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
}
auto args = renderContext->args;
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)
auto viewport = args->_viewport;
@ -609,9 +616,46 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), viewport);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewTransform, true);
// batch.setProjectionTransform(projMat);
// 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
if (points && !deferredLightingEffect->_pointLights.empty()) {
// POint light pipeline
@ -645,9 +689,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
// Splat spot lights
if (spots && !deferredLightingEffect->_spotLights.empty()) {
_spotLightsBuffer._buffer->setData(deferredLightingEffect->_spotLights.size() * sizeof(int), (const gpu::Byte*) deferredLightingEffect->_spotLights.data());
std::vector<int> again(deferredLightingEffect->_spotLights.size() + 1);
again[0] = deferredLightingEffect->_spotLights.size();
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
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->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) {
auto light = deferredLightingEffect->getLightStage().getLight(lightID);

View file

@ -161,6 +161,8 @@ public:
gpu::BufferView _spotLightsBuffer;
RenderDeferredLocals();
};

View file

@ -21,12 +21,16 @@
<@include model/Light.slh@>
<$declareLightBuffer(32)$>
uniform lightIndexBuffer {
int lightIndex[32];
};
out vec4 _texCoord0;
flat out int instanceID;
void main(void) {
vec4 coneVertex = inPosition;
Light light = getLight(gl_InstanceID);
instanceID = lightIndex[gl_InstanceID];
Light light = getLight(instanceID);
vec3 lightPos = getLightPosition(light);
vec4 coneParam = getLightVolumeGeometry(light);

View file

@ -20,75 +20,93 @@
// Everything about light
<@include model/Light.slh@>
<$declareLightBuffer(32)$>
uniform lightIndexBuffer {
int lightIndex[32];
};
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
<@include LightSpot.slh@>
<$declareLightingSpot(supportScattering)$>
uniform vec4 texcoordFrameTransform;
//uniform vec4 texcoordFrameTransform;
in vec4 _texCoord0;
//flat in int instanceID;
out vec4 _fragColor;
void main(void) {
// DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
// Grab the fragment data from the uv
vec2 texCoord = _texCoord0.st / _texCoord0.q;
vec2 texCoord = _texCoord0.st;/* / _texCoord0.q;
texCoord *= texcoordFrameTransform.zw;
texCoord += texcoordFrameTransform.xy;
texCoord += texcoordFrameTransform.xy;*/
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);
// frag.depthVal = depthValue;
frag.position = fragPosition;
if (frag.mode == FRAG_MODE_UNLIT) {
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 lowNormalCurvature;
if (frag.mode == FRAG_MODE_SCATTERING) {
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;
_fragColor.rgb += specular;
// Frag pos in world
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;
}
}