230 likes | 442 Views
CS 3388: Programmable Shading in GLSL. [Hill § 8.7] http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf. Programmable Shading. OpenGL 1.1 is a “fixed-function pipeline” each new feature adds complexity (environment mapping, bump mapping, advanced lighting,...)
E N D
CS 3388: Programmable Shading in GLSL [Hill §8.7] http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf
Programmable Shading • OpenGL 1.1 is a “fixed-function pipeline” • each new feature adds complexity (environment mapping, bump mapping, advanced lighting,...) • by now, hundreds of gl functions • Instead of configuring graphics pipeline, insert arbitrary code into pipeline! send my_code... application.exe opengl32.dll char* my_code = "void main() {" "gl_FragColor = vec4(1,0,0,1);" "}"; GLuint red = ... glUseProgram(red); void main() { gl_FragColor = vec4(1,0,0,1); } my_code runs inside video card!!
Types of “Shader” Programs • Vertex shader • executed once for each vertex (in parallel) • must output a vertex in clip coordinates • can control interpolation of arbitrary per-vertex quantities (normals, colours, texcoords, ...) • Fragment shader • executed once for each pixel/subpixel (in parallel) • can compute colour (stored in framebuffer) • can compute pseudodepth (stored in z-buffer)
Example: Simple Red #version 120 // GLSL version for OpenGL 2.1 uniform mat4 PM; // projection*modelview matrix attribute vec4 p; // the (x,y,z,1) point to process void main() { gl_Position = PM*p; // output clip coordinate of p } VERTEX SHADER #version 120 void main() { gl_FragColor = vec4(1,0,0,1); // RGB = (1,0,0), A = 1 } FRAGMENT SHADER
Example: Visualize Depth #version 120 // GLSL version for OpenGL 2.1 uniform mat4 PM; // projection*modelview matrix uniform mat4 M; // modelview matrix attribute vec4 p; // the (x,y,z,1) point to process varying vec4 p_eye; // the eye coordinate of p void main() { gl_Position = PM*p; // output clip coordinate of p p_eye = M*p; // also output eye coordinate of p } VERTEX SHADER #version 120 varying vec4 p_eye; // eye coordinate of this fragment void main() { float d = -p_eye.z/10; // map z range [0..-10] to [0..1] gl_FragColor = vec4(d,d,d,1); // RGB = depth, A = 1 } FRAGMENT SHADER
Under the Hood • Video card never sees your GLSL code • Vendor’s OpenGL driver compiles it into vendor-specific microcode (diagram on board) • Microcode highly optimized for user’s particular video card void main() { gl_FragColor = vec4(1,0,0,1); } nvoglv32.dll def c0, 1, 0, 0, 0 mov gl_FragColor, c0.xyyx
Microcode (Assembly) • Simple Red program • Visualize Depth program dp4 gl_Position.w, v0, c3 dp4 gl_Position.z, v0, c2 dp4 gl_Position.y, v0, c1 dp4 gl_Position.x, v0, c0 def c0, 1, 0, 0, 0 mov gl_FragColor, c0.xyyx fragment shader instructions vertex shader instructions dp4 gl_Position.w, v0, c3 dp4 gl_Position.z, v0, c2 dp4 gl_Position.y, v0, c1 dp4 gl_Position.x, v0, c0 dp4 vary0.w, v0, c7 dp4 vary0.z, v0, c6 dp4 vary0.y, v0, c5 dp4 vary0.x, v0, c4 def c0, 0.1, 1, 0, 0 mul gl_FragColor.rgb, -vary0.z, c0.x mov gl_FragColor.a, c0.y c0..c3 initialized to rows of PM matrix c4..c7 initialized to rows of M matrix
Compiling GLSL programs • Compile vertex shader; fragment shader • glCreateShader,glShaderSource,glCompileShader • Link them into one program • glCreateProgram,glAttachShader,glLinkProgram • Bind the program before drawing • glUseProgram • For convenience, cs3388lib provides gl_createprogram function (easy!)
GLSL “uniform” Variables • Same value for all triangles being drawn • hence the name uniform • Read-only (set value before drawing) • Accessible by vertex & fragment shaders // get identifier for GLSL variable named 'fillcolor' intloc = glGetUniformLocation(program,"fillcolor"); glUniform4f(loc,0,1,0,1); // set to green C/C++ code uniform vec4 fillcolor; // external RGBA constant void main() { gl_FragColor = fillcolor; // send to framebuffer } GLSL fragment
GLSL “attribute” Variables • Different for each vertex • position, normal, colour, texcoord, ... whatever • Read-only (pulled from vertex buffer data) • Accessible by vertex shader only structvertex { // make our own vertex structure vec3 pos; // (x,y,z) position of vertex vec2 texcoord; // (u,v) texture coordinate }; // each vertex has 5 floats total C/C++ code attribute vec3 pos; // per-vertex floats 0..2 attribute vec2 texcoord; // per-vertex floats 3..4 void main() { ... GLSL vertex
GLSL “varying” Variables • Different for each fragment (each pixel) • Write-only at vertex, read-only at fragment • Value seen by fragment is interpolated • 3D barycentriccoord of fragment determines value attribute vec4 pos; // per-vertex floats 0..3 attribute vec4 color; // per-vertex floats 4..7 varying vec4 blah; // OUTPUT: some per-vertex value void main() { blah = color; // blah is this vertex's color vertex varying vec4 blah; // INPUT: interpolated value of 'blah' void main() { gl_FragColor = blah; // blah = interpolated per-vtx color } fragment
GLSL Variable Types • Besides uniform/attribute/varying, each variable also needs a type • float,vec2,vec3,vec4,mat2,mat3,mat4,... • Remember to use glUniformXXX where XXX corresponds to type of variable • Also a number of texture variable types • sampler2D,samplerCube,sampler2DShadow.. • See OpenGL 2.1 language specification: http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf
GLSL Texture Sampling • A samplervariable identifies a texture • A texture lookup function samples the texture at a specific (u,v)coordinate • Must still bind the texture and set texid! uniform sampler2D sampler; // texture unit varying vec2 uv; // interpolated texcoord fragment... void main() { gl_FragColor = texture2D(sampler,uv); // sample RGBA texture } ...fragment glBindTexture(GL_TEXTURE_2D,texture_id); // assume texunit 0 glUniform1i(glGetUniformLocation(program,"sampler"),0);
GLSL Demos • Best way is to learn by example • Available from lectures page glsl_demo glsl_texture_demo glsl_proctexture_demo “procedural texture” “bitmap texture”
Multi-Texturing • Realistic shading needs multiple textures • Each texture encodes a different property • diffuse, specular, normals, static light intensity, ... two texture maps per-pixel shading via textures diffuse coeffs specular coeffs http://rainybrain.org/?p=131
Multi-Texturing • Can have multiple samplervariables • Must bind each texture to a “texture unit” uniform sampler2D dtex; // per-pixel diffuse coefficient uniform sampler2D stex; // per-pixel specular coefficient varying vec2 uv; // (u,v) coord of this fragment void main() { vec4 diffuse = texture2D(dtex,uv); // sample diffuse coeff vec4 specular = texture2D(stex,uv); // specular coeff ... // compute shading colour as usual (need light etc) } fragment glActiveTexture(GL_TEXTURE0); // make texunit 0 active glBindTexture(GL_TEXTURE_2D,texid_dtex); glUniform1i(glGetUniformLocation(program,“dtex"),0); glActiveTexture(GL_TEXTURE1); // make texunit 1 active glBindTexture(GL_TEXTURE_2D,texid_stex); glUniform1i(glGetUniformLocation(program,“stex"),1);
GLSL Multi-Texture Demo • Available from lectures page glsl_multitexture_demo UVs for diffuse UVs for lightmap (0,0) (0,0) if box were here can compute a lightmap that encodes light that would reach the walls (3,6) (1,1)
Light Maps Used Everywhere • Light maps are pre-computed global illumination for static scenes • Next topic: global illumination diffuse texture only (no lights) diffuse texture + static light maps
Light Maps Used Everywhere • Light maps are pre-computed global illumination for static lighting (not “dynamic” lighting) light map intensities computed by “Radiosity” technique light map (no filtering; raw texels)
Light Maps Used Everywhere • Light maps are pre-computed global illumination for static lighting (not “dynamic” lighting) colour light maps light map (filtered)
Light Maps Used Everywhere • Light maps are pre-computed global illumination for static lighting (not “dynamic” lighting) colour light maps (no filtering)
Bump/Normal Mapping • Use texture to encode per-pixel normal • Gives illusion of complex geometry • Take notes for normal mapping in class! diffuse colour map normal map per-pixel diffuse shading
http://3d.dtuts.com/3d-tutorials/making-of-nemesis/ Generating Normal Maps • Sophisticated tools allow artists to • model an “asset” as high-poly mesh • automatically “bake” into approximate low-poly mesh + normal map hi-poly mesh low-poly mesh, normal mapped automatic normal map