Direct Primitive Rendering

Because some effects are difficult or cumbersome to make with high level rendering only (eg. by rendering geometries) I added access to the renderer DrawTriangle function.

You may ask why I did not do that before? Well, that's because the renderer internals might or might not be 'special' and require primitives to be drawn in very specific ways or at very specific moments.

The OpenGL renderer, when using the deferred path, is a good example of such a 'special' renderer (but no more than the raytraced renderer is, in yet another way). This rendering path uses multiple target rendering to output material components to disctinct textures organized in a specific way. A final pass is done to combine lighting with the scene material components.

Example with a new Builtin



A floating light in the editor that a builtin materializes at runtime.

I just wrote a lens flare builtin with this new part of the API and it required adding a new item callback known to execute when the renderer is in a neutral state. By neutral state I mean that the deferred rendering is done, the screen is ready for display and the renderer can work in any mode and precisely in the mode we have an interest in: the fixed-function immediate mode.

Let's have a look at this new API and its use.

function    DrawBillboardQuadTextured(matrix, center, size, texture, uvmin = UV(0, 0), uvmax = UV(1, 1), color = Vector(1, 1, 1), flag = MaterialRenderDefault)
{
        local   v0 = center + (matrix.GetLeft() + matrix.GetUp()) * size,
                        v1 = center + (matrix.GetRight() + matrix.GetUp()) * size,
                        v2 = center + (matrix.GetRight() + matrix.GetDown()) * size,
                        v3 = center + (matrix.GetLeft() + matrix.GetDown()) * size
 
        local   uv0 = uvmin,
                        uv1 = UV(uvmax.u, uvmin.v),
                        uv2 = uvmax,
                        uv3 = UV(uvmin.u, uvmax.v)
 
        RendererDrawTriangleTextured(g_render, v0, v1, v2, texture, uv0, uv1, uv2, color, flag)
        RendererDrawTriangleTextured(g_render, v0, v2, v3, texture, uv0, uv2, uv3, color, flag)
}

This DrawBillboardQuadTextured function is now part of the engine Squirrel API so you can use it directly, no need to redefine it.

One last note, the lens flare builtin knows when it is assigned to a light and will inherit the light properties like its diffuse color in such a case.

Current Limitations


Unfortunately, it is far from perfect. Even if a nice number of effects are now easily done through the combination of the new callback and the DrawTriangle API the more interesting effects are not possible just yet. For example, outputting primitives during the deferred rendering path execution will still produce unexpected results (and non-reproducible on other ports!).

There are easy ways to address this issue:

  1. Give access to the system material library (mostly done),
  2. Add a DrawTriangleWithMaterial() function,
  3. Add an item OnRenderPass(pass) callback for each stage of the rendering process.

Another limitation concerns performances. Not only is drawing a single primitive at a time horrible for the GPU performance, but doing so from a script is also horrible for the CPU performance. So the current system should prove useful for a variety of smaller screen-based effects but is not meant to be used as a mean to render full worlds... yet ;).


To infinity... and beyond!