Vertex and Pixel Shaders: Making the world safe for Computer Graphics Adrian Perez 15-463: Computer Graphics 2 February 27th, 2001
Download ReportTranscript Vertex and Pixel Shaders: Making the world safe for Computer Graphics Adrian Perez 15-463: Computer Graphics 2 February 27th, 2001
Vertex and Pixel Shaders: Making the world safe for Computer Graphics Adrian Perez 15-463: Computer Graphics 2 February 27th, 2001 Administrivia Homework 1 will be handed back on Thursday Midterm is next Tuesday Review for midterm is this Thursday. Talk Outline Motivation for vertex/pixel shaders Vertex Shaders Implementation in DX8 Examples Pixel Shaders Implementation in DX8 Examples Integration with other areas of DX8 But First…holy war update Direct3D won. Get over it. OpenGL cannot accommodate the speed at which the graphics industry is moving now. All of the extentions to do things like vertex and pixel shading are vendor-specific. Direct3D stopped sucking a few versions ago anyway. Transformation and Lighting The way D3D used to be was fixedfunction Unlit primitives (objectspace position/normal/material/uv’s) Lit primitives (objectspace position/color/uv’s) Transformed-and-lit primitives (screenspace position/color/uv’s) Transformation and Lighting The Good Provided a mechanism for people to roll their own T&L (back when everybody did so) The Bad Restrictive in function. You were bound to D3D’s lighting model and transformation paradigm; not a terribly big deal for awhile Transformation and Lighting Games these days want more control over the hardware Important because otherwise, every game is going through the same code path, making them look very similar Especially important since hardware is getting unfucking-believably fast Microsoft and nVidia realized that a more generic way for applications to perform transformation and lighting was needed Enter Vertex Shaders A Vertex Shader is essentially assembly language for the T&L engine Subset of most ASM languages: no branching, for example If hardware T&L is available, the op-codes are just downloaded to the chip and run natively The op-codes are interpreted by a surprisingly fast software implementation if T&L hardware isn’t available Enter Vertex Shaders The Good Amazingly powerful You are not bound to provide it any specific data as input, as you are writing the handling code Much more precision – everything is in floating point The Bad Hard to debug and grok We’re right back in assembly hacking land Vertex Shader Registers Input Registers Output Registers Name Count R/W Name Count R/W an 1 scalar W only oDn 2 vectors W only c[n] 96 vectors R/W oFog 1 scalar W only rn 12 vectors R/W oPos 1 vector W only vn 16 vectors R only oPts 1 scalar W only oTn 4 vectors W only note: all vectors are 4 floats Vertex Shader Instructions add dp3 dp4 dst expp lit logp mad max min mov mul rcp rsq Sum Three-components dot-product Four-component dot-product Distance vector Exponential 10-bit precision Lighting coefficients Logarithm 10-bit precision Multiply and add Maximum Minimum Move Multiply Reciprocal Reciprocal square root sge slt sub def vs exp frc log m3x2 m3x3 m3x4 m4x3 m4x4 Set on greater or equal than Set on less than Subtract Define Constants Version and Type Exponential base2 full precis. Fraction Logarithm base 2 full precision 3×2 vector matrix multiply 3×3 vector matrix multiply 3×4 vector matrix multiply 4×3 vector matrix multiply 4×4 vector matrix multiply Vertex Shader Semantics Shaders are defined in a separate source file. They are ‘compiled’ into bytecode (at runtime, if you wish) and then the bytecode can be loaded onto the card. When you render, you choose a vertex shader to use Fixed-function pipeline is still available (as a hard-coded vertex shader) Vertex Shader Examples Vertex Shader Examples #include "Constants.h" // v0 -- position // v1 -- normal // v2 -- tex coord vs.1.0 // compute world space position dp4 r1.x, v0, c[CV_WORLD_0] dp4 r1.y, v0, c[CV_WORLD_1] dp4 r1.z, v0, c[CV_WORLD_2] dp4 r1.w, v0, c[CV_WORLD_3] // transform position dp4 oPos.x, v0, c[CV_WORLDVIEWPROJ_0] dp4 oPos.y, v0, c[CV_WORLDVIEWPROJ_1] dp4 oPos.z, v0, c[CV_WORLDVIEWPROJ_2] dp4 oPos.w, v0, c[CV_WORLDVIEWPROJ_3] // vector from point to eye add r2, c[CV_EYE], -r1 // transform normal dp3 r0.x, v1, c[CV_WORLD_IT_0] dp3 r0.y, v1, c[CV_WORLD_IT_1] dp3 r0.z, v1, c[CV_WORLD_IT_2] // normalize normal dp3 r0.w, r0, r0 rsq r0.w, r0.w mul r0, r0, r0.w // normalize e dp3 r2.w, r2, r2 rsq r2.w, r2.w mul r2, r2, r2.w // e dot n dp3 oT1.x, r0, r2 // l dot n dp3 oT0.x, r0, c[CV_LIGHT_DIRECTION] Vertex Shader Examples Vertex Shader Examples ; Distorts vertices in eye-space to give a fish-eye lens effect #include "trees.h" #define FACTOR_KPLUS1 c[CV_CONSTANTS].x #define XYZW_MAX_XZRATIO x #define XYZW_FACTOR_K y #define XYZW_ZERO z #define XYZW_ONE w vs.1.0 ; Transform position to view space dp4 r0.x, v0, c[CV_WORLDVIEW_0] dp4 r0.y, v0, c[CV_WORLDVIEW_1] dp4 r0.z, v0, c[CV_WORLDVIEW_2] dp4 r0.w, v0, c[CV_WORLDVIEW_3] ; scale x and y, set z and w to 0 mul r1, r0, c[CV_FISHEYEINFO].xxzz ; compute normalized distance from camera (camera in viewspace is alwasy at (0,0,0)) ; r1.x = sqrt(x^2 + y^2)/z dp3 r1.x, r1, r1 rsq r1.y, r1.x mul r1.y, r1.y, r0.z rcp r1.x, r1.y ; and take the absolute value max r1.x, r1.x, -r1.x ; compute (k*d + 1) mad r1.z, r1.x, c[CV_FISHEYEINFO].XYZW_FACTOR_K, c[CV_FISHEYEINFO].XYZW_ONE ; compute (k+1)/(k*d + 1) -- this is the reciprocal formula of the ; above referenced web-page because our distances are ; generally not less than 1.0! rcp r1.z, r1.z mul r1.xy, FACTOR_KPLUS1, r1.z ; only scale the original x, y with this factor mul r0.xy, r0, r1 ; transform new position to clip space dp4 oPos.x, r0, c[CV_PROJ_0] dp4 oPos.y, r0, c[CV_PROJ_1] dp4 oPos.z, r0, c[CV_PROJ_2] dp4 oPos.w, r0, c[CV_PROJ_3] ; Draw using supplied tree color mov oD0.xyzw, v1 mov oT0.xy, v2 Vertex Shader Examples One Last Example… One Last Example… vs.1.0 ; Projected Textures ; Adrian Perez ; 2/27/01 ; Constants: ; c0-c3 - World+View+Projection matrix ; c4-c7 - Texture matrix 1 ; c8 - Color ; c9 - 1.0 ; c10 - -0.5's for adjusting the texture coordinate ; c11 - Texture position 1 (worldspace) ; c12-c15 - world->model matrix ; Transform position m4x4 oPos, v0, c0 ; r3: the light positoin in worldspace mov r3, c11 ; Set r0 to the clip-space view from the texture light m4x4 r0, v0, c4 ; Normalize r5 with r6 mul r5.xyz, r5.xyz, r6.xyz ; Fill r1 with 1's mov r1, c9 ; Compute two recriprocals to do perspective correction rcp r1.xy, r0.z ; r6: Compute a dot product to find the diffuse light dp3 r6.x, r5, v3 ; Apply reciprocals mul r2, r0, r1 ; subtract 0.5's to adjust the texture coordinates add r2.xy, r2.xy, c10.xy ; r4: the light position in modelspace m4x4 r4, r3, c12 ; r5: subtract the model-space position to get a light vector sub r5, r4, v0 ; r8: store the temp length dp3 r8.w, r5, r5 ; r6: reciprocal square root of the scalar rsq r6.xyzw, r8 ; modulate r6 by the diffuse color mul r6, r6.xxxx, c8 ; Write out the color and texture mov oD0, r6 mov oT0, r2 Pixel Shaders Same idea as vertex shaders, but they control how textures and colors are combined per-pixel Currently there is no hardware that implements them The GeForce3 (when it comes out) will do them, so will the XBox Pixel Shaders The Good Explicit control of texture combining Lots of Nifty Tricks (EMBM) The Bad Designed for a more general piece of hardware; a lot of the functionality of the GeForce3 is not exposed Pixel Shader Registers Name I/O Min. Number Max/Inst Source cn Read-only 8 2 API call rn Read/write 2 2 Written tn Read/write 4 1 Textures vn Read-only 2 1 Vertex Colors Pixel Shader Instructions add Add cnd Conditional dp3 Three-Component Vector DotProduct lrp Linear Interpolation Blend mad Multiply and Add mov Copy Source Into Destination mul Modulate sub Loads the difference of the two colors in the source operands. tex No Modification texbem Bump Environment Map texbeml Bump Environment Map with Luminance texcoord Texture Coordinate texkill Mask Out Pixel texm3x2pad Input to 3×2 Matrix Multiply texm3x2tex 3×2 Matrix Multiply Result texreg2ar Remapping Alpha and Red Components texreg2gb Remapping Green and Blue Components texm3x3pad Input to 3×3 Matrix Multiply texm3x3spec Specular Reflection and Environment Mapping texm3x3tex 3×3 Matrix Multiply Result texm3x3vspec Specular Reflection/Environment Mapping without Constant Eye Vector Pixel Shader Examples Unfortunately, right now the only way to develop pixel shader apps is to use the Reference Rasterizer. So source on how to use it is pretty scarce The documentation is also pretty cryptic, it’s not nearly as wellengineered as vertex shaders are Pixel Shader Examples Pixel Shader Examples Other Cool Shit in DX8 N-Patches Subdivision scheme that requires no adjacency information. You provide a set of vertices and vertex normals, and it renders a smooth mesh. Neat: You send the base level mesh down to the card, and your vertex shader gets fed the subdivided vertices. This is one good way to get around the fact that you can’t create new vertices in a shader Bezier surfaces Yea, yea… they’re not as cool as N-Patches N-Patches Other Cool Shit in DX8 Volume Textures Holy crap these things fucking rock Finally, an elegant way to handle explosions and rocket flares Plus a million other tricks Third texture coordinate, they behave almost exactly like 2D textures Other Cool Shit not in DX8 Shadow Mapping Supported by the GeForce3, but the functionality is not exposed by DX8. And yes, it is exposed in OpenGL. (sigh…) Conclusion DirectX 8.0 is the fucking bomb. Questions? ? ? ?