Download presentation
Presentation is loading. Please wait.
Published byAdelia Tucker Modified over 7 years ago
1
Regressions in RT Rendering: LittleBigPlanet Post Mortem
Alex Evans & Anton Kirczenow Media Molecule Advances in Real-Time Rendering in 3D Graphics and Games Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
2
Constraints & Mash-ups
Back in 2006, I gave a talk at this same course that advocated this confusing mess of ideas, the idea of mashing together known techniques in a relatively haphazard way to achive the desired ‘look’ - art directed programming. That was written literally as we were founding MediaMolecule, so I thought it would be interesting to top & tail things by looking back at the lessons learnt making the LBP engine. I’m still on the same tip - that of taking simple ideas, seeing connections where perhaps there is no mathematical basis for a connection, but there is a valid visual motivation, and throwing things together. Thus, once again, I’m going to take a whip through some of the techniques we used & abused in LBP, Once again, it’s the combination of techniques, individually simple, that together make up the LBP look. Any commercial product is essentially an exercise in compromises, and we used as many constraints as we could to guide our decisions. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
3
LBP’s Constraints (Back in 2006) Blank slate
no code, no tech, no existing franchise New, Unknown & Strange platform but a single platform! User generated content was to be key no pre-computation ‘worst’ case is the typical case: untrained ‘artists’ aka users Distinctive art style based on ‘miniature world’ style binding content: allow LBP’s style to shine through any UGC My technical prejudices 1.5 programmers & 36 months LBP was an exciting opportunity to reinvent the wheel; by choosing a game built on UGC, I had the opportunity to avoid most of the traditionial ‘engine startup woes’: our entire graphics tool chain, to this day, consists of a MAX exporter, which links the entire game’s codebase, builds a ‘level’ in memory and all its dependent resources (shaders, textures, meshes, lights, ....) in ‘game’ format, and dumps them straight to disk. Knowing we had a single platform, no legacy code, and a desire to keep the edit-view-on-target cycle under 1 second, was extremely useful in keeping the technical choices erring on the ‘simple to maintain’. To put it another way - LBP, being ‘2.5D’ was a relatively ‘easy’ runtime target; rather than spending our effort optimising the runtime performance or features, we chose to optimise the development process, and completely remove the art ‘build’ process. The look of LBP is the work of many people, but the work presented here is largely by Anton Kirczenow - he’s the 1 in 1.5 :) Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
4
Prejudices to force decisions
We had little time to mess about, so the overriding goal was always: whatever is easiest to code & plays to our strengths no middleware (home-made turtles all the way down please) one code path for all rendering of all objects eg same path for solid, transparent, fx... all lighting per-pixel no per-vertex or (shudder) per-object ‘optimizations’ playing to strength of team: I hate vertices, and I don’t have time to write those secondary paths anyway minimum number of ‘knobs’ for the artists - but not too few relatively non-technical art team, busy with other tasks An important lesson learnt time again in computer graphics, especially realtime computer graphics, is to only do work when you need to. Typicallly that means computing items at the lowest frequency possible - whether spatial, or temporal. The fastest computation, is the one that you don’t do. At its most extreme, precomputing invariants, for example, PRT, pre-computed PVS, or baking lighting - offloads runtime work to build-time work. On LBP, we made limited use of this, but the game design was amenable to keeping this at a minimum. 95% of the geometry in LBP is procedurally generated - the 5% remaining typically being the character. So precomputation wasn’t an important avenue. The next layer up is to reduce spatial frequency of computation - that is, pushing slowly varying quantities down from the per-pixel work to vertices, irradiance cache points, photon maps, or even per-object computations. The essential tradeoff is in knowing what your sampling artifacts will be; realtime- graphics and games coders are notorious for never really straying beyond point or linear sampling: for example, coalescing anything after 2 or 3 primary lights onto a per-object light probe - typically SH or other low order basis for diffuse reflections, and environment maps for specular reflections. At most, irradiance gradients takes the approximation to linear. These techniques are spectacularly successful at handling 95% of cases where the space that is being sampled, is well sampled; if objects become excessively large, or tessellation is too uneven, machines or humans can come in and tweak / subdivide or quite simply avoid the bad cases. It’s the human-in-the-loop which is so crucial to games production and optimization - not just any old human either, but a well trained artist with intuitive feel for the strengths or weaknesses of a given approximate renderer. User generated content forces you to cater to a much less skilled audience - the users, and has the pleasant effect of forcing the use of relatively ‘un-brittle’ algorithms - those that ‘just work’ regardless of badly set parameters, badly tessellated scenes, or whatever. This suited my ‘prejudice’ quite well - as a graduate of the demo-scene, I find the allure of simple, single code path, less- than-the-fastest-ever but easiest-to-code techniques the ones I always gravitate to. In the very crowded decision space of ‘what shall I do for my next gen engine’, this proved to be a very practical way of picking a path. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
5
Prejudices into Features
lots of dynamic geometry & cloth (we can’t pre-compute anything anyway...) motion blur, DOF, flexible color correction used in unusual context unbounded numbers of dynamic lights emphasis on many layers of texture to achieve surface look refractive glass correct DOF / motion-blur behind transparent objects ability to arbitrarily cover the entire world in 'stickers' with no loss in frame-rate fluid & cloth to drive all FX we almost avoided writing a particle system. almost. So for the rest of this talk I’m going to run through the more interesting or unusual aspects of some of these in detail; with the overarching theme being as ever ‘whatever works, and is simplest’. the story I’m trying to tell is really about how it’s possible to combine many disparate techniques, whether ‘old’ era graphics papers or new; if your game/target artistic style is clear enough, there are a rich source of ‘good enough’ ideas which when thrown together, can create something special. ‘dont be afraid to be opinionated’ I’ll be covering the full pipeline, starting at the vertex end and proceeding to the post-processing. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
6
Unusual vertex pipe Avoid Vertex Shader slowness on RSX by using SPU instead Add some sexy features to take advantage of SPU: Cloth Soft bodies Patch tesselation Point deformers We’d heard an unsubstantiated rumour that the PS3’s vertex pipe was comparitively weak. We also had to learn how to program the PS3’s 6 ‘SPU’ units - small, 4-way vector processors connected to 256k of very fast L1-style RAM and a DMA unit. The familiar and relatively unthreatening world of vertex transforms was where we started. Since the SPU is not a stream processor in the sense of a GPU - being better suited to chunked processing - ‘anything that you can fit in 256k’ - we thought it would be approproiate to dice the world into simple ‘decorations’ Each decoration would support soft body physics, to give the world of LBP a dynamic, tactile feel. The majority of the SPU work on LBP was created by anton, so I’ll let him explain more - back in November through a haze of MP4 artefacts: Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
7
Anton shows all Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
8
Vertex pipeline: iterate spring/collision constraints Verlet Integrate
with world Input verts Find cluster matrix Rigid Skinning So what’s going on there? The model we settled on very early was for the SPU’s to output a world-space polygon soup of unlit vertices each frame. This allowed a simple separation of work - Anton handled vertices, and I handled lighting that soup. As a result, we ended up with large buffers filled each frame with the position of every vertex in the visible scene. By double buffering these position buffers, we were able to trivially know the velocity of any vertex. This was ideal for the first stage of the vertex pipe: verlet integration. Input bones X compute N, T Stitch seams Morph targets X Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
9
Vertex motion SPU’s job is to create world-space ‘polygon soup’ per frame P & N are triple buffered, allowing simple Verlet physics Pnew = 2P-drag*(P-Pold)-Pold+A drag is set by collision routine Meshes automatically turned into springs across grids of quads, with artist weighting in vertex colors Vertex lerp’ed back to skinned pos using artist defined weights One of the key lessons we learned while creating LBP (at least with our artists) was that whenever we could create an automated system to set a parameter, their productivity shot up. For example, if we’d asked them to hand-specify the layout of springs in their meshes, cloth would simply never have been used. As a result, the max exporter automatically detects grids of quads and creates a lattice of springs across that grid, including X struts, and links straddling pairs of rows. We found that the function from ‘artist effort’ to ‘frequency of use in game’ wasn’t really very soft at all - it was a brick wall. It was either fully automatic, with a fun parameter to tweak hear or there that ‘always worked’, or it was nothing at all. That isn’t to say that the artists weren’t incredibly dedicated or talented - just that, intuitively, given the choice between spending time tweaking opaque / overly complex parameters and doing something where they actually contributed ‘artistically’, they would gravitate to the latter, even if it meant omitting the use of a techy feature. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
10
Collision Detection old new SPU does collision against:
extruded 2D convex shapes (world) swept ellipsoids (character) vertex transformed into old & new ellipsoid position raycast sphere vs ellipse in stationary ‘ellipse space’ raycast Pold Pold old Pnew A crucial part of any cloth simulator is collision. LBP’s 2d world was conveniently made up of extruded 2D convex shapes, that could easily be ray- cast against. the character was augmented with a set of ellipsoids attached to primary bones; thus the SPU only had to handle moving-point vs moving ellipsoid/swept extruded 2d shape. by transforming the old and new positions of the vertex into the local space of the ellipsoid / rigid convex shape, collision is quite easy. colliding points don’t respond elastically - instead, the point is forced onto the surface of the colliding object, and a drag bit is set per vertex that squashes their velocity in the next Verlet step. we didn’t bother damping velocity in the normal direction only. new transform into ellipse space Pnew Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
11
Clusters Lovely mesh-less algorithm: least-squares fit a new rigid matrix to a deformed cloud of vertices remove center of mass - that gives translational component matrix sum of dyadic of (P-COM) x (Prest-COMrest) multiply by inverse of pre-computed matrix in rest pose orthogonalize resulting best-fit matrix to give affine transform, and optionally preserve volume by normalizing blend with original rigid body matrices to make as squishy/rigid as you want more detail: Meshless Deformations Based on Shape Matching - Muller et al, SIGGRAPH 05 One of the earliest demos of LBP included ‘deely boppers’ small stars attached to springs, attached in turn to the rigidly moving head of sackboy. To achieve this effect, we wanted to be able to have 2-way interactions between rigid portions of mesh, and ‘clothy’ spring based portions of mesh. In the end, a really lovely, SPU friendly algorithm was chosen: ‘clusters’ of vertices, labelled by the artist as belonging together, are integrated by the Verlet & collision steps; the SPU then finds the best fitting matrix that, when used to transform the vertices from the rest pose, best matches the results of the physical simulation. This is a simplified, linear version of the technique outlined in Muller et al 2005. Because the verlet integrator in subsequent frames depends only on 2 previous positions, by lerping the vertices towards their best fit ‘rigid’ positions, the artist can control how clothy vs rigid the cluster is. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
12
flexibility of vertex pipeline
we ended up using that pipeline not just for meshes, decorations, cloth but also SFX like confetti, dust, embers,... allowing us to almost entirely avoid an explicit ‘particle system’ with one exception: jet-pack smoke was a simple point-sprite based backend on the integrated/collided vertices... rendered 1/4 screen-res for fill-rate reasons each point sprite has a 2D gradient across it - gives remarkable sense of ‘3d-ness’ every pixel samples the sun’s shadowmap to give volumetric shadows in the smoke as can be seen in this squence of screenshots, we ended up using this flexible vertex pipeline for some quite non-traditional ‘FX” uses: by simply replacing the sackboy mesh with one made up of disconnected-quads, and marking them all as fully ‘clothy’ rather than rigid, Sackboy (or any other mesh) can readily be turned into what looks like a particle system for embers. By taking the positions and old positions from the old, ‘rigid’ mesh, the particles are even initialized with the correct initial velocities. The beauty of this is that, other than the code to switch meshes from ‘rigid’ to ‘clothy’, the rest of the effect requires no special code whatsoever. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
13
On to pixels: graph based?
Once the polygon soup is generated, it needs to be textured. Early on in development, we read that on PS3, the PPU must patch constants into the pixel shader code directly, since the GPU does not actually have any pixel shader ‘constant’ ram. patching was causing some slowdown issues in early PS3 titles, so I decided to design a material system that simply used a completely static shader per ‘material’. I also wanted an entirely data-driven method of creating these textures. The prevalent idiom in games at the time, as now, is the maya-esque ‘shader graph’. Having implemented an number of these ‘boxes and lines’ systems for audio before, I dived righti n. observation: far too many knobs proliferate in a naive ‘boxes’n’lines’ system. every node ends up having a few parameters to be tweaked, or at least a plethora of inputs. The resulting high-dimensional parameter space is neither intuitive nor enjoyable for artists to explore, and I didn’t have time to write a lovely interface for them, nor did we have manpower to hire dedicated ‘shader’ artists. As a short-term fix, I hacked into the max exporter some code to automatically generate the graph of nodes based on Max’s layered materials. I assumed that artists would use this to ‘boot strap’ their creative process, then dive into the graph-based material editor to create the final shaders. however: Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
14
fixed everything aint so bad?
the graph editor was never used by artists they were happy to composite LOTS of texture layers at different scales and left me to hard-code a single ‘uber-shader’ that handled everything else. that BRDF is entirely ‘cooked up’ based on live shader editing and my eyeballs. approximately: 2 strong rim-light with color set using artist controlled hemisphere based on (V.N)^2 with bias & scale the 2 rim lights are lerp’ed between based on sunlight shadow diffuse a mixture of N.L and (N.L)^2 ambient a simple 2 color hemisphere specular simply (R.L)^22 artists *never used* the graph editor. not because it was bad, (I hope!) but because the max auto-path was plenty good enough for them to be ‘creative’, and had just enough flexibility. (occasionally I would go in and tweak the graph, for example tie game-code generated values into shader parameters, but that was the exception) this also led to a way of creating shaders that contributed greatly to the LBP ‘miniature look’: note the obscene number of layers of texture: I count 4 diffuse layers, 3 specular layers, and a bump map. for a very, very basic cloth material... sigh But by taking the old idea of ‘detail maps’ to this extreme, LBP ended up with a very ‘tactile’ look at all scales. there was another, slightly unexpected up side: incredibly tiny textures. the vast majority of lbp1’s texture content fits in under 50 megs. key visual look here: SCALE, bumpiness, tacticle-ness. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
15
shadowing one sun light & arbitrary numbers of ‘sprite lights’
world has shallow depth, so we got away with very simple shadowmapping Initially TSM eg Finally, just orthogonal single 768x768 shadowmap! very tightly tuned frustum of shadow casters soft shadows via variance shadow maps + AO contact shadows just the vanilla form of VSM: after Donnelly et al lots of light leaking used 16FP render targets with two copies of X, X^2 in R/G and B/A second copy scaled by 32. recombined in shader -> less boiling LBP was, from its inception, an outdoor game. However I knew that I wanted to support arbitrary numbers of lights per pixel; indeed, there are many user generated levels now that routinely use hundreds of local lights to create the look of their level. Before we get to those lights, I knew I wanted to rapidly ‘set the scene’ with a single, softly shadowed, light - to create an attractive base on which users could splash light. Initially we used a TSM to control shadow map aliasing between the foreground and the background - at that stage of the game design, users could create arbitrarily ‘deep’ levels and so it was important to be able to have well- defined and good looking soft shadows for much deeper than scenes than are typically associated with LBP. Eventually, the game design changed to limit the depth of levels to 3 layers + a background. To this day, the background is in fact made up of the same sorts of things as the foreground - in fact, some users have discovered a hack/bug/exploit to create super deep levels with 50 layers of user generated content - but once I knew that the front 3 were all that mattered, we simply culled the background out from the shadowing. The loss of shadows in the heavily DOF’ed background wasn’t that great, and in return we won back a lot more space in our shadow map to dedicate to the foreground. so much so, in fact, that we ditched TSM and went to a single, orthographic shadow map of 768 x 768. the shadow map is rendered in Z-only double speed mode of the RSX, before being blurred in two passes by two 7 tap filters. The resulting blurred VSM is stored as FP16. We found that even for our heavily culled shadow frustum, FP16 didn’t have enough precision to prevent ‘boiling’ in the penumbras. the extra bits of precision imparted by storing two scaled copies in the spare channels of the texture was enough. We made no attempt to fix light leaks - beyond a slight bias-and-scale in the shader. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
16
ambient occlusion for contacts
the character’s feet were small & felt floaty... so we added an AO ‘light’ that analytically computed the occlusion of the character modeled as 5 spheres (2 feet, 2 legs, 1 groin) see Inigo Quilez’ awesome site for derivation The physical nature of LBP is very important, and sackboy felt like his feet weren’t rooted to the ground, especially because the blur kernel of the VSM was quite wide. ‘hand’ added foot-shadows are a staple of computer games since the 80s; these days, it isn’t hard to compute the ‘ambient occlusion’ of a sphere analytically - so we placed 5 sphere on the leg bones of each sackboy, and rendered each as a tiny multiplicative ‘light’. the original code to compute the occlusion of the spheres was cooked up intuitively - and the formula is in fact so simple that it’s easy to see where the terms come from I took the dot product between the surface normal and occluder, since ‘overhead’ objects are occluding the large part of the diffuse cosine lobe, and occluders near or below the occludee’s horizon are not important; secondly, the amount of occlusion must be proportional to the projected size of the occluding sphere onto the hemisphere above the occludee - in other words there must be a term of the form ‘r^2/d^2’. It turns out that this is indeed correct - and for the full and more rigorous derivation, I encourage you to check out the very instructive site of Inigo Quilez. (He has some beautiful rendered images up there, based on ray marching signed distance fields. highly recommended!) AO= (N.D) (r2/D.D) Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
17
Spritelights take 1 as presented at SIGGRAPH 06, I started by slicing the view frustum and rendering light volumes directly into those slices (as a volume texture) A sort of ‘irradiance volume’ - but with no directional component. (‘0th order SH’) Use grad of irradiance in direction of normal to approximate N.L type lighting. So, now the main sun light is sorted out, I wanted to investigate the ability to have large numbers of localised light sources. However, since my previous project, in 2005, had been a PC DX9 deferred renderer, I was interested to explore more unusual alternatives that might allow me a more ‘forward’ style of rendering elsewhere. This was the subject of most of my 2006 talk... the part that is relevant to today is that I basically used my desire to try out new stuff, as a way of driving out alternative ways of thinking about a hard problem. Again, constraints driving tech choices, with an underlying ‘artistic’ look in mind. the main technical idea was that localised lights are typically large, low- frequency blobs of light. Since the LBP play-area is relatively shallow, it seemed practical to store the entire visible play area as a volume texture, and splat those lights into the volume, without regard to the scene geometry. The scene can then be rendered ‘forward’, with all non-sun lights simply costing one or 2 volume texture lookup per pixel. essentially, a dynamic irradiance buffer... Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
18
Sprite Lights Take 1 Initially I tried rendering the lights into quite a ‘wide’ (in coefficient terms) volume texture - that is, storing 9 SH coefficients per voxel, to encode the direction as well as intensity of the light passing through each point in space. However this proved too costly, both in terms of memory and in the time it took to update the volume every frame. Intuitively, it frustrated me that so little information was conveyed by the 9 coefficients in typical scenes, despite the memory cost. After playing with various hybrid 0th-order-colour / higher-order-monochrome solutions, I settled on an approximation: storing only the non-directional component of the light, I took the grad of the light in the direction of the shaded normal. This amounts to sampling the volume twice: once on the shaded surface, and once slightly ‘off’ it. The difference in irradiance colours will be positive if the normal is towards a light, and negative if away. With judicious tweaking, this looked pretty good, as seen in this video: Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
19
Sprite Lights Take 1 We used this technique in production throughout Throughout this period, as mentioned previously, the levels created were relatively ‘deep’. To handle this depth, the volume was aligned to the view in post-projective space, slicing the view frustum into 16 evenly spaced slices in ‘w’, causing the slices to be spaced as 1/z in world space, clustering towards the camera. However, as can be seen towards the end of the video, the resulting change of scale between layers actually causes severe undersampling of small lights, in the z direction. A light which crossed two layers and was relatively localised in world space, was now skewed so heavily (for example, from a sphere into a very eccentric ellipsoid) in post-perspective space that the low number of z slices become visible. In addition, the layers weren’t constrained to be parallel to the world depth, and moved with the camera. The lack of accuracy in the approximation, and the small amount of code being discarded, led me back to the drawing board. I knew that the only alternative was to use some kind of deferred approach, but I still wanted to avoid the bandwidth/memory cost of a full ‘G’ buffer. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
20
Sprite lights take 2: Defer?
Lay down a Z/N pre-pass at 2X MSAA ...then light as if it were grey plastic (specular -> alpha) ...and do sprite lights in the traditional ‘deferred’ way BUT! no G-buffer, no material properties, no MRTs: just Z, N in The solution we shipped with amounts to (I discovered yesterday researching the other talks at this course!) Wolfgang Engel’s light-prepass algorithm ,or a variant of it. So we’re in good company :) and I won’t cover that aspect of it any more today as I’m guessing Wolfgang will have covered it and many extensions already. For LBP the technique evolved less from a ‘prepass’ mentality, and more through my self imposed allergy to MRTs, combined with the observation that every single one of the materials generated by the artists to that date had the same specular power. (!) (which happened to be the default i’d set luckily I’d spent some time choosing that value - but it’s worth noting: whenever you choose a default for your artists, do so carefully, and visually. there is never any excuse for hiding behind the old excuse of ‘oh its just coder art some artist can make it look good later’ if you’re a graphics coder) I figured that I might as well light the whole scene with one ‘grey plastic’ shader, whose material properties were constant and thus didn’t require any screen space material buffers, and then ‘paint the color’ over the scene in a 2nd geometry pass. The specular lobe was broken out into the alpha channel so that it could be modulated separately from the diffuse component. This had the added benefit that it forced me to revisit both ‘spite lights’, but also MSAA and transparency, both of which were now ‘weaker’ (aka not working) than they had been in the previous forward renderer. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
21
Sprite lights take 2: Defer?
then re-render scene ‘forwards’, sampling ‘L’ into BRDF a brief note on performance: for typical sunlit scenes, the new 2-pass system was relatively well suited to the peculiarities of the RSX GPU: the first pass sampled only normal maps, and acted almost like a fast z prepass (although I couldn’t use the double speed rendering mode, it’s still a relatively small amount of the total frame time, at under 3ms). This helped reduce overdraw for the 2nd pass with its extremely bandwidth-hungry multi-layered textures, and reduced thrashing of the texture cache: the normal maps (which were themselves often layered) were ‘out the way’, balanced between the two passes. So the performance penalty of rendering the scene geometry twice was largely offset. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
22
sprite lights take 2: god rays
now we’re doing sprite lights properly, we might as well add some features: god rays! Also at this time, I was investigating fake bounce lighting and SSAO. I couldn’t get SSAO looking nice enough - I wanted ‘top down contact shadows’ ,rather than ‘dirt in the creases’, and I found the haloing around the character too difficult to avoid. after a few abortive attempts, I salvaged this: I’d noticed that, while rendering the deferred light, the ‘in scattering’ term, when viewed on its own, looked ripe for smearing into fake shadows / god rays / crepuscular rays :). both the images here take this idea: as for most deferred renderers, the ‘sprite light’ volume is rendered, back-face-with-z-test-inverted, accumulating light into the L buffer; at the same time, an ‘in scatter’ amount is computed based on the distance between the front and back surfaces of the light volume, compared to the scene’s z buffer. This ‘glow’ is then downsampled to a low resolution buffer, with a single channel per light: Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
23
god rays implementation
completely 2d screenspace effect each light volume is rendered to an off-screen surface, one channel per light (in batches of 4) pixel shader integrates light scattering along eye ray to first solid object (z buffer distance) 3 pass ‘smear shader’ then smears dark regions with MIN blending each pass doubles distance of smear similar to masa’s ‘rthdribl’ lens-flare streak shaders ibl/ The smear shader is a simple 5 tap linear 2d ‘smear’: the screenspace pixel position is scaled towards the source of the light, and the samples merged together. Rather than summing the samples, which leads to a soft edge on both sides of the smeared image, the sampled values are biased by the smear distance, and then min-blended. That is: (...next slide...) Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
24
god rays implementation
completely 2d screenspace effect each light volume is rendered to an off-screen surface, one channel per light (in batches of 4) pixel shader integrates light scattering along eye ray to first solid object (z buffer distance) 3 pass ‘smear shader’ then smears dark regions with MIN blending C = sample(u,v) for (i=0;i<5;i++) u=(u-cu)*k+cu; v=(v-cv)*k+cv; C=min(C, sample(u,v) + i/5.f); (where k<1 sets smear radius, cu,cv is the screenspace position of the lightsource) Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
25
2 layer transparency deferred shading with alpha. what?
the new deferred renderer was fine, but immediately threw into question how to light transparent objects. LBP very often has semi transparent objects placed over the scene, most obviously in ‘create mode’ where a 50% alphad ‘stamp’ object can be positioned in the scene before being ‘materialised’ by hitting X. So it was extremely important to be able to light scenes including transparent objects. I was unwilling to introduce a second code path for those objects. In addition, transparent rendering wasn’t the only problem: any technique that reads back the z buffer has issues with transparency. as I mentioned at the outset, the visual style of LBP was ‘miniature world’ and heavy DOF & motion blur were the most important techniques to achieve that ‘real world mini’ look these techniques rely on post-processing of the rendered scene, typically taking into account the Z buffer value at each pixel. Thus, they break down on scenes with transparency. In the switch to a deferred shader, the main surface renderer also now fell into this ‘transparency is hard’ category. LBP uses 2X MSAA, and it occurred to me that it would be nice to trade spatial antialiasing for the majority of the screen, with layered transparency where it was needed. In other words, use the memory normally reserved for related color samples in a pixel, to store 2 layers of both Z and N, but only where it was needed. By running the deferred lighting passes at double horizontal resolution, and by making the post-processing effects aware of this ‘dual layer transparency’, it was possible to create correct lighting, DOF and motion blur for the very-common-in-LBP case of a single semi-transparent object in front of solid objects. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
26
2 Layer transparency Exploiting the fact that we have 2X MSAA hardware
and we can ‘cast’ the ‘L’ buffer to be 2560x720p non MSAA deferred lighting done at full 2560x720p resolution allows us two independent Z values per final pixel PS3 you have to resolve your 2560x720p into 1280x720 by hand. turn this into a virtue: trade transparency for MSAA in different regions of the screen custom resolve shader is quite tricky: uses alpha channel to control blend between the two samples - compositing either as ‘A over B’ or ‘(A+B)/2’ The PS3 uses a somewhat more low level API than most PCs, allowing you to render to surfaces either as 2X MSAA or as if they were double resolution un- MSAA targets. Indeed, there is no hardware resolve - instead, you must sample the MSAA surface by hand and combine the samples in the post processing stages. In LBP, we render all geometry to Z, Light and Color buffers as if they were 1280x720 2xMSAA. Solid objects render as usual; alpha objects disable blending, and set the hardware MSAA sample mask to be ‘right only’. They write their alpha value into the destination alpha channel. The deferred lighting shaders treat the resulting buffers as 2560x720p buffers, and thus with no extra code correctly light both layers of Z. This comes at some cost - the light shaders are run on twice as many pixels. On the upside, in regions with no transparency, you actually get ‘post specular lobe’ 2x MSAA filtering, and in areas of transparency, you get, well, correct transparency. The post-processing effects that rely on Z operate at half resolution (640x360p), starting with a fast downsampling step. This downsampling step was made ‘intelligent’ - it samples the two hi-res 2560-wide layers (solid & alpha) separately, then averages them together, weighting each on the amount of DOF/moblur it will need. This is an approximation, but is good enough to allow us at final-comp stage to give the impression of separate DOF layers. As seen in these images: Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
27
2 layer transparency & DOF &...
Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
28
2 is not a big number leads to odd effects when you get more than 2 layers: users actively are exploiting this to great effect! Obviously, this 2 layer system wasn’t without its costs. It led to relatively ‘fragile’ shaders which carefully offset their input UV coordinates by half a pixel here and there - not intuitive looking code, and a hassle when supporting multiple resolutions or off-screen rendering. worst of all, you run out of ‘2’ very quickly! glass-behind-glass disappears. Amazingly, the community now uses this (along with another bug in the handling of fog!) to striking effect: quite a few levels place a thin layer of glass across the front of the entire level. now, all objects made of glass in the main play area disappear, since the alpha layer is entirely used up by the transparent foreground layer. Now, these entreprising creators can create ‘magical’ levels where the mechanism is hidden, or objects appear to float. In the hands of the right users, no mis-feature is ever all bad.... Worse, it slowed down some shaders - especially the final MSAA resolve shader, and the DOF shaders - because they had to take great care to treat the two samples separately. Since LBP was released, Matt Swoboda and the Phyre Engine team have done some very interesting work on using the SPU to do deferred shading. In particular, their optimization of categorizing tiles of framebuffer according to need - eg transparency, no transparency- could be used to both speed up the easy cases, and further improve the quality/features of the ‘deferred transparency’ (perhaps with more layers). A particularly interesting variant is to decouple the resolution of the lighting pre-passes, from the final colour passes. In that scenario, the final color passes would need to ‘scan’ the lower resolution lighting buffers, for appropriate samples. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
29
2 layers: Refraction Glass shader only WRITES to even pixels in X (‘alpha layer’) it only READS from odd pixels in X (‘solid layer’), sampling from it’s own screenspace pos P perturbed by the glass surface normal k is the ‘index of refraction’ P.xy+=k*N.xy P.x-=frac(P.x)+0.5; <--- MAGIC! Cout=tex2D(screen,P) code above relies on using UV’s measured in pixels, not 0-1 One last cute trick that the 2 layer system enabled, was a really fast way of refracting the solid layer through the transparent layer. Typically, one should not read from the same memory that one is rendering to. However, if you know that you are only writing to one of the two MSAA samples, as is the case with the transparent object case, and you arrange to only READ from the other, you can do so without hazard. Refractive (or other post-processing) materials become easy: they only render to the ‘even’ X pixels, and simply sample the frame buffer at a normal-map perturbed position, *quantized in the X direction* to only read from the ‘odd’ X pixels. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
30
careful MB/DOF calculation
Motion-blur & DOF were vital to the miniature look willing to spend lots of GPU cycles on this however it still runs at half res: PASS 0: downsample 2x in Y, 4x in X blend 2 layers correctly according to degree to which each sample needs blurring. Alpha channel = coarse z buffer Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
31
careful MB/DOF calculation
PASS 1 & 2: 7 tap ‘classic’ DOF with variable circle of confusion, checking alpha channel for z conflicts samples distorted along direction of screenspace motion motion blur comes ‘for free’ using same sample points as DOF stationary pixel This is pretty much the same-old-same-old that everyone’s been doing for years. The DOF & motion blur passes are combined into one pass. The 7 tap filters were chosen rather than poisson disc because I ike the look of the resulting regular looking ‘bokeh’, which to my eye further emphasizes the ‘person filming a world with a camcorder’ look. Subtle implementation point: Originally, I had a small 2x2 matrix for the ellipsoid, computed from the DOF and motion blur parameters at each pixel, as shown in the diagram. In the end, a simpler approach leading to fewer cycles was used: each of the 7 samples was offset from the central pixel separately for the DOF and blur; that is, each point would first be offset by R * sin/cos(i*PI*2/7), and THEN offset by V * shuffle[i], where V is the screenspace motion vector and shuffle[] is a constant random permutation of the numbers 0 to 7. In theory, this means that some directions cause the DOF kernel to ‘collapse’ to a degenerate line; however the shuffle helps to reduce this to just causing a bit more aliasing (only a few samples will collapse together for any given direction), and the perceived change in image was much less than the gain in speed. fast moving pixel Final MSAA Resolve: reads 1/2 res blurred image, and composites it over the full-res screen; however it does this BEFORE blending the two alpha layers, and mixes the blurred image into each layer only according to that layer’s need. This conditional blend happens at full res, so no need for bilateral filter et al Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
32
first stab at motion blur
we have a screenspace motion vector (x,y) for each pixel however, boundaries of objects don’t look nice: Initially, tried to render geometry extruded along direction of motion. however, fast rotating objects broke this: One of the frustrations of a naive motion blur implementation is the sharp edges that a foreground object will have when moving relative to its background. Since the motion blur is being emulated with a GPU friendly ‘gather’ step rather than the potentially less artefact-y ‘scatter’ step, the pixels that fall just outside a fast moving object have no idea to include the neighboring object’s influence in the final image. In early builds of LBP, we distorted the geometry at the vertex level: each vertex knows its old and new positions in the vertex shader, and the shader is written to output whichever one lies along the ‘smooth normal’ direction of that point. In this way, a sphere is elongated along its direction of motion into a capsule: vertices on the leading edge choose the current position, while vertices on the trailing edge choose the old position. (* a smooth normal is a normal computed ignoring any creases; thus a cube has smooth normals facing diagonally out from all its vertices. That way, creases with multiple vertices that share positions, also share smooth normals and thus don’t rip apart during this process). In addition, I was rendering the screen-space velocity field in a separate pass from the main geometry render. By only extruding the geometry used to render the *velocity* buffer, unpleasant squashing/stretching of the geometry is hidden and replaced with a more pleasing fringe around fast moving objects. however the linear approximation used broke down for fast rotating objects, where the linear approximation of ‘old to new’ distortion caused cylinders to collapse inwards. Adding extrapolation for the leading edge just reversed the problem; if we’d had acceleration information available to the vertex shader, I could have made a quadratic approximation to the motion - but in the end, we found an alternative way that completely did away with the need to distort the geometry. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
33
improving motion blur how to improve ‘leading’ and ‘trailing’ edges?
insight: use 2 frames of info - this frame (1) and old frame (0) blur C1 with V0, and C0 with V1 (twice as many taps) use Z-in-alpha to help composite samples together Frame 0 Frame 1 these regions get frame 0 background blurred by frame 1’s velocity while these regions get fr.1 background, with fr.0 velocity Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
34
improving motion blur: results
Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
35
fluids: how? Stam stable fluids, 2D water-grid PDE, or SPH?
Anton will take them all, thanks very much! Stam-style stable fluids can be seen all over the place for smoke, fire & dissolve fx Water Grid used for ‘sea level’ Rigid body coupling to grid, generates... ... splash particles, combining SPH water-volume preserving forces with existing vertex pipeline (verlet, collisions etc) for this last section, I’ll return to some work by Anton. We’ve used a fluid solver throughout LBP to handle dissolve, smoke & fire effects. More recently, he’s been doing some research into water rendering. In keeping with the theme of this talk, we use a collection of well established techniques to achieve the desired look. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
36
water grid shallow water simulation - 256x128 on SPU
fixed grid only contains visible play area, and is post-perspective distortion to give even tesselation The method is as in Claes Johanson’s MSc thesis, "Real Time Water Rendering: Introducing the projected grid concept” but tweaked to keep the grid evenly spaced in X when the camera is very near the surface and looking forward. V advects quantities with bicubic filtering linear not good enough - leads to ‘viscous’ look method is similar to Chapter 11 of ‘Fluid Simulation for Computer Graphics by Robert Bridson 2008’ The water surface is a shallow water simulation on a 256x128 grid running on the SPUs. The fixed size grid contains the visible play area and is scrolled to follow the camera when it moves. It tracks depth and velocity per cell on staggered grid. Velocity advects quantities with bicubic filtering as linear advection makes the water look too viscous. The method is quite similar to [Fluid Simulation for Computer Graphics by Robert Bridson 2008, Ch. 11] which is a great reference for this sort of stuff in general. For rendering, the water simulation grid is resampled on the SPU to generate an evenly spaced mesh from the point of view of the camera. This avoids drawing offscreen geometry and extends the surface beyond the grid. The method is as in [Claes Johanson "Real Time Water Rendering: Introducing the projected grid concept" MSc Thesis 2004 ] but tweaked to keep the grid evenly spaced in X when the camera is very near the surface and looking forward. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
37
Water rendering The water surface normals are generated by bicubic filtering a texture of the height field, linear isn’t good enough: Refraction is just cheesy resampling of screen buffer with perturbed UVs by the surface normal additional z check to ensure refracted sample is actually below surface: The water surface normals are generated by bicubic filtering a texture of the height field [Sigg & Hadwidger "Fast Third Order Texture Filtering" in GPU Gems 2]. This does much a better job of hiding grid artifacts than linear interpolation of per vertex normals. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
38
Water rendering The depths of the water surface and refracted bottom are also used to compute fog and filter colors proportional to the amount of water in front of the refracted surface [e.g. Real Time Rendering 3rd Ed. ]. The surface "reflects" the frame buffer turned upside down and adds a bit of a generic sky box cube map. This is horribly wrong but at least it is cheap and has the right colors and follows the camera in a plausible way when it tracks left and right. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
39
water grid / rigid body coupling
For rigid body coupling: find rigid bodies intersecting the water surface, take their AABBs and compute the change of "submerged-ness" in the water. This is diffused and added to the water depth to create wakes and ripples. The method is as per [Thurey et. al."Real Time Breaking Waves for Shallow Water Simulations" 2007] , but with Stam style stable diffusion so it doesn't blow up so much. We also add some of the velocities of the immersed objects to the water grid Rigid bodies make ripples as they move around in the water. Though the graphics water does not affect the rigid bodies; the coupling is one way. We find rigid bodies intersecting the water surface, take their AABBs and compute the change of "submergedness" in the water. This is diffused and added to the water depth to create wakes and ripples. The method is as per [Thurey et. al."Real Time Breaking Waves for Shallow Water Simulations" 2007] , but with Stam style stable diffusion [Stam "Stable Fluids" SIGGRAPH 99] so it doesn't blow up so much. We also add some of the velocities of the immersed objects to the water grid. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
40
Grid -> SPH: Splashes!
We generate splashes wherever the water height changes rapidly emit particles where these both hold: change in water height > threshold gradient(water height) dot water velocity > 0 Splash particles (and bubbles) also add depth to the water grid when they collide with it to cause secondary ripples. splash particles are in an SPH simulation as per Muller et. al. "Particle based Fluid Simulation for Interactive Applications" Eurographics 2003 with a novel collision detection scheme that is more SPU friendly more details in the course notes! We generate splashes in a similar way to [ O'Brien and Hodgkins "Dynamic Simulation of Splashing Fluids" Proc Computer Animation 1995 ]We analyse the surface to find places to emit "splash" particles where change in water height > threshold gradient(water height) dot water velocity > 0We didn't want a full 3D grid/hash table for spatial acceleration so instead we sort particles on X and then sweep through them with a 2D bucket grid on Y & Z.We add only as many particles to the YZ buckets as are necessary to overlap current particle in X, and remove others preceding it as we go.This means we only need to check 9 buckets for a particle for interactions instead of 27 for 3D buckets and use much less memory.Particle interactions are found only once per pair instead of twice as they are with voxel bucket methods.We can still parallelize the collision detection by splitting the particle array into even sized non overlapping slabs in X, processing those in parallel, and adding a fix up pass for the seams between them. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
41
splat based splash rendering
2 pass rendering: 1st pass sorts coarse quads front-to-back, with UNDER compositing of N and alpha this ensures isolated particles look sharp, while still blending adjacent particles smoothly each particle is elongated along its direction of motion particles near the water surface stretch to simulate joining 2nd pass outputs color uses stencil buffer to avoid overdraw uses similar shader as the water surface to provide consistency The quads are rendered front to back and normals blend with the under operator: (1-dstalpha)*srccolor+dstalpha*dstcolor and adds alpha values.In this way isolated blobs are sharp but overlapping blobs blend their normals together.In a second pass normals are read from the deferred buffer and used to render reflections and refractions similarly to the surface.The stencil buffer is tested and updated to ensure only the front most blob pixel is rendered. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
42
underwater & caustics! inspired by Pixar’s ‘Finding Nemo’ DVD extras &
Advanced Animation and Rendering Techniques by Alan Watt & Mark Watt, 1992, Ch 10.1 small area compared to grid = bright large area compared to grid = dark Incoming light on regular grid intersect refracted grid of sun-rays with fixed ground-plane beneath the water surface Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
43
underwater & caustics! inspired by Pixar’s ‘Finding Nemo’ DVD extras &
Advanced Animation and Rendering Techniques by Alan Watt & Mark Watt, 1992, Ch 10.1 simply intersect refracted grid of sun-rays with fixed ground-plane beneath the water surface on SPU, for each vertex, compute change in area of surrounding refracted quads vs un-refracted quads output as a gouraud shaded mesh, rendered by GPU blend as MAX rather than +, to keep dynamic range down Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
44
Refraction a 1024x512 caustic map renders in only 0.6ms!
Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
45
underwater when rendering main scene, project caustic texture through world We also add lots of bubble meshes and ambient floating bits using our cloth simualor (!) and use Curl Noise to move them about. [Bridson et. al. "Curl- Noise for Procedural Fluid Flow" ACM Transactions on Graphics 2007]. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
46
stable fluids 3 layers of 256x128 2D fluid, used for smoke & dissolve FX borrowing tricks from Mark Harris’ GPU implementation (GPU Gems) GPU re-samples screenspace z & v buffers to initialize boundary conditions fluid only run on 3 world aligned slices, that scroll with the camera GPU copies from the backbuffer into the fluid buffer to cause objects to ‘dissolve’ SPU outputs list of point sprites on a grid to avoid wasting fill rate where there is no fluid Another SPU feature was a 2D fluid simulator to do smoke, fire, poison gas, dissolving objects etc.It follows the Jos Stam Stable Fluids approach borrows some tricks from the Mark Harris GPU implementation. The SPU does the velocity field, boundaries, densities and so on at low res, and the RSX upscales it and adds some texture detail.I guess its debate-able whether the RSX or SPUs would do velocity fields faster/better.I went with SPUs as the RSX was already maxxed out most of the time, was suspicious of float performance and got some benefits from being able to do bit wise ops on SPUs too.It vectorizes very well, though an auto vectorizer for SPU would have been very useful. The synchronization between SPU and RSX gets quite funky as RSX renders a low res ortho view of the scene to create a bitmap of boundaries for the fluid sim,calls back the PPU to kick the SPU to process the boundary image, do the velocity/density field updates, split the result in to tiles and kick an RSX label to render them.The RSX is busy rendering the main scene while the SPU is doing the fluid sim. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
47
breathe.... ...and be thankful that we didn’t go through all the other fun stuff, like virtual texturing for stickering, or procedural mesh generation on the SPU... Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
48
remind me what that was about?
the key here is that many disparate techniques can be blended to create something unique looking it’s valid to treat dev-time as a primary constraint for LBP, we were able to trade accuracy & generality for ‘good enough’ approximations... the devil joy is in the details! the SPU freed us from worrying about casting every problem as a VS/PS stream processing ‘DX9’ combination which ironically unlocked a lot of fun pre-GPU literature avoiding special case code paths kept the complexity down and the code coverage good... ...making it cheap to re-visit major decisions, like ‘forward’ vs ‘deferred’, and re-implement features several times. Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
49
conclusion in other words,
have fun mixing up and blending as many ideas as you think will help you achieve the visual look you’re after (or something) Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
50
thankyou! Advances in Real-Time Rendering in 3D Graphics and Games
New Orleans, LA (August 2009)
51
Bibliography 1/5 Akenine-Moller T., Haines, E. & Hoffman, N. (eds) - "Real Time Rendering 3rd Ed." 2008 A. K. Peters (pub) - Bridson, R. et. al. - "Curl-Noise for Procedural Fluid Flow" in ACM Transactions on Graphics 2007 Bridson, R. - "Fluid Simulation for Computer Graphics by Robert Bridson" 2008, Ch Donnelly, W. & Lauritzen A. - "Variance Shadow Maps" Engel, W. - "Light Pre-Pass Renderer Mark III" in SIGGRAPH 2009 Advances in Real-Time Rendering in 3D Graphics and Games course notes, 2009 Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
52
Bibliography 2/5 Evans, A. - "Fast Approximations for Global Illumination on Dynamic Scenes" 2006 in SIGGRAPH 2006 Advanced Real-Time Rendering in 3D Graphics and Games course notes - Harris, M. - “Fast Fluid simulation on the GPU” 2004 in GPU Gems Iwasaki, Kei et al - "An Efficient Method for Rendering Underwater Optical Effects Using Graphics Hardware" in Computer Graphics Forum tokyo.ac.jp/nis/cdrom/cgi/cgf.pdf Johanson C. - "Real Time Water Rendering: Introducing the projected grid concept" in MSc Thesis Lander, J. - "Devil in the Blue-Faceted Dress: Real-Time Cloth Animation" In Gamasutra Magazine Features, Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
53
Bibliography 3/5 Martin, T. & Tan, Tiow-Seng - "Anti-aliasing and Continuity with Trapezoidal Shadow Maps" in proceedings of Eurographics Symposium on Rendering Muller, M. et al - "Particle based Fluid Simulation for Interactive Applications" in Proceedings of Eurographics 2003 Muller, M. et al - "Meshless deformations based on shape matching" in proceedings of SIGGRAPH _SIG05.pdf O'Brien & Hodgkins - "Dynamic Simulation of Splashing Fluids" in Proc. Computer Animation 1995 Quilez, I. - "Sphere Ambient Occlusion" Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
54
Bibliography 4/5 Sigg, C. & Hadwidger M. - "Fast Third Order Texture Filtering" in GPU Gems VRVis pdf Stam, J. - "Stable Fluids" In SIGGRAPH 99 Conference Proceedings, Annual Conference Series, August 1999, Swoboda, M. et al, "Deferred Lighting and Post Processing on PLAYSTATION" in GDC 2009 Presentations, dLightingandPostProcessingonPS3.ppt Thuerey, N. et. al. - "Real Time Breaking Waves for Shallow Water Simulations" Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
55
Bibliography 5/5 Valient, M. et al, "Deferred Rendering in Killzone," in Develop Conference, Brighton, July conference.com/developconference/downloads/vwsection/Deferred Watt, A. & Watt, M. - "Advanced Animation and Rendering Techniques" Ch 10.1 Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
56
the end Advances in Real-Time Rendering in 3D Graphics and Games
New Orleans, LA (August 2009)
57
really the end Advances in Real-Time Rendering in 3D Graphics and Games New Orleans, LA (August 2009)
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.