450 likes | 655 Views
Shaders /GLSL. CS 4363/6353. Another Look at the Pipeline. Vertex Processing. Clipping/Assembly. Rasterization. Fragment Processing. Another Look at the Pipeline. Attributes (ins). Vertex Processing. OpenGL Application. Clipping/Assembly. Server-side. Rasterization. Client-side.
E N D
Shaders/GLSL CS 4363/6353
Another Look at the Pipeline Vertex Processing Clipping/Assembly Rasterization Fragment Processing
Another Look at the Pipeline Attributes (ins) Vertex Processing OpenGL Application Clipping/Assembly Server-side Rasterization Client-side Fragment Processing
Attributes • Remember, these are values that are per vertex! • Denoted with keyword in • Are read-only • Maximum of 16 attributes per shader program • Always stored as a vec4, even if you declare it as a single float! • Examples: • Raw vertex positions • Normals • Texture coordinates • Could also be other things?
Another Look at the Pipeline Attributes (ins) Vertex Processing Uniforms OpenGL Application Clipping/Assembly Rasterization Fragment Processing Uniforms
Uniforms • Uniforms are not individualized • Apply to all vertices/fragments • Denoted by the uniform keyword • Examples: • Matrices (ModelView, Perspective) • Light positions
Another Look at the Pipeline Attributes (ins) Vertex Processing Uniforms Texture data OpenGL Application Clipping/Assembly Rasterization Texture data Fragment Processing Uniforms
Texture Data • Remember, these are set up in hardware units • Textures can be in 1, 2 and 3 dimensions • Can also be in cube maps • Accessed in the fragment shader using sampler2D
Another Look at the Pipeline Attributes (ins) Vertex Processing Uniforms Texture data outs New vertex positions OpenGL Application Clipping/Assembly ins Texture data Fragment Processing Uniforms
GLSL • Must have a minimum of two shaders • Syntax is similar to C (it has a main) • Supports functions • Doesn’t support pointers! • Has variables similar to C • bool finished = false; • intmyInt = -6; • uint = 567u; • float value = 42.0;
Vectors • GLSL supports vectors with 2, 3 and 4elements • vec2, vec3, vec4 • ivec2, ivec3, ivec4 • uvec2, uvec3, uvec4 • bvec2, bvec3, bvec4 • Initialize with a “constructor” • vec4 color = vec4 (1.0f, 0.0f, 1.0f, 1.0f); • Common operations • result = myVec + yourVec; • myVec += vec4 (1.0f, 0.5f, 0.4f, 0.2f); • myVec *= 3.0f;
Individual Elements • Can access individual elements using • xyzw – typically for positions • rgba – usually for colors • stpq – usually for texture coordinates • … it’s your choice, but you can’t mix them! • Examples • myVec.x = 4.0f; • myVec.xy = vec2 (1.0f, 5.0f); • myVec.xyz = yourVec.xyz; • vColor.bgra = vOldColor.rgba; // called “swizzling”
A note about Efficiency & Gotchas • Vector operations are supported by hardware • Performed all at once! • Inefficient: • vPos.x = vPos2.x + 1.0f; • vPos.y = vPos2.y +3.0f; • vPos.z = vPos2.z + 2.0f; • Efficient: • vPos.xyz = vPos2.xyz + vec3 (1.0f, 3.0f, 2.0f); • Gotcha: • If you don’t use an attribute or uniform, OpenGL “optimizes” by removing it!
Matrices! • Several types in columns and rows: • mat2x2 (or simply mat2) • mat3x3 (or mat3) • mat4x4 (or mat4) • mat2x3 and mat2x4 • mat3x2 and mat3x4 • mat4x2 and mat4x3
Matrices • Organized as an array of column vectors • mMV[3] = vec4(1.0f, 0.0f, 1.0f, 1.0f); • vec3 myVec = mMV[3].xyz; • Matrices can be multiplied by other matrices and vectors • Matrices have one nasty “constructor” and one good one mat4 theMatrix = mat4 (1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); mat4 theMatrix = mat4(1.0f);
Storage Qualifiers • in – passed in from a previous stage • out – going to the next stage • const – a read-only variable (one that doesn’t change) • uniform – does not change across vertices • inout – only used in functions (it’s essentially a pointer) • in centroid/out centroid – used in multisampled buffers (interpolation) • noperspective – don’t use perspectively-correct interpolation • flat – don’t interpolate (colors) at all; declared in both vertex and frag shaders • smooth – the default interpolation
Example noperspective Perspectively interpolated http://wwwx.cs.unc.edu/~sud/courses/236/a6/
A Side-By-SIDE Comparison • Show the relationship between client code and shader code • Assume you loaded a sphere, plane, or monkey face… • numVertices – the number of vertices (duh!) • vVerts – the position information of each vertex • vNorms – the normal information of each vertex
buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); Note: buffer “lives” on the graphics card in a nice, two-bedroom loft…
Hey – I’m active now buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
Now I know how big I am! buffer glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); Why 6?
Now I’m putting vVerts at the beginning buffer vVerts glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*3*sizeof(GLfloat), vVerts); glBufferSubData (GL_ARRAY_BUFFER, numVertices*3*sizeof(GLfloat), numVertices*3*sizeof(GLfloat), vNorms); Put vVerts at 0… it’s pretty bigthough…
I’m putting vNormals next buffer vVerts vNorms glBindVertexArray(vao); GLuintbuffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, numVertices*6*sizeof(GLfloat), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*3*sizeof(GLfloat), vVerts); glBufferSubData (GL_ARRAY_BUFFER, numVertices*3*sizeof(GLfloat), numVertices*3*sizeof(GLfloat), vNorms); Put vNormals startingright after that! It’s pretty bigtoo…
What we Have so far… • We have a buffer with an ID • That buffer lives on the graphics card • That buffer is full of vertex position/normal data • How do we get that info to our shader? • Immediately after this code, we put the following…
GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition"); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); }
Guys! I’m still active, remember? buffer GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition");glEnableVertexAttribArray(loc);glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); } vVerts vNorms
Tell vNormal where to look in me… buffer vVerts vNorms GLuintloc2 = glGetAttribLocation(shaderProgramID, "vNormal");glEnableVertexAttribArray(loc2);glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertices*3*sizeof(GLfloat))); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); }
GLuintloc = glGetAttribLocation(shaderProgramID, "vPosition");glEnableVertexAttribArray(loc);glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0); GLuintloc2 = glGetAttribLocation(shaderProgramID, "vNormal");glEnableVertexAttribArray(loc2);glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertices*3*sizeof(GLfloat))); #version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); }
the Fragment Shader • For every vertex shaderout, there’s a fragment shaderin • Value is smoothly interpolated from vertex shader • Fragment shaders have an out as well • Called “output zero” • Sent to color buffer • Represents the color of the fragment
Compiling and Linking Shaders GLintfShaderID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fShaderID, 1, (constGLchar**)&shaderSource1, NULL); glCompileShader(fShaderID); GLintvShaderID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vShaderID, 1, (constGLchar**)&shaderSource2, NULL); glCompileShader(vShaderID); GLuintprogramID = glCreateProgram(); // KEEP THIS! glAttachShader(programID, vertexShaderID); glAttachShader(programID, fragmentShaderID); glLinkProgram(programID);
Using/Deleting • To use the shader: • glUseProgram (GLuintprogID); • Any subsequent draw calls will use that shader • There are only a limited number of shaders on the graphics card (16) • When you’re done with one: • glDeleteShader( GLuintprogID);
#version 150 in vec4 vPosition; // This will be referenced in your OpenGL program!! in vec3 vNormal; // The normal of the vertex out vec4 color; // Out to fragment shader uniform mat4 p; // This is perpsective matrix uniform mat4 mv; // This is the model-view matrix uniform vec4 light_pos; // This is the light position void main () { gl_Position = p*mv*vPosition; vec3 L = normalize (light_pos.xyz); vec3 N = normalize (vNormal); color = vColor*max(0.2f, dot(N, L)); } #version 150 out vec4 fColor; in vec4 color; // from the vertex shader void main () { fColor = color; }
A note About Versions • Version number – minimum version supported • Version numbers changed! • OpengGL 3.0 – GLSL version 1.3 (#version 130) • OpenGL 3.1 – GLSL version 1.4 (#version 140) • OpenGL 3.2 – GLSL version 1.5 (#version 150) • OpenGL 3.3 – GLSL version 3.0 (#version 300) • OpenGL 4.0 – GLSL version 4.0 (#version 400)
UniForms • Persistent across all vertices • Can’t be marked as in/out • Can’t be interpolated • Always read-only • Find uniform variables using: • glGetUniformLocation (GLuintprogID, constGLchar* varName);
Setting Uniforms • Scalars and vectors (glUniformXY – where Y is the data type): • glUniform1f (GLuint location, GLfloat v0); • glUniform2f(GLuint location, GLfloat v0, GLfloatv1); • glUniform3f(GLuint location, GLfloatv0, GLfloatv1, GLfloat v2); • glUniform4f(GLuint location, GLfloatv0, GLfloatv1, GLfloat v2, GLfloatv3); • Example: GLunitlightID = glGetUniformLocation (progID, “light_pos”); glUniform4f (lightID, light_x, light_y, light_z, 1.0f);
Setting Uniforms • Arrays are similar: • glUniform1fv (GLuint location, GLuint count, GLfloat* v); • glUniform2fv(GLuint location, GLuint count, GLfloat* v); • glUniform3fv(GLuint location, GLuint count, GLfloat* v); • glUniform4fv(GLuint location, GLuint count, GLfloat* v); • What’s the difference? Format of glUniformXYv • X is how many elements are in each array • count is how many of those arrays you have • Y is the type • Example: GLunitlightID = glGetUniformLocation (progID, “light_pos”); GLfloat* myLightPosition[4] = {10.0f, 10.0f, 10.0f, 1.0f); glUniform4fv (lightID, 1, myLightPosition);
Setting Uniforms • Set uniform matrices by their dimension: • glUniformMatrix2fv (GLunitloc, GLuint count, GLboolean transpose, GLfloat* m); • glUniformMatrix3fv (GLunitloc, GLuint count, GLbooleantranspose, GLfloat* m); • glUniformMatrix4fv (GLunitloc, GLuint count, GLbooleantranspose, GLfloat* m); • count represents the number of matrices (almost always 1) • transpose is used to indicate if the matrix is stored in column order
Built-In GLSL Functions • Tons of different mathematical functions • Scalars • Vectors • Matrices • Robust trig functions: • float x = sin (1.0); // Also have cos, tan, atan, asin… • vec4 y = sin (vec4(1.0f, 0.5f, 0.25f, 0.0f)); // Overloaded function • float z = radians (45.0f); // Convert from degrees to radians • float z = degrees (0.6f); // Convert from radians to degrees
Built-IN GLSL Functions • Robust exponentials: • vec2 results = pow (vec2(2, 3), vec2 (2, 2)); // 2^2, 3^2 • log( ) – natural log • exp( ) - ex • log2( ) – log base 2 • exp2( ) – 2 to the power of… • sqrt( )
Built-In GLSL Functions • Geometric functions (generic “vec”) • float length (vec x); • float distance (vec p0, vec p1); • float dot (vec x, vec y); • vec3 cross (vec x, vec y); • vec normalize (vec x); • vec reflect (vec I, vec N); // I is incident vector (light/view) and N is normal • vec refract(vec I, vec N, float eta); • vecfaceForward (vec N, vec I, vecnRef);// if dot(Nref, I) < 0, return N, else return -N
BUILT-IN GLSL Functions • Matrices • transpose( ) • determinant( ) • inverse( ) • outerProduct( ) • Relational functions • veclessThan (vec x, vec y); && veclessThanEqual (vec x, vec y); • vecgreaterThan (vec x, vec y); • vec equal (vec x, vec y); && vecnotEqual (vec x, vec y); • bool any (bvec x); // returns true if any booleans in x are true • bool all (bvec x); // returns true if all booleans in x are true
Built-In GLSL Functions • Common functions • abs, sign, floor, ceil, mod, min, max... yeah, yeah… • trunc(x) – nearest whole number not larger than the absolute value of x • round(x) – based on 0.5 • roundEven(x) – “returns a value equal to the nearest integer to x.Thefractional part of 0.5 will round toward the nearest even integer. For example, both 3.5 and 4.5 will round to 4.0.” • fract (x) – returns the fractional part • clamp(x, y, z) – returns x if it’s between y and z, else returns y or z • mix (x, y, a) – returns the linear blend of x and y, as a varies from 0 to 1 • step (edge, x) – returns 0.0 if x < edge, 1.0f otherwise • smoothstep (edge0, edge1, x) – 0 if x < edge0, 1 if x > edge1, interpolated otherwise
Last of the Built-Ins • isnan(x) – true is x is not a number (NAN) • isinf(x) – returns true is x is +∞ or -∞ • floatBitsToInt(x) – converts floating point values to ints • intBitstoFloat(x) – converts integers to floating points