Skip to content

OpenGL Rendering Effects

James Walker edited this page Oct 2, 2019 · 3 revisions

Quesa’s OpenGL renderer makes it possible to use several rendering effects that were not available in QuickDraw 3D. This document describes those effects and how to enable them.

Shadows

QuickDraw 3D’s standard renderer did not support shadows, but the QuickDraw 3D APIs do have several features relating to shadows: One can designate any light as casting a shadow or not, and there are style objects to specify which objects cast shadows and which objects receive shadows. Quesa implements shadows using a standard OpenGL technique known as stencil shadows or shadow volumes. This implementation makes use of the casts-shadows option on lights and the casts-shadows style object.

Quesa must make 2 additional rendering passes for each shadow-casting light, one to mark the shadow location in the stencil buffer and one to add the contribution of the light to the color buffer. Consequently you would be wise to limit the number of lights that cast shadows.

Translucent objects do not cast shadows, nor do points or lines.

To use shadows, your OpenGL device driver must support either OpenGL 2.0 or later, or the GL_EXT_stencil_two_side extension. If this requirement is not met, requesting shadows in Quesa will have no effect.

Using shadows requires an OpenGL pixel format that includes a stencil buffer. Quesa can request a stencil buffer for you when you use shadows, or you can explicitly request a stencil buffer by setting a property on the Quesa draw context before you start rendering:

#!cpp
TQ3Uns32    stencilBits = 8;
Q3Object_SetProperty( theDrawContext,
   kQ3DrawContextPropertyGLStencilBufferDepth,
   sizeof(stencilBits), &stencilBits );

The stencil buffer must be at least 8 bits deep, and typically that is the only option.

On the Windows OS, there is a restriction that you can set a pixel format for a window only once. Consequently, if there is any chance you will be rendering with shadows in a particular window, you must request a stencil buffer from the start.

Shadow rendering can be turned on or off by setting a property on the renderer object. The renderer checks this flag at the beginning of each frame.

#!cpp
TQ3Boolean    shadowFlag = kQ3True;
Q3Object_SetProperty( theRenderer,
    kQ3RendererPropertyShadows,
    sizeof(shadowFlag), &shadowFlag );

The shadow algorithm sets the yon value of your camera range to infinity. To prevent surprises, it would be a good idea to set yon to infinity yourself. While it is true that you get the best depth resolution when hither is as large as possible and yon is as small as possible, it is much more important to make hither as large as possible.

The optional renderer property kQ3RendererPropertyAttenuationThreshold can be used to fine-tune shadow rendering performance. The idea is that if a point or spot light is attenuated by distance, then objects sufficiently far away from the light can be skipped when rendering shadows for that light.

Cartoon Style

Quesa's rendering can be modified to achieve a cartoon-like effect using the optional renderer properties kQ3RendererPropertyQuantizePerPixelLight and kQ3RendererPropertyCartoonLightNearEdge.

Full-Screen Antialiasing

Antialiasing is a technique to reduce the appearance of jagged edges at pixel boundaries. QuickDraw 3D and Quesa have long had the ability to antialias edges and polygons, controlled via style objects. More recently, Quesa gained the ability to antialias the whole image at once using the OpenGL technique of multisampling.

To use full-screen antialiasing in Quesa, you must, you must provide a multisample-capable pixel format (created by platform-dependent means) as an object property of type kQ3DrawContextPropertyGLPixelFormat when you set up the draw context. Also, early in your rendering loop, you must submit an antialias style object requesting full-screen antialiasing.

Finding a multisample-capable pixel format is likely to depend on the display device (i.e., which monitor is being used), and may require that you already have a valid OpenGL context. For example, on WIndow, you might need to create a dummy window, get a function pointer for wglChoosePixelFormatARB, choose the pixel format, and then destroy the dummy window.

Setting up full-screen antialiasing in the Cocoa API is illustrated in the Cocoa sample in the Extras folder of the Quesa SDK.

To support multisampling, the OpenGL driver must either have an OpenGL version of 1.3 or later, or support the OpenGL extension GL_ARB_multisample.

Testing for Driver Capabilities

When Quesa is unable to provide one of the special features described above, it simply falls back to standard rendering. You may want to detect when one of these features is unavailable, perhaps to disable a menu item or perhaps to advise the user to buy a better computer. In order to do so, you will first need to set up an OpenGL context. You can do so using Quesa in the usual way (setting up a view, draw context, and renderer, and starting a rendering loop) or by direct calls to platform APIs. Bear in mind that on a computer with more than one video card, a particular capability might exist on one monitor and not another.

Once you have a current OpenGL context, the OpenGL calls glGetString( GL_VERSION ) and glGetString( GL_EXTENSIONS ) will suffice to determine most capabilities. However, for full-screen antialiasing, it is not sufficient to check the version and extensions for multisampling support, you must actually try to obtain a multisample pixel format.