1 / 80

95.4501

95.4501. Rendering Architectures. Preamble. There are 2 aspects to lighting . Light coloring ; e.g., a red light colors nearby walls red. Light shadowing ; e.g., walls not visible to a light are not colored .

isra
Download Presentation

95.4501

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 95.4501 Rendering Architectures

  2. Preamble • There are 2 aspects to lighting. • Light coloring; e.g., a red light colors nearby walls red. • Light shadowing; e.g., walls not visible to a light are not colored... Lighting in this section deals exclusively with LIGHT COLORING. Occlusion knowledge is completely ignored...

  3. Terminology • A forward renderer is one in which shader computations include all lighting aspects in the same shader (otherwise, it’s not a forward renderer). • A light pass renderer is one which iterates over all the lights to process them for some reason. • A light indexed renderer is one which maintains information about lights via indices rather than their properties... • A deferred renderer is one that uses information previously stored in specific passes for use in a later pass...

  4. Game Engine Variations Forward Renderers Light Pass Renderers Light Indexed Renderers Deferred Renderers Light Pass Deferred Renderers Light Pass Forward Renderers Light-Indexed Light Pass Forward Renderers Light-Indexed Light Pass Renderers Light-Prepass Deferred Renderer • Of interest for historical reasons Designing a Renderer for Multiple Lights: The Light Pre-Pass Renderer, Engel (Rockstar; GTA), pp 655-666, ShaderX7, 2009.

  5. 95.4501 Renderers

  6. Overdraw • Overdraw is the notion that portions of the screen are drawn multiple times each with their own completely different shaders. Top view Much wasted GPU power goes in drawing the red walls when all that is visible when done is the blue wall. camera

  7. Renderers • Renderers deal with overdraw either by ignoring it (assuming a powerful GPU) or by invoking a special pass called the depth only pass (invented by Carmack in Doom3). • The depth only pass draws all geometry with • color writing offdepth writing on, depth testing on and subsequent passes are drawn with • color writing ondepth writing off, depth testing on

  8. Depth Only Pass Only Uses Cheap Vertex Shader • If we draw a building model, many walls will draw (most overdrawn by a closer wall)... • With color writing off and depth writing on, only the vertex shader runs computing clip coordinate x/y/z values (in particular, the z-value establishes depth). 2 to 8 times faster if color writing is off (Engel, Rockstar Games) Top view Only this wall ends up WITH DEPTH INFO IN THE DEPTH BUFFER AND NO PIXEL SHADERS RUN camera

  9. The 2nd Standard Draw Pass • With color writing on and depth testing on (but not depth writing), the complex shader runs only IF the depth test is passed. These ALL FAIL THE DEPTH TEST (Vertex shader runs BUT NOT PIXEL SHADER) Top view Only this wall ends up being visible (Vertex shader AND COMPLEX PIXEL SHADER RUNS) because it’s visible... camera

  10. Dealing with Several Lights • The simplest approach used by older engines is to have each pixel shader loop over the lights (if you have many objects, it’s equivalent to) what each shader does. • for each object do • for each light do • lighting += computeLighting (object, light); Feasible for a handful of lights BUT NOT FOR 200 LIGHTS MOST OF WHICH ARE TOO FAR AWAY FROM THE PIXEL

  11. Dealing with Several Lights • A more efficient approach breaks objects into smaller objects and determines which lights affect which objects and draws one at a time. • for each object • for each light that can affect this object do • lighting += computeLighting (object, light); • OR • for each light do • for each object affected by light do • lighting += computeLighting (object, light); Instead of 1 draw call, you have many draw calls (substantially slower). The engine has to do a lot of work breaking up the large draw call and determining which lights affect which objects (ALL DONE ON CPU)

  12. Taking the Lighting Computation Completely Out Of The Standard Renderer • Instead of an O(n2) loop of form • OR • for each object do • for each light than can affect this object do • lighting += computeLighting (object, light); • for each light do • for each object affected by light do • lighting += computeLighting (object, light); • We would like two O(n) loops...

  13. More specifically, we would Like • for each object (via large triangle buffers) do • g-buffer = non-light specific lighting properties of visible object; • for each light do • lighting += light_model (g-buffer, light); Deferred Renderers Light Pass Renderers A g-buffer is a buffer of geometric attributes (in this case, lighting attributes); implemented as a collection of textures each able to hold 4 float attributes...

  14. Problems with Transparency • Forward renderer: conventional style that processes lighting in every single shader. • Deferred renderer: non-conventional style that tries to deal with lighting in a separate lighting pass by grabbing and deferring the use of some information. Both have problems dealing with transparent objects since these need to be (1) captured, (2) sorted by depth, and (3) drawn last…

  15. Lighting with Forward Renderers: Summary • Game engine needs to break world geometry into groups affected by sets of lights (say a dozen). Leads to many draw calls. • Each group needs to be drawn separately. Not too hard for static lights... much harder for dynamiclights... • Groups affected by more than the light limitneed to be drawn again BLENDING the new lighting with the old (multitexturing) Many draw calls Many state changes You can’t have every shader loop over 100 lights…

  16. What’s Wrong With Forward Renderers • Scales poorly with complex lighting or large numbers of lights. • Increasingly important as the game quality climbs up. Particularly with hundreds of lights…

  17. Lighting with Deferred Renderers • Shaders are rewritten to produce deferred information but don’t themselves use this deferred information. Drastically cuts down on the number of shaders; e.g., a relief mapper, non-relief mapper, skinning shader. • On PC at least, such renderers use MRT (multiple render targets) to support g-buffers with many attributes; e.g. 24 floats. Not clear what kinds of special effects are no longer supported.

  18. Deferred Rendering is a multiphase technique • One pass deals with non-lighting. • One pass deals with lighting (they are light pass renderers). • By not mixing them, the goal is to simplify the game engine... and in the process, be able to support a much larger set of lights. There are 2 different ways of tracking the lighting information: either the lights themselves or the lights’ lighting materials

  19. 95.4501 Variations of the Basic Deferred Renderer

  20. Variations Due To G-Buffer Stingyness • Standard deferred renderer use 4 texture g-buffer. • Light prepass deferred renderer uses 2 texture g-buffer; recovers missing information by rendering geometry twice... Normal.xNormal.yNormal.z Unused Diffuse DiffuseDiffusematerial.xmaterial.ymaterial.z Unused SpecularSpecularSpecularSpecularmaterial.xmaterial.ymaterial.z power Position.xPosition.yPosition.z Unused Normal.xNormal.yNormal.z Unused Position.xPosition.yPosition.z Unused • R G B A

  21. Another Viewpoint • LIGHTS AFTER MATERIALS • Standard deferred renderer • Light prepass deferred renderer (poor name) light map back buffer large g-buffer REAL draw geometry draw lights simple DRAW QUAD combine geometry • LIGHTS BEFORE MATERIALS back buffer small g-buffer light map SIMPLE draw geometry draw lights REAL draw geometry • Uses geometry materials to finish lighting geometry • “real draw after lights” renderer

  22. Hieroglyph3 FPS Comparison: 33 = 27 lights • Standard renderer more than twice as fast 206 85 standarddeferred renderer light prepass deferred renderer Deferred Rendering, Practical Rendering and Computation with Direct3D11 pp 491-541, CRC Press, 2011.

  23. Hieroglyph3 FPS Comparison: 73 = 343 lights • Neither is a winner (BOTH too slow)... 39 27 Varied 26-37 Varied 31-41 standarddeferred renderer light prepass deferred renderer

  24. Note to Wilf • To run the hieroglyph demo, startup Visual Studio 2010. • Select the “Deferred Rending” OR the “LightPrepass”project. • Select “Project” and click on “Set as startup project”. • Then RUN.

  25. Conclusions • We will only investigate standard deferred renderers. • No clear advantage to light prepass deferred renderer. • We will also investigagelight-Indexed renderers (which like the above are light pass renderers) but pick up which light instead of which light information (each light has its own lighting information).

  26. 95.4501 Standard Deferred Renderers

  27. Hieroglyph3 Demo (343 Lights) Deferred Rendering, Practical Rendering and Computation with Direct3D11 pp 491-541, CRC Press, 2011.

  28. Investigating Hieroglyph3: Traditional Deferred Rendering • Pass 1 renders a g-buffer (which is where the relief map shader would run; the demo only support normal mapping; can’t do self occlusion since lights not yet available). • Pass 2 renders the lights to create a light map; each light adds to it… • Pass 3 draws one fullscreen quad to blend materials in the g-buffer with the light map (output to the backbuffer). Warning: Converts everything to world rather than camera space. so we won’t show shader code for this. It is advantageous to have a z-buffer prepass 0 so that pass 1 does not run multiple overdrawn relief map shaders…

  29. 95.4501 Pass 1 of Standard Deferred Renderers: Rendering G-Buffer

  30. Hieroglyph3: The G-Buffer Rendering Shader • The g-buffer layout… NOTHING LIGHT SPECIFIC. • Render target 0: Normal.xNormal.yNormal.z Unused Diffuse DiffuseDiffusealbedo.xalbedo.yalbedo.z Unused • Render target 1: SpecularSpecularSpecularSpecularalbedo.xalbedo.yalbedo.z power • Render target 2: Position.xPosition.yPosition.z Unused • Render target 3: • R G B A Albedo MEANS material…

  31. Hieroglyph3 • The demo provides additional passes to perform MSAA (multi-sample anti-aliasing) if you enable it in the user interface (too complicated to consider). • The “.cpp” code is • for all objects in world dodraw via g-buffer rendering shader Gbuffer.hlsl Warning: The shader code presented below has been slightly simplified for presentation purposes.

  32. Hieroglyph3: The G-Buffer Rendering Shader //Vertex shader and pixel shader for filling the G-Buffer of STANDARD//deferred renderer (SLIGHTLY MODIFIED BY WILF) //Note: The word albedo MEANS material… cbuffer Transforms { matrix WorldMatrix; matrix WorldViewMatrix; matrix WorldViewProjMatrix;}; cbufferMatProperties { float3 SpecularAlbedo; float SpecularPower;}; Texture2D DiffuseMap : register (t0);Texture2D NormalMap : register (t1);SamplerStateAnisoSampler : register (s0); Albedo MEANS material… Diffuse map is the texture map... Should discard register keywords

  33. Hieroglyph3: The G-Buffer Rendering Shader structVSInput { float4 Position : POSITION; float2 TexCoord : TEXCOORDS0; float3 Normal: NORMAL; float4 Tangent: TANGENT; float4 Bitangent: BITANGENT; }; structVSOutput { float4 PositionCS: SV_Position; float2 TexCoord: TEXCOORD; float3 NormalWS: NORMALWS; float4 PositionWS: POSITIONWS; float3 TangentWS: TANGENTWS; float3 BitangentWS: BITANGENTWS;}; structPSInput { float4 PositionSS : SV_Position; float2 TexCoord: TEXCOORD; float3 NormalWS: NORMALWS; float4 PositionWS: POSITIONWS; float3 TangentWS: TANGENTWS; float3 BitangentWS: BITANGENTWS;}; structPSOutput { float3 NormalWS: SV_TARGET0; float4 DiffuseAlbedo: SV_TARGET1; float3 SpecularAlbedo: SV_TARGET2; float3 PositionWS: SV_TARGET3;}; Added by WILF CS MEANS clip space (not camera space)… WS MEANS world space… SS MEANS screen space (camera space)… SV_Position means x/y are texture coordinates rather than deuce box -1/+1 coordinates (even though the vertex shader computes it as clip coordinates) Added WS by WILF 4-way MRT (multiple render targets)

  34. Hieroglyph3: The G-Buffer Rendering Shader VSOutputVSMain (in VSInput input) { VSOutput output; //All except PositionCS is converted to world space. //Convert position and normal to world space.Output.PositionWS = mul (input.Position, WorldMatrix).xyz;output.normalWS= normalize (mul (input.Normal, (float3x3) WorldMatrix)); //Build the tangent frame vectors. output.TangentWS= (normalize (mult (input.Tangent.xyz), (float3x3) WorldMatrix);output.BitangentWS= (normalize (mult (input.Bitangent.xyz), (float3x3) WorldMatrix); //Calculate the clip space position. output.PositionCS = mul (input.Position, WorldViewProjMatrix); //Pass along the texture coordinate.Output.TexCoord = input.TexCoord; return output;} Note that it’s just as easyto convert everything into CAMERA space to match what we did when computing ambient occlusion Code and comments slightly modified by Wilf

  35. Hieroglyph3: The G-Buffer Rendering Shader PSOutputPSMain (in PSInput input) { VSOutput output; //Sample the diffuse map. float3 diffuseAlbedo = DiffuseMap.Sample (AnisoSampler, input.TexCoord).rgb; //Build the tangent frame. float3x3 tangentFrameWS = float3x3 (normalize (input.TangentWS), normalize (input.BitangentWS), normalize (input.NormalWS)); //Sample the tangent space normal map and convert to vector. float3 normalTS = NormalMap.Sample (AnisoSampler, input.TexCoord).rgb;normalTS = normalize (normalTS * 2 – 1); //Convert from 0/1 to -1/+1 coords. //Convert from tangent space to world space. Float3 normalWS= mul (normalTS, tangentFrameWS); //Output the g-buffer. output.NormalWS = float4 (normalWS, 1.0);output.DiffuseAlbedo = float4 (diffuseAlbedo, 1.0);output.SpecularAlbedo = float4 (specularAlbedo, SpecularPower);output.PositionWS = float4 (input.PositionWS, 1.0); return output;} WS MEANS world space… TBNWS matrix support normal mapping Shader variables

  36. 95.4501 Pass 2 of Standard Deferred Renderers: The Light Pass

  37. Hieroglyph3: The Light Rendering Shader • The frame buffer is set up to draw into a lightmap texture initially all black using an additive blend (1 * source + 1 * destination)… • The engine draws the light shapes one by one where a point light is a sphere, a spot light is a cone, and a directional light is full screen quad (since you can’t place it anywhere)… • The “.cpp” code is • for all lights in world dodraw light shape via light rendering shader Warning: There is a problem drawing light shapes. We’ll address it later…

  38. Other Changes • The demo provides one shaderwith macros that are externally defined. • By compiling the shader ONCE for each light type, it gets the effect of having multiple shaders. • We’ll add an extra lightType variable to the shader so we can use one shader... Lights.hlsl

  39. Hieroglyph3: The Light Rendering Shader //Vertex shader and pixel shader for drawing lights in a STANDARD//deferred renderer (SLIGHTLY MODIFIED BY WILF) //The following 4 textures make up the g-buffer... Texture2D NormalWSTexture : register (t0);Texture2D DiffuseAlbedoTexture : register (t1);Texture2D SpecularAlbedoTexture : register (t2);Texture2D PositionWSTexture : register (t3); cbufferLightParameters { float3 LightPositionWS; float3 LightColor; float3 LightDirectionWS; float2 SpotlightAngles; float LightRadius; intLightType;}; cbufferCameraParameters { float3 CameraPositionWS; }; Added WS by WILF In world space… Added WS by WILF Changed by WILF Added by WILF Added WS by WILF

  40. Hieroglyph3: The Light Rendering Shader structVSInput { float4 Position : POSITION;}; structVSOutput { float4 PositionCS: SV_Position; }; VSOutputVSMain (in VSInput input) { //Calculate the clip space position. output.PositionCS = mul (input.Position, WorldViewProjMatrix); return output;} Doesn’t really do anything (other than converting to clip space)

  41. Hieroglyph3: A Soft Spotlight #define clamp01 saturate #define innerAngleAsCosineSpotlightAngles.x /* larger angle */ #define outerAngleAsCosineSpotlightAngles.y /* smaller angle */ float spotLightAttenuation (float3 toLight) { //Spotlight specific attenuation for inside/outside spot light zone. float pixelAngleAsCosine= dot (-toLight, LightDirectionWS); //Before clamping, >1 if > inner; < 0 if < outer; 0 to 1 otherwise. return clamp01 ( (pixelAngleAsCosine– outerAngleAsCosine) / (innerAngleAsCosine – outerAngleAsCosine ));} bright area inner 1 outer 2 fuzzy area WILF: Tricky to Decipher intensity 0 outside outer zone, 0 to 1 between outer and inner zone (fuzzy area), 1 in inner zone (bright area)

  42. Hieroglyph3: The Light Rendering Shader #define POINT_LIGHT 0#define DIRECTIONAL_LIGHT 1#define SPOT_LIGHT 2 void readGBufferAttributes (float2 screenPosition, out float3 pixelPositionWS, out float3 normalWS, out float3 diffuse, out float3 specular, out float specularPower) { int3 coordinate = int3 (screenPosition.xy, 0); //So we use LOD 0... pixelPositionWS = PositionWSTexture.Load (coordinate).xyz;normalWS = NormalWSTexture.Load (coordinate).xyz;diffuse = DiffuseAlbedolTexture.Load (coordinate).xyz; float4 fullSpecular= SpecularAlbedoTexture.Load (coordinate); specular = fullSpecular.xyz; specularPower = fullSpecular.w;} WILF: Enum instead of bool Pick up all g-buffer attributes via 2D screenPosition

  43. Hieroglyph3: The Light Rendering Shader float4 lightingFor (intlightType,in float3 pixelPositionWS, in float3 normalWS, in float3 diffuse, in float3 specular, in float specularPower) { float3 toLight; float attenuation; //To be computed 3 ways... switch (lightType) { case POINT_LIGHT:toLight = LightPositionWS – pixelPositionWS; float3 distance = length (toLight); toLight /= distance; //normalizeattenuation = max (0.0, 1.0 – distance/lightRadius); break; case DIRECTIONAL_LIGHT:toLight = -LightDirectionWS; attenuation = 1.0; break; case SPOT_LIGHT:toLight = LightPositionWS – pixelPositionWS; float3 distance = length (toLight); toLight /= distance; //normalizeattenuation = max (0.0, 1.0 – distance/lightRadius);attenuation *= spotLightAttenuation (toLight); break; } same continued

  44. Hieroglyph3: The Light Rendering Shader //Calculate light visibility. float visibility = clamp01 (dot (normalWS, toLight)); //Calculate the specular term. float3 toCamera = CameraPositionWS – pixelPositionWS; float3 halfwayVector = normalize (toLight + toCamera); float3 specularity = pow (clamp01 (dot (normalWS, halfwayVector), specularPower) *specular; return //Convert float3 to opaque float4 result... float4 (visibility * LightColor * (diffuse + specularity) * attenuation, 1.0);} Not much different than our lighting routines but has 3 types.

  45. Hieroglyph3: The Light Rendering Shader structPSInput { float4 screenPosition : SV_Position;}; float4 PSMain (PSInputinput) : SV_Target0 { float3 pixelPositionWS; float3 normalWS; float3 diffuse, float3 specular; float specularPower; readGBufferAttributes (input.screenPosition.xy, pixelPositionWS, normalWS, diffuse, specular, specularPower); return lightingFor (lightType,pixelPositionWS, normalWS, diffuse, specular, specularPower) ; } SV_Position means x/y are texture coordinates rather than deuce box -1/+1 coordinates (even though the vertex shader computes it as clip coordinates) For a red light, this would draw 1 red pixel. When the next light draws, it might draw a green pixel at the same place which is blended onto the lightmap texture (to give yellow = red + green)

  46. An Example Light Shape • All triangles are outward facing • To draw front faces, enable back face culling. camera • To draw back faces, enable front face culling. camera

  47. Drawing a Light Shape • What’s so hard about drawing a light shape? A wall needs to go red if it’s IN a red light... Should notdraw on walls(not touching it) camera Both Should draw on walls(red part) tough case tough case Do you draw front faces or back faces? problem camera camera

  48. Presentation Deviation • Original technique given in terms of complex stencil buffer rules. • We provide those rules but will skip them so we can present a simpler approach that doesn’t need the stencil buffer... • But, like for the ambient occlusion demo, we need to be using camera space for everything instead of world space. • We’ll assume shaders can be rewritten to use camera space instead...

  49. Drawing a Light Shape: One Way Via Stencil Buffer (Conceptually, a Mask) • Need a shape with outward-facing faces. Initially, mask for each pixel cleared to 0. Draw with z-buffer testing and writing disabled. • 1st stencil draw: Draw only front faces on mask with rule: “If pixel behind z-buffer, set mask 1”. • 2nd color draw: Draw only back faces on non-mask with rule: “If mask 0 and pixel behind z-buffer, draw”. In any case, reset mask to 0. Wilf SKIP THIS This is SIMILAR but NOT IDENTICAL to what all published deferred renderers seem to do including this one.

  50. Drawing a Light Shape 1st stencil draw: Draw only front faces on mask with rule: If pixel behind z-buffer, set mask 1. RULE OUT WHERE FRONT FACES ARE BEHIND Z-BUFFER. 2nd color draw: Draw only back faces on non-mask with rule: If mask 0 and pixel behind z-buffer, draw. In any case, reset mask to 0. RULE IN BACK FACES BEHIND Z-BUFFER. RULE IN RULE OUT Should notdraw on walls(not touching it) camera Both Should draw on walls(red part) Wilf SKIP THIS camera camera

More Related