Deferred Directional & Ambient Lights

So I added directional and ambient lights to the deferred renderer:

The G-Buffer is pretty simple. Color (RGBA8), positions (RGBA16F), and normals (RGBA16F):

(I didn’t convert the normals properly, since I just used apitrace to dump the framebuffer contents).

Of course, it could be optimized. I’m going to pack specular into the alpha channel of the color buffer. I could make normals RG16F and get Z from X/Y (1 – x * x + y * y) since they’re normalized (of course). And I could make positions RG16F as well and get the Z from the depth buffer and camera matrix.

But I think that’s a bit premature. :)

The lights are composited in a separate buffer:

…and then blended with the colors from the GBuffer to generate the final lit image.

In the DeferredRendererPass, I collect light nodes and push them into their own list:

function DeferredRendererPass:walk(node, delta) if node:isCompatibleType(LightSceneNode) then table.insert(self.lights, PendingNode(node, delta)) else — … end

— …
end

Then when I draw lights, after building the GBuffer, I switch based on the derived LightSceneNodeType:

for i = 1, #self.lights do local node = self.lights[i].node if node:isCompatibleType(DirectionalLightSceneNode) then self:drawDirectionalLight(node, delta) elseif node:isCompatibleType(AmbientLightSceneNode) then self:drawAmbientLight(node, delta) end end

And finally, I handle specific logic in the drawDirectionalLight/drawAmbientLight/etc methods.

Again, this could be optimized. I could push all lights of specific types into their own queues and render all directional lights in one go, then all ambient lights, then all point lights, etc.

But it’s too early to optimize.