Texture Mapping

advertisement
SHADERS/GLSL
CS 4363/6353
SHADERS
•
What is a shader?
• It is a small program that runs on the GPU
• Usually written in a high level shader language (e.g. GLSL)
•
common shaders:
• Vertex Shader: executes once for every vertex
• Fragment Shader: executes one for every fragment (potential pixel)
2
VERTEX SHADER APPLICATIONS
•
Moving vertices
• Transformations
• Morphing
• Wave motion (e.g., water)
• Fractals
•
Lighting
• More realistic models
• Cartoon shaders
3
FRAGMENT SHADER APPLICATIONS
Per fragment lighting calculations
per vertex lighting
per fragment lighting
4
FRAGMENT SHADER APPLICATIONS
Texture mapping
smooth shading
environment
mapping
bump mapping
5
SHADERS IN THE GRAPHICS PIPELINE
Vertex Shader
Fragment Shader
OpenGL (application software)
6
COMPILE A SHADER
1)
Read in shader source (standard c/c++ io)
2)
glCreateShader – create a shader object
3)
glShaderSource - add the source code in a shader object
4)
glCompileShader – compile the shader
7
LINK AND USE A SHADER PROGRAM
• The program nust include BOTH fragment and vertex
shaders
1) glCreateProgram – create an empty program id
2) glAttachShader - attach a frag shader
3) glAttachShader – attach a vertex shader
4) glLinkProgram – after compilation (prev slide), link!
5) glUseProgram – call this before you start using the
shader during rendering.
8
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;
• int myInt = -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
Perspectively interpolated
noperspective
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
glBindVertexArray(vao);
GLuint buffer;
buffer
glGenBuffers(1, &buffer);
Note: buffer “lives” on the graphics card in a nice, two-bedroom loft…
glBindVertexArray(vao);
GLuint buffer;
Hey – I’m active now
buffer
glGenBuffers(1, &buffer);
glBindBuffer (GL_ARRAY_BUFFER, buffer);
glBindVertexArray(vao);
GLuint buffer;
Now I know how big I am!
buffer
glGenBuffers(1, &buffer);
glBindBuffer (GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER,
numVertices*6*sizeof(GLfloat),
NULL, GL_STATIC_DRAW);
Why 6?
glBindVertexArray(vao);
GLuint buffer;
Now I’m putting vVerts at the beginning
buffer
glGenBuffers(1, &buffer);
vVerts
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 big
though…
I’m putting vNormals next
glBindVertexArray(vao);
GLuint buffer;
buffer
glGenBuffers(1, &buffer);
vVerts
vNorms
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 starting
right after that!
It’s pretty big
too…
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…
GLuint loc = glGetAttribLocation(shaderProgramID, "vPosition");
#version 150
in vec4 vPosition;
in vec3 vNormal;
out vec4 color;
// This will be referenced in your OpenGL program!!
// The normal of the vertex
// Out to fragment shader
uniform mat4 p;
uniform mat4 mv;
uniform vec4 light_pos;
// This is perpsective matrix
// This is the model-view matrix
// 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));
}
GLuint loc = glGetAttribLocation(shaderProgramID, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
Guys! I’m still active, remember?
buffer
vVerts
vNorms
#version 150
in vec4 vPosition;
in vec3 vNormal;
out vec4 color;
// This will be referenced in your OpenGL program!!
// The normal of the vertex
// Out to fragment shader
uniform mat4 p;
uniform mat4 mv;
uniform vec4 light_pos;
// This is perpsective matrix
// This is the model-view matrix
// 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));
}
Tell vNormal where to look in me…
buffer
vVerts
vNorms
GLuint loc2 = glGetAttribLocation(shaderProgramID, "vNormal");
glEnableVertexAttribArray(loc2);
glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(numVertices*3*sizeof(GLfloat)));
#version 150
in vec4 vPosition;
in vec3 vNormal;
out vec4 color;
// This will be referenced in your OpenGL program!!
// The normal of the vertex
// Out to fragment shader
uniform mat4 p;
uniform mat4 mv;
uniform vec4 light_pos;
// This is perpsective matrix
// This is the model-view matrix
// 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));
}
GLuint loc = glGetAttribLocation(shaderProgramID, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint loc2 = glGetAttribLocation(shaderProgramID, "vNormal");
glEnableVertexAttribArray(loc2);
glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(numVertices*3*sizeof(GLfloat)));
#version 150
in vec4 vPosition;
in vec3 vNormal;
out vec4 color;
// This will be referenced in your OpenGL program!!
// The normal of the vertex
// Out to fragment shader
uniform mat4 p;
uniform mat4 mv;
uniform vec4 light_pos;
// This is perpsective matrix
// This is the model-view matrix
// 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 shader out, there’s a fragment shader in
•
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
GLint fShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource (fShaderID, 1, (const GLchar**)&shaderSource1, NULL);
glCompileShader(fShaderID);
GLint vShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource (vShaderID, 1, (const GLchar**)&shaderSource2, NULL);
glCompileShader(vShaderID);
GLuint programID = glCreateProgram(); // KEEP THIS!
glAttachShader(programID, vShaderID );
glAttachShader(programID, fShaderID );
glLinkProgram (programID);
USING/DELETING
•
To use the shader:
• glUseProgram (GLuint progID);
• 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( GLuint progID);
#version 150
in vec4 vPosition;
in vec3 vNormal;
out vec4 color;
// This will be referenced in your OpenGL program!!
// The normal of the vertex
// Out to fragment shader
uniform mat4 p;
uniform mat4 mv;
uniform vec4 light_pos;
// This is perpsective matrix
// This is the model-view matrix
// 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;
void main () {
fColor = color;
}
// from the vertex shader
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 (GLuint progID, const GLchar* varName);
SETTING UNIFORMS
•
•
Scalars and vectors (glUniformXY – where Y is the data type):
•
glUniform1f (GLuint location, GLfloat v0);
•
glUniform2f (GLuint location, GLfloat v0, GLfloat v1);
•
glUniform3f (GLuint location, GLfloat v0, GLfloat v1,
GLfloat v2);
•
glUniform4f (GLuint location, GLfloat v0, GLfloat v1,
GLfloat v2, GLfloat v3);
Example:
GLunit lightID = 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:
GLunit lightID = 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 (GLunit loc, GLuint count,
GLboolean transpose, GLfloat* m);
•
glUniformMatrix3fv (GLunit loc, GLuint count,
GLboolean transpose, GLfloat* m);
•
glUniformMatrix4fv (GLunit loc, GLuint count,
GLboolean transpose, 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));
• log( ) – natural log
• exp( ) - ex
• log2( ) – log base 2
• exp2( ) – 2 to the power of…
• sqrt( )
// 2^2, 3^2
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);
• vec faceForward (vec N, vec I, vec nRef);// if dot(Nref, I) < 0, return N, else return -N
BUILT-IN GLSL FUNCTIONS
•
Matrices
• transpose( )
• determinant( )
• inverse( )
• outerProduct( )
•
Relational functions
• vec lessThan (vec x, vec y); && vec lessThanEqual (vec x, vec y);
• vec greaterThan (vec x, vec y);
• vec equal (vec x, vec y); && vec notEqual (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.The fractional 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
Download