Shader Language (Cg, © nVIDIA)
Transcription
Shader Language (Cg, © nVIDIA)
Shader Language (Cg, © nVIDIA) 2 Graphics Pipeline Geometry Picture Graphics Pipeline Geometry Transform Light Clip Setup Blend Rasterize Texture Z-test Framebuffer Picture Graphics Pipeline Vertex Connectivity Vertex Shader Primitive Assembly Textures Texture Clip & Setup Blend Rasterize Fragment Shader Raster OPs Framebuffer Picture Graphics Pipeline Vertex Connectivity Vertex Shader Primitive Assembly Textures Texture Clip & Setup Blend Rasterize Fragment Shader Raster OPs Framebuffer Picture Bottlenecks Too many operations Parallelize Too many memory accesses Parallelize SCREEN TILE XBAR GEOMETRY OPERATIONS FRAGMENT OPERATIONS SCREEN TILE SCREEN TILE Parallelization Distribute computation to processors Work allocation Distribute texture to memory banks Tile Screen-pixels into memory banks Do all processors have access to all memory Distribute access/Replicate data Graphics Pipeline III Vertex Textures Connectivity Vertex Shader Rasterize Primitive Assembly Geometry Shader Fragment Shader Clip & Setup Texture Blend Raster OPs Framebuffer Picture Declaring Programs in Cg Cg program entry function can have any name: <return-type> <program-name> (<parameters>) [:<semantic-name>]{ /* ... */ } Program Inputs and Outputs GPUs operate on streams of data: A stream of vertices A stream of primitives A stream of fragments A Cg-program is executed repeatedly on a GPU: once for each element of data. Program Inputs and Outputs Two kinds of program inputs: Varying inputs: specified with each element of the stream. Eg.: color, normal per vertex or interpolated texture coordinates for fragments Uniform inputs: specified seperately from the stream Changes at lower frequency Eg.: transformation matrix for a vertex program. Varying Inputs Binding semantics Associates a meaning with the parameter POSITION NORMAL BINORMAL BLENDINDICES BLENDWEIGHT TANGENT PSIZE TEXCOORD0-TEXCOORD7 Binding semantics may implicitly specify the mapping of inputs to particular hardware registers, or tie output of one program to the input of the next struct myinputs{ float3 myPosition : float3 myNormal : float3 myTangent : float refractiveIndex : }; POSITION; NORMAL; TANGENT; TEXCOORD3; outdata foo(myinputs inData, float otherInData: TEXCOORD4) { // In program scope, the parameters are // referred to as 'inData.myPosition', //'inData.myNormal', and so on. } Varying Outputs from VS Outputs of a program are available to a subsequent program as varying inputs. Program must agree on the data being passed between them. → Binding semantics Output binding semantics: POSITION COLOR0-COLOR1 PSIZE FOG TEXCOORD0-TEXCOORD7 // Vertex Program struct myvf { float4 pout : float4 diffusecolor float4 uv0 : float4 uv1 : }; myvf foo(/*...*/){ myvf outstuff; /* .. */ return outstuff; } POSITION; : COLOR0; TEXCOORD0; TEXCOORD1; // Fragment Program struct myvf { float4 diffusecolor : COLOR0; float4 uv0 : TEXCOORD0; float4 uv1 : TEXCOORD1; }; fragout bar(myvf indata){ float4 x = indata.uv0; /* .. */ } Varying Outputs from PS Required to output a vector with COLOR semantics Some profiles support a DEPTH output As structure, as out parameters, or directly void main(out float4 color : COLOR, out float depth : DEPTH){ /*...*/ color = diffusecolor; depth = /*...*/; } float4 main() : COLOR { /* ... */ return diffusecolor; } Data Types Basic Data types: float, half, int, fixed, bool, sampler* Built-in vector data types: Support for matrices (up to 4x4) : float4 bool4 float3 float2 float1 bool3 bool2 bool1 float1x1 matrix1; float4x2 matrix3; float2x3 matrix2; float4x4 matrix4; Data Types Type conversions C-like Structs Arrays (no pointer syntax): float4x4 mymatrix[5]; Note: float M[4][4] != float4x4 M Statements and Operators Control Flow: Function calls and the return statement if/else while for Function definitions and overloading: function function function function blah1(out float x); // x is output-only blah2(inout float x); // input/output blah3(in float x); // input only blah4(float x); // input only // (default) bool same(float a, float b); bool same(bool a, bool b); Statements and Operators Arithmetic Operators: +, -, *, / Can be used on vectors as well as on scalars Eg.: a * float3(A, B, C) * float3(D, E, F) equals float3(a*A*D, a*B*E, a*C*F) Matrix operands are not supported. Use the mul() functions: matrix-column vector: mul(M, v); row vector-matrix: mul(v, M); matrix-matrix: mul(M, N); Statements and Operators Boolean and comparison operators Swizzle Operator (.) Allows the components (x,y,z,w or r,g,b,a) of a vector to be rearranged Elements can be repeated or omitted. float3(a,b,c).zyx float4(a,b,c,d).xxyy float2(a,b).yyxx float4(a,b,c,d).w yields float3(c,b,a) yields float4(a,a,b,b) yields float4(b,b,a,a) yields d Statements and Operators Texture lookup functions require at least 2 parameters: Texture sampler: Type: sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, samplerRECT. Combination of a texture image with a filter, clamp, wrap or similar configuration. Provided by the application as uniform parameters. Texture coordinate: A scaler, 2/3/4-vector, depending on the texture lookup. Statements and Operators Example: void applytex( uniform sampler2D mytexture, float2 uv : TEXCOORD0, out float4 outcolor : COLOR) { outcolor = tex2D(mytexture, uv); } Wide variety of texture-lookup functions: tex2D, texRECT, texCUBE, tex2Dproj, texRECTproj, texCUBEproj, ... Setting up Cg Cg toolkit: http://developer.nvidia.com/object/ cg_toolkit.html Link your program with the libraries: Cg and CgGL Include the core Cg runtime API: #include <Cg/cg.h> #include <Cg/cgGL.h> Initialize Cg (after initializing OpenGL) Initializing Cg First, create a context: CGcontext context = cgCreateContext(); Add the shader to the context: CGprofile myProfile = cgGLGetLatestProfile (CG_GL_VERTEX); CGprogram myProgram = cgCreateProgram( context, CG_SOURCE, "myProgram.cg", myProfile, "main", args); Pass the resulting object code to 3D API: cgGLLoadProgram(myProgram); Program Parameters Get a handle to the parameter: Cgparameter myParameter = cgGetNamedParameter(myProgram, "myParameter") Set the parameter value: cgGLSetParameter4fv(myParameter, value); Executing a Program Enable a program's corresponding profile: cgGLEnableProfile(myProfile); Bind a program: cgGLBindProgram(myProgram); Only one vertex and one fragment program can be bound at a time for a particular profile. Releasing Resources Free resources allocated for a program: cgDestroyProgram(myProgram); Free resources allocated for a context: cgDestroyContext(context); GLSL sampler InputImage; float4 main(float2 topLeft : TEXCOORD0, float2 left : TEXCOORD1, float2 bottomLeft : TEXCOORD2, float2 top : TEXCOORD3, float2 bottom : TEXCOORD4, float2 topRight : TEXCOORD5, float2 right : TEXCOORD6, float2 bottomRight : TEXCOORD7): COLOR { // Take all eight taps float4 tl = tex2D (InputImage, topLeft); float4 l = tex2D (InputImage, left); float4 bl = tex2D (InputImage, bottomLeft); float4 t = tex2D (InputImage, top); float4 b = tex2D (InputImage, bottom); float4 tr = tex2D (InputImage, topRight); float4 r = tex2D (InputImage, right); GLSL // Compute dx using Sobel operator: // -1 0 1 // -2 0 2 // -1 0 1 float dX = -tl.a - 2.0f*l.a - bl.a + tr.a + 2.0f*r.a + br.a; // Compute dy using Sobel operator: // -1 -2 -1 // 0 0 0 // 1 2 1 float dY = -tl.a - 2.0f*t.a - tr.a + bl.a + 2.0f*b.a + br.a; // Compute cross-product and renormalize float4 N = float4(normalize(float3(-dX, -dY, 1)), tl.a); // Convert signed values from -1..1 to 0..1 range and return return N * 0.5f + 0.5f; } HLSL void main( in a2v IN, out v2p OUT ) { // input parameters include view project matrix ModelViewProj, // view inverse transpose matrix ModelViewIT, // and light vector LightVec. OUT.Position = mul(IN.Position, ModelViewProj); // multiply position with view project matrix float4 normal = mul(IN.Normal, ModelViewIT); normal.w = 0.0; normal = normalize(normal); float4 light = normalize(LightVec); float4 eye = float4(1.0, 1.0, 1.0, 0.0); float4 vhalf = normalize(light + eye); // transform normal from model-space to view-space, store normalized // light vector, and calculate half angle vector. float4(1.0, 1.0, 1.0, 0.0) // is a vector constructor to initialize vector float4 eye. .xyzz, a swizzle // operator, sets the last component w as the z value. HLSL float diffuse = dot(normal, light); float specular = dot(normal, vhalf); specular = pow(specular, 32); // calculate diffuse and specular components with dot // product and pow function. float4 diffuseMaterial = float4(0.5, 0.5, 1.0, 1.0); float4 specularMaterial = float4(0.5, 0.5, 1.0, 1.0); // set diffuse and specular material. OUT.Color = diffuse * diffuseMaterial + specular * specularMaterial; } struct a2v { float4 Position : POSITION; float4 Normal : NORMAL; }; // Normal item is added for color computing. struct v2p { float4 Position : POSITION; float4 Color : COLOR0; };