• No results found

Chapter 5 Cadence Models and Examples

5.1.1 Shader Composition for Bloom Effect

Focussing for the moment on how shaders5 in the Stargate model have been combined to produce a HDR (High-Dynamic Range) bloom effect [Kalogirou, 2006] illustrates how Cadence can act asglue. Figure 5.5 shows a more detailed view of this part of the model. Bloom is the apparent glow of bright objects in a scene which is illustrated in figure 5.4 where different values and configurations have been used to adjust the strength of the effect. The process of generating the images in figure 5.4 itself illustrates both the liveness (cf. EUD principles in §2.1.1) and experimental characteristics of Cadence models. To achieve the effect it is necessary to render the scene multiple times using a variety of pixel shaders and settings, in this example there are 9 steps involved. Figure 5.5 shows these 9 steps as a chain of nodes that have various dependencies between them, the dependencies being shown by the red dashed edges. The class name of the associated C++ agents is given (e.g.RenderTarget). To fully demonstrate how Cadence has been successfully used in this way the remainder of this section details each step of the process.

Step 1: The first RenderTarget object (cf. the bottom node in figure 5.5) will take a scene, specified by the Scene object, and a camera, which gives perspective 4This refers to the DMT as mentioned in the footnotes of§3.3.1. In chapter 7 the DMT has been

modified to draw graph structures.

5Shaders are small programs that are run on the highly parallel GPU of the graphics card to control

Figure 5.3: Graph structure of the Stargate model. Grey nodes indicate the existence of a C++ game library agent attached to that object. The blue node is the root node. Only structural relationships are shown, no latent or dynamic dependencies.

Figure 5.4: Bloom configurations. Each image denotes a different configuration of the shaders that can be made while the model is active

and position information, and render that scene into a Texture object. In this case it also renders depth information into another texture. The listing in 5.1 shows how the destination texture is described in Cadence.

t e x t u r e = (new t y p e = T e x t u r e w i d t h i s { @ s g w i d g e t c h i l d r e n cam1 w i d t h } h e i g h t i s { @ s g w i d g e t c h i l d r e n cam1 h e i g h t } c o m p r e s s = f a l s e h d r = t r u e n e a r e s t = t r u e c l a m p = t r u e )

Listing 5.1: Description of a texture

Dependencies have been used in a basic way here to connect the width and height of the texture object to the width and height of the window in which the resulting image will be displayed. This means that if the user changed the resolution of the 3D window then all buffers would also change by dependency. It is a good example of where dependency can be used to maintain an otherwise troublesome relationship and simple dependencies of this form can be found in other user interface technologies (e.g. WPF

dependency properties). Example 5.1 also includes several properties used internally by the C++ agent, such ashdr that tells it to use floating point colour values instead of 8-bit integers so that a much higher range of brightness and colour can be represented. Relating back to the issues identified with EDEN (cf. table 3.2), the texture object in 5.1 is an example of a richer type and so shows how the Cadence approach helps resolve problem B3, that of primitive types being inadequate. Since the texture object is also self-describing and groups related observables together, it helps with problem B6 as well. Another interesting object is the Camera object as this contains definitions to map from keyboard and mouse inputs to camera motion through the scene. Good examples are the deltax andx definitions shown in listing 5.2. These show potentially complex and dynamical dependencies. Whilst these are not animating dependencies, they are self-referent so would not be possible in EDEN (cf. problem C1 in table 3.2) where an agent would be required to move the camera instead.

d e l t a x := { @math s i n ( .o r i e n t a t i o n y − 1 . 5 7 0 7 ) ∗ ( .d l e f t + ( .d r i g h t) ) + (@math c o s ( .o r i e n t a t i o n y − 1 . 5 7 0 7 ) ∗ ( .dup + ( .ddown) ) ∗ ( .s c a l e x z) ) } x := { .x + (@ r o o t i t i m e ∗ (@camera d e l t a x) ) }

Listing 5.2: Camera motion definitions in Stargate

Step 2: After the scene has been rendered the next step is to apply a threshold to it in order to extract only the bright parts of the scene. Another RenderTarget is used with a specific pixel shader that either renders the corresponding pixel or renders a black pixel based upon a simple threshold test. The resulting texture object is also scaled down to half the size of the original scene which is achieved by the dependencies for width and height given in listing 5.3. Figure 5.6 shows the results of each step including this one.

Figure 5.6: The 9 steps of the bloom effect

w i d t h := { @bloom 0 t e x t u r e w i d t h / 2 }

h e i g h t := { @bloom 0 t e x t u r e h e i g h t / 2 }

The threshold value is given to the shader as a shader variable (cf. listing 5.4).

v a r i a b l e s = (new

b r i g h t T h r e s h o l d := { @bloom 10 m a t e r i a l v a r i a b l e s b r i g h t T h r e s h o l d }

)

Listing 5.4: Shader variables connected by dependency

Steps 3,4,5 and 6: All of these steps involve blurring the image and reducing the resolution. Steps 3 and 5 blur in the horizontal with 4 and 6 blurring vertically. The result in step 6 is a blurred image one eighth the size of the original rendered scene. Again dependency is used to define what the width and height of the resulting texture should be, along with specifying a shader variable used for the blurring process to select which dimension and how much to blur (cf. listing 5.5).

dy := { 1 . 0 / (@bloom 2 t e x t u r e h e i g h t) }

dx = 0 . 0

Listing 5.5: Definitions to control blurring

Steps 7 and 8: These two steps combine first the blurred images from steps 4 and 6 and then combines the result of that with the original thresholded image of step 2.

Step 9: Finally the last stage combines the blurred thresholded image of step 8 with the original HDR scene rendering of step 1. This involves the use of a special HDR shader to convert the floating point HDR colour information into 8-bit colour values by using various settings such as exposure. This process is called tone mapping. Once complete this is used by a widget agent to draw to the screen.

Note that the images in figure 5.6 showing each of the above steps were generated by trivially altering the structure of the DOSTE graph so as to bypass certain steps

and directly draw the image to the screen. The DASM statement in 5.6 was used to achieve this and clearly illustrates the ease with which such structures can be constructed and manipulated for different visual effects. Such manipulation shows how Cadence ameliorates problems B1 and B5 (cf. EDEN problems, table 3.2) by allowing whole sub-graphs to be switched around rather than individual observables being redefined manually or by loading new scripts. There are actually many more steps included in the model that have been bypassed as they did not seem to add much to the image quality. Looking at figure 5.5, the numbers on some edges jump from 6 to 9 but numbers 7 and 8 do exist, as do numbers 11-15. This is an example of subjective exploratory experimentation, something which was done throughout the development of the Stargate model and already indicates the Empirical Modelling nature of modelling with Cadence.

.w i d g e t r o o t c h i l d r e n cam1 s o u r c e = (@bloom 0 ) ;

Listing 5.6: Bypassing bloom steps by changing the graph