Download Presentation
## 95.4501

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -

**95.4501**Review**Getting Started**• Shader lights have generally been covered in other courses… • We still need some notion of lights with any advanced topic. • Let’s develop a simplistic library for subsequent use… and in the process get a quick refresher… Lighting For Dummies**Keep in Mind: Understandability is Key**• Code full of math is generally produced by novices. • You need math but programming is about providing abstractions that make it understandable in terms of the domain. if (dot (cross(a,b),c) > 0.01… if (normal (side1,side2).alignedWith (toLight) … Doom Engine Died From Lack Of Understandability**95.4501**Math for Dummies**c’s height**c q c’sshadow Math for Dummies • Properties of projections: c’s shadow = c cosq c’s height = c sin q • Properties of cosine: • Properties of high powers: cosq = 1’s shadow q = 0 +1 aligned with q = 90 0 q = 180 -1 aligned against 1 q c b q a cosq = a / c 1100 1 0.9100 0.9 * 0.9 * 0.9 … 0.9 0 c cosq = a traditional**Illustrating “c’s shadow = c cosq” and “c’s**height” • What’sx,y,a1,b1,ab B y b1 1 b x b2 A B a1 a2 a**Math for Dummies**Properties of the sign of dot product (a number): U.V = u1v1 + u2v2 + u3v3 U.V = |U| |V| cosq where q Î [0, 180°] cos 0° = 1 cos 90° = 0 cos 180° = -1 U U U q q q V V V q < 90°U.V > 0 q = 90° U.V = 0 q > 90° U.V < 0 aligned with perpendicular aligned against**Math for Dummies**Dot products as projection lengths: U.V = |U| |V| cosq where q Î[0, 180°] If V is a unit vector, (U.V) V Is the projection of U on V U V q U U cosq**95.4501**Transformation Spaces for Dummies**The transformation Pipeline**• The transformation pipelineWC-1P. • p WC-1P projection space (4D) camera or view space (3D) world space (3D) local or model space (3D) + tangent space Each space is a different coordinate system. We’ll be using a right handed system if we can.**Texture Coordinate Space (Or Tangent Space)**In texture, x goes right, y goes up, z goes out, Artist Terminology v bitangent y x tangent u at least in a right-handed system w normal z**All Spaces are 3D Spaces**• Front in texture space might look like Texture coordinates ranging from 0.0 to 1.0 • Side view might look like noseT = [0.5, 0.5, -0.3] T for tangent (texture) spaced**In Vertex (Model) Space**• You might have a box whose center is the origin... Coordinates are in meters. Suppose it’s a 10 meter wide box. The texture is upside down, so the tangent space origin is the front top left corner Twisted a bit so we can see the left side... Coordinate system origin at the center of the object noseM = [-5+0.3, 0, 0] = = [-4.7, 0, 0] M for model space**In World Space**• To place the box in the world, you could rotate it 180 degrees around y and translate right 1 meter... Twisted a bit so we can see the rightside... Coordinate system origin is 1 meter to the left of the center of the object noseW = [4.7+1, 0, 0] = [5.7, 0, 0] W for model space**It makes no sense to perform math on points/vectors from**different spaces noseT = [0.5, 0.5, -0.3] noseM = [-4.7, 0, 0] noseW = [+5.7, 0, 0] • Spaces T(angent) M(odel) W(orld) C(amera) P(erspective) • Units 0/+1uv meters meters meters -1/+1 persp. • ForwardConverters TBN World View Perspective • Backward Converters (inverses) TBN-1 World-1 View-1 Perspective-1 If p = qM, then qM = p qMM-1 = pM-1 q = pM-1**95.4501**Lights for Dummies**Lighting Components**• AmbientKa background • DiffuseKd dull light contribution (with shadow) • SpecularKsshinyness light contribution**Ambient lighting**• Usually define via material constant Ka. • We’ll use a demo dependent implemention. float4 Ka () {return g_materialAmbientColor;} or float4 Ka () {return g_vMaterial * g_vLightAmbient;} float4 ambientColor () {return Ka ();}**Diffuse Directional Lighting**• Diffuse directional lighting: Kd max (0, n.L) n L aligned with aligned against(no contribution) L • n is the pixel (or face) normal.L is a “to light” vector (usually normalized).**Diffuse lighting: Kd max (0, n.L)**• Usually define via material constant Kd. • We’ll use a demo dependent implemention. float4 Kd () {return g_materialDiffuseColor;} or float4 Kd () {return g_vMaterial * (1 - g_vLightAmbient);} float4 diffuseColor (float3 pixelNormal, float3 normalizedToLight) {return Kd () * clamp01 (dot (pixelNormal, normalizedToLight));}**Diffuse lighting: If there are shadows**float4 diffuseColor (float3 pixelNormal, float3 normalizedToLight, float shadowIntensity) { return diffuseColor (pixelNormal, normalizedToLight) * shadowIntensity;}**For Spotlights: Need a cone angle q.**q pixel outside light cone P L • P is the “to pixel” point.L is a “from light” vector (usually normalized).q is the angle outward from the light vector… Warning: normally, we use a toLight vector**Is a point in the spotlight?**A.B = |A||B| cosq = cosq if |A| = |B| = 1cos 90° = 0, cos 45° = 0.707, cos 0° = 1 In spotlight from 45° to 0° (> 0.707). A.B > 0.707 means theangle is 45° OR LESS q L P cos 0° = 1 cos 35° = 0.8 cos 45° = 0.7 cos 55° = 0.5 cos 65° = 0.4 55° P in 0° 35° 45° 65° P out Inside if P’s cone angle as Cosine > lights Cone angle as Cosine boolinSpotLight (float3 normalizedPixelToLight, float3 normalizedToLightVector, float coneAngleAsCosine) {//Negating each of the above unit directions A and B makes them point away from the light. //Note: -A.-B = A.B = |A||B| cos angle = cos angle. cos 45° = 0.707, cos 0° = 1 return dot (normalizedPixelToLight , normalizedToLightVector ) > coneAngleAsCosine;}**Specular lighting: 2 Models for WHEN we see HIGHLIGHT**L is “to light” C is “to camera”R is reflection of -L H is (L+C)/2 n is pixel normal Phong Blinn-Phong L L R R n n H C C Reflected light R aligns with camera direction C Halfway vector H aligns with normal n**Specular lighting: The mathematical definition**Phong Blinn-Phong • Phong model: Ks max (0,(C.Reflect(-L,n))) • i.e., reflected -L aligns with C. • Blinn-Phong: Ks max (0,Halfway(C,L).n)) • i.e., average of C and L aligns with n. L L R R n n H C C**Specular lighting**• Usually define via material constant Ks. • We’ll use a demo dependent implemention. float4 Ks () {return g_materialSpecularColor ;} or float4 Ks () {return float4 (0,0,0,0);} //i.e., no specular**Specular lighting: Blinn-Phong**• float4 specularColor (float3 pixelNormal, float3 normalizedToLight, float3 normalizedToCamera) { • //Uses Blinn-Phong’s halfway vector… float3 halfway = normalize (normalizedToLight+normalizedToCamera); float intensity = pow (clamp01 (dot (halfway, pixelNormal)), g_SpecularExponent); • return Ks () * intensity;}**Combining ALL lighting components**• Multiply texture color by (ambient + diffuse) • Add specular color as an extra… float4 combinedColor (float4 textureColor, float3 normal, float3 toLight, float3 toCamera , float shadowBrightness) { //All vectors must be normalized… return textureColor * (ambientColor () + diffuseColor (normal, toLight, shadowBrightness)) + specularColor (normal, toLight, toCamera); } float4 combinedColor (float4 textureColor, float3 normal, float3 toLight, float3 toCamera) { return combinedColor (textureColor, normal,toLight,toCamera , 1.0) }**95.4501**Shader Concepts for Dummies**Older shaders**• Early GPU work on 2x2 pixels in parallel running in lock step. • This was to allow gradients to be computed on any variable by taking neighbor differences. • This is used internally by tex2D to compute the mipmap level to use. • Dynamic branching breaks lock stepping requiring subsequent access to use tex2DLOD or tex2Dgrad instead.**3 Vertex Shaders + thousands of Pixel Shaders**A2 X = A + (B-A)t where t = delta pixels / total pixels; e.g., 57/200. • Use flat top/bottom rectangle. • Interpolate outside edges. • Interpolate inside (scanlines) 200 total pixels 57 pixels X1 Xinside X2 A1 A4 Interpolation formula A3 Perspective correct interpolationinterpolates A1/z1 to A2/z2 to get A (along with 1/z1 to 1/z2 to get Z) AND divides to get value without z.**Interpolating Vectors Changes the length**• Consider V1 + (V2-V1) * t where t = 0.5. • V1+ (V2 -V1) * 0.5 • = V1+ 0.5 * V2 – 0.5 * V1 • = 0.5 * V1+ 0.5 * V2 • = 0.5 * (V1 + V2) • = average of V1 and V2. Average = [0.0, 0.25, 0.0] NOT unit length V1 = [- 0.968, 0.25, 0.0] V2= [+0.968, 0.25, 0.0] unit length unit length 0.9682+ 0.252 = 0.9375 + 0.0625 = 1**95.4501**STOP Rest is Unfinished**95.4501**DirectX11**Credits**• Some of this information comes from http://www.directxtutorial.com. • Some comes from http://rastertek.com which provides a tutorial by building a simplified game engine. • Additional information comes from “Practical Rendering & Computation with DirectX11, Zink, Pettineo, and Hoxley, CRC Press, 2011.**The Swap Chain**• Theswap chain is the object representing a chain of buffers, swapping position pointers each time a new frame is rendered. front butter back butter What you currently see What you are drawing for next time Usage: flip the 2 pointers &front butter &back butter**Can Have More Than 2 Buffers**front butter back butter third butter beforeflipping 1 2 3 http://rastertek.com afterflippingonce 1 2 3 afterflippingtwice 1 2 3 What you are drawing for next time What you are drawing for next time What you currently see**Programming Details**• Several things are needed to start the ball rolling... • windowHandle: from windows • device (“the graphics card”): who you talk to for creating objects • deviceContext: who you talk to for performing some action • a swap chain: buffer flipper • render target view for a texture resource • depth stencil view for a depth stencil buffer**Programming-Wise**• Somwhere, you’ll need variables such as • ID3D11Device *device; • ID3D11DeviceContext *deviceContext; • IDXGISwapChain *swapchain;**Object creation often require description objects of the**appropriate type for submission to the create operation. • Objects so created are reference counted and must subsequently be disposed of via a release operation.**Sample from rastertek.com**//Code to determine screen’s refresh rate (DETAILS NOT SHOWN)... numerator = displayModeList[i].RefreshRate.Numerator; denominator = displayModeList[i].RefreshRate.Denominator; DXGI_SWAP_CHAIN_DESC swapChainDescription; //Initialize the swap chain description. ZeroMemory (&swapChainDescription, sizeof (swapChainDescription)); //Set to a single back buffer. swapChainDescription.BufferCount= 1; //Of back buffers (excludes front buffer) //Set the width and height of the back buffer. swapChainDescription.BufferDesc.Width = screenWidth; swapChainDescription.BufferDesc.Height= screenHeight; //Set regular 32-bit surface for the back buffer. swapChainDescription.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //Interpretable as float 0.0 to 1.0. used on next slide**Sample from rastertek.com**//Set the refresh rate of the back buffer. If (m_vsync_enabled) { swapChainDescription.BufferDesc.RefreshRate.Numerator = numerator; swapChainDescription.BufferDesc.RefreshRate.Denominator = denominator; } else { swapChainDescription.BufferDesc.RefreshRate.Numerator = 0; swapChainDescription.BufferDesc.RefreshRate.Denominator = 1; } //Set the usage of the back buffer. swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //Set the handle for the window to render to. swapChainDescription.OutputWindow = windowsHandle; //Turn multisampling off. swapChainDescription.SampleDesc.Count = 1; //multisamples per pixel swapChainDescription.SampleDesc.Quality = 0; important**Sample from rastertek.com**//Set to full screen or windowed mode. swapChainDescription.Windowed = ! fullscreen; //Set the scan line ordering and scaling to unspecified. swapChainDescription.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDescription.BufferDesc.Scaling= DXGI_MODE_SCALING_UNSPECIFIED; //Discard the back buffer contents after presenting. swapChainDescription.SwapEffect= DXGI_SWAP_EFFECT_DISCARD; //Don't set the advanced flags. swapChainDescription.Flags= 0; //Such as DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH //Set the feature level to DirectX 11. D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; //Create the swap chain, Direct3D device, and Direct3D device context (ALL at once) HRESULT result = D3D11CreateDeviceAndSwapChain (NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDescription, &m_swapChain, &m_device, NULL, &m_deviceContext); If (FAILED (result)) {return false;} //Success or failure (caller quits if it fails) which card to use software mode**Summary**D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; HRESULT result = D3D11CreateDeviceAndSwapChain (NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDescription, &m_swapChain, &m_device, NULL, &m_deviceContext); If (FAILED (result)) {return false;} //Success or failure (caller quits if it fails) SOMEWHERE IN YOUR DESTRUCTOR OR IN A CLOSEDOWN METHOD... • m_swapChain >Release ();m_device >Release ();m_deviceContext >Release (); WHEN DRAWING IS FINISHED, PERFORM A FLIP... • m_swapChain >Present (0, 0); next one immediately Assuming you have the following directories in VS2010 $(DXSDK_DIR)Include;$(IncludePath)$(DXSDK_DIR)Lib\x86;$(LibraryPath)**Rendering Frames: What You Need**multiple render targets MRT • One or more drawing areas to draw called render target views: back buffer versus texture render target views). • One depth/stencil view. • What part of the rectangular area to draw into. A FRAMEBUFFER is a concept used to denote the collection of views (so there are at least 2, 1 drawing target and 1 depth/stencil).**Rendering Frames: Multiple Frame Buffers**• Drawing into a texture and drawing onto the screen requires 2 frame buffers; i.e., 2+2 views. one for one for copied from directxtutorial.com**RenderTargets**ID3D11RenderTargetView* backbufferRenderTarget; ID3D11RenderTargetView* textureRenderTarget; A render target view is a FRAMEBUFFER comprised of 1 or more drawing textures (actually views) and a combined depth+stencil texture (actually a view)**Creating BackBufferRenderTargets**ID3D11RenderTargetView* backbufferRenderTarget; ID3D11RenderTargetView* textureRenderTarget; ID3D11Texture2D *backBufferTexture; swapchain->GetBuffer (0 /*First back buffer*/, __uuidof (ID3D11Texture2D), (LPVOID*) &backBufferTexture); • device->CreateRenderTargetView (backBufferTexture, NULL, &backbufferRenderTarget); backBufferTexture->Release();**Creating Texture RenderTargets: First Create a Texture**ID3D11Texture2D* renderTargetTexture; //Store it somewhere... //Initialize the render target texture description.D3D11_TEXTURE2D_DESC textureDescription;ZeroMemory(&textureDescription, sizeof(textureDescription)); //Setup the render target texture description.textureDescription.Width = textureWidth;textureDescription.Height = textureHeight;textureDescription.MipLevels = 1; //0 means alltextureDescription.ArraySize = 1;textureDescription.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;textureDescription.SampleDesc.Count = 1; //No MSAAtextureDescription.Usage = D3D11_USAGE_DEFAULT;textureDescription.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;textureDescription.CPUAccessFlags = 0;textureDescription.MiscFlags = 0; //Create the render target texture.device->CreateTexture2D (&textureDescription, NULL, &renderTargetTexture); first create a texture ignoring error code**Create Texture RenderTargets: Then The RenderTarget or View**ID3D11RenderTargetView* backbufferRenderTarget; ID3D11RenderTargetView* textureRenderTarget; ID3D11Texture2D* renderTargetTexture; //Store it somewhere... //Setup the description of the render target view.D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDescription;renderTargetViewDescription.Format= textureDescription.Format;renderTargetViewDescription.ViewDimension= D3D11_RTV_DIMENSION_TEXTURE2D;renderTargetViewDescription.Texture2D.MipSlice = 0; //Use mipmap level 0 //Create the render target view.device->CreateRenderTargetView (renderTargetTexture, &renderTargetViewDescription, &textureRenderTarget));