390 likes | 676 Views
GPU Shading and Rendering: OpenGL Shading Language. Marc Olano UMBC. OpenGL Shading. High level language OpenGL Shading Language = GLslang = GLSL Integrated into OpenGL API (no extra run-time). Organization. API Vertex Shading Fragment Shading Lots of demos.
E N D
GPU Shading and Rendering:OpenGL Shading Language Marc Olano UMBC
OpenGL Shading • High level language • OpenGL Shading Language = GLslang = GLSL • Integrated into OpenGL API (no extra run-time)
Organization • API • Vertex Shading • Fragment Shading • Lots of demos. • 2-year old Apple PowerBook G4/1.5GHz • ATI Mobility Radeon 9700
API-integrated • Compiler built into driver • Presumably they know your card best • IHV’s must produce (good) compilers • Use built-in parameters (glColor, glNormal, …) • Add your own • Other options can still produce low-level code • Cg, ASHLI, RapidMind, … • With loss of integration
Using High-level Code • Create shader objectS = glCreateShader(GL_VERTEX_SHADER)S = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB) • Vertex or Fragment • Load shader into objectglShaderSource(S, n, shaderArray, lenArray)glShaderSourceARB(S, n, shaderArray, lenArray) • Array of strings • Compile objectglCompileShader(S)glCompileShaderARB(S)
Loading Shaders • glShaderSource(S, n, shaderArray, lenArray) • One string containing entire mmap’d file • Strings as #includes • Varying variables between vertex and fragment • Strings as lines • Null-terminated if lenArray is Null or length=-1
Using High-level Code (2) • Create program objectP = glCreateProgram()P = glCreateProgramObjectARB() • Attach all shader objectsglAttachShader(P, S)glAttachObjectARB(P, S) • Vertex, Fragment or both • Link togetherglLinkProgram(P)glLinkProgramARB(P) • UseglUseProgramObject(P)glUseProgramObjectARB(P)
Using High-level Code (3) • Where is my attributes/uniforms parameter?i=glGetAttribLocation(P,”myAttrib”)i=glGetUniformLocation(P,”myAttrib”) • Set themglVertexAttrib1f(i,value)glVertexAttribPointer(i,…)glUniform1f(i,value)
Using Low-level Code • Load shaderglProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, length, shader) • Vertex or fragment • Single string (vs. array) • EnableglEnable(GL_VERTEX_PROGRAM_ARB)
Shader debugger Immediate updates Choose model/texture Tweak parameters Examine/dump frames Several available Not hard to build OpenGL debugger Trace of calls made Examine resources Breakpoints/actions Graph performance A couple of choices Useful Tools
gDEBugger – A Professional OpenGL Debugger and Profiler • Provides graphic pipeline information needed to find bugs and to optimize application performance: • Shortens debugging and profiling time • Improves application quality • Optimizes application performance
Free gDEBugger License for Academic Users! • OpenGL ARB and Graphic Remedy Academic Program: • Annual program for all OpenGL Academic users • License of the full feature version for one year • Includes all software updates • A limited number of free licenses available fornon-commercial developers who are not in academia • More details: http://academic.gremedy.com
Non-windows OS • Linux • gDEBugger in progress • Apple OpenGL Profiler and Driver Monitor • Free part of OS / Developer tools
High-level Code void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Main Function void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Use Standard OpenGL State void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Built-in Types void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1]= Vp; gl_TexCoord[3]= vec4(Kin); }
Swizzle / Channel Selection void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Vector Construction void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Built-in Functions void main() { float Kin = gl_Color.r; // key input // screen position from vertex and texture vec4 Vp = ftransform(); vec4 Tp = vec4(gl_MultiTexCoord0.xy*1.8-.9, 0.,1.); // interpolate between Vp and Tp gl_Position = mix(Tp,Vp,pow(1.-Kin,8.)); // copy to output gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = Vp; gl_TexCoord[3] = vec4(Kin); }
Trick #1: Where is the Eye ObjectSpace Projection Matrix ModelViewMatrix EyeSpace ClipSpace • Where is the Eye in Eye Space? • (0,0,0)? Not necessarily! • Know where it is in Clip Space • (0,0,-1,0), looking in the (0,0,1,0) direction • Assuming GL_LESS depth test • Invert projection to find the eye! • Works for any eye position, or even parallel projection.
Trick #2: Subtract Homogeneous Points • Homogeneous point: vec4(V.xyz, V.w) • 3D equivalent: V.xyz/V.w • Defers division, makes perspective, translation, and many things happy • Vector subtraction: V–E • V.xyz/V.w – E.xyz/E.w • (V.xyz*E.w – E.xyz*V.w)/(V.w*E.w)
Trick #3: Skip Division for Normalize • normalize(V.xyz/V.w) = normalize(V.xyz) • If V.w isn’t negative • Put it all together: • normalize(V-E) • = normalize(V.xyz*E.w - E.xyz*V.w)
Lighting Vectors in Eye Space void main() { // convert shading-related vectors to eye space vec4 P = gl_ModelViewMatrix*gl_Vertex; vec4 E = gl_ProjectionMatrixInverse*vec4(0,0,-1,0); vec3 V = normalize(E.xyz*P.w-P.xyz*E.w); vec3 N = normalize(gl_NormalMatrix*gl_Normal); …
Accumulate Each Light … // accumulate contribution from each light gl_FrontColor = vec4(0); for(int i=0; i<gl_MaxLights; i++) { vec3 L = normalize(gl_LightSource[i].position.xyz*P.w - P.xyz*gl_LightSource[i].position.w); vec3 H = normalize(L+V); float diff = dot(N,L); gl_FrontColor += gl_LightSource[i].ambient; if (diff > 0.) { gl_FrontColor +=gl_LightSource[i].diffuse * diff; gl_FrontColor +=gl_LightSource[i].specular * max(pow(dot(N,H), gl_FrontMaterialShininess),0.); } } …
Standard Vertex Shader Stuff … // standard texture coordinate and position stuff gl_TexCoord[0] = gl_TextureMatrix[0]*gl_MultiTexCoord0; gl_Position = ftransform(); }
Noise • Controlled, repeatable randomness • Still spotty implementation • Can use texture or compute
Noise Characteristics • Repeatable • Locally continuous but distant points uncorrolated • values [-1,1], average 0 • 1/2 – 1 cycle per unit • Versions for n-D input
Noise Subtleties • Many noise functions based on a lattice • Like a spline between integer coordinates • Hash of integer coordinates control points • Interpolating values easy but poor • Even with higher-order interpolation • Perlin’s noise • Passes through 0 at each integer • Hash gives gradient
Modified Noise [Olano 2005] • Three relatively independent modifications • New computable hash • Change gradient computation • Reorder computation • Variety of computation/texture options • Can just store in a texture • Can compute with some texture accesses • Can compute with no texture accesses
Computable Hash • Normal hash chains access to permutation texture • Want totally computable hash • mod(k*x2, m) • Still chain for higher-D • hash(floor(P.x) + hash(floor(P.y))) • Not quite as good, but cheap & computable • Noise usually not used alone
Gradient • 3D Gradient = (±fract(P.x), ±fract(P.y)) • Each sign from one bit of hash • Made slightly more difficult without bitwise ops • Allows noise(x) = noise(x,0) • If 2D noise is stored in a texture • Can share the same texture for 1D noise as well • Not normally true!
Reordered Computation • Refactor to be able to build n-D noise from two shifted calls to n-1 D noise • If 2D noise is stored in a texture • Can build 3D noise from 2 texture accesses • Can build 4D noise from 4 texture accesses
Shader Design Strategies • Learn and adapt from RenderMan • Noise • Layers • Multiple Passes • Baked computation