lecture note - image processing
TRANSCRIPT
Programmable shader
Hanyang University
Objective
• API references (will be skipped)
• Examples– Simple shader
– Phong shading shader
INTRODUCTION
GLSL(OPENGL SHADING LANGUAGE)
Data types• Scalar
• Vectors and matrices
– Matrices are column-major ordered.
• Array– A 1-D array is only supported. – Dynamic allocation of memory is not available.
– The length() method can be used to return the length of an array.
• Unlike C language, pointer types are not available.
• Structure – Structures are similar to that of C language.
Qualifiers
• Type qualifiers
– Usage
Operators
Constructors Constructors are special functions primarily used
to initialize variables, especially of multicomponent data types, including structures and arrays.
They can also be used as expressions.
A single scalar value is assigned to all elements of a vector.
You can mix and match scalars, vectors, and matrices in your constructor, as long as you end up with enough components to initialize the entire data type. Any extra components are dropped.
Matrices are constructed in column-major order. If you provide a single scalar value, that value is used for the diagonal matrix elements, and all other elements are set to 0.
Type conversions are performed only using constructors.
Component selectors(swizzling)• Individual components of a vector can be accessed
by using dot notation along with {x,y,z,w}, {r,g,b,a}, or {s,t,p,q}.
• You cannot mix and match selectors from the different notations.
• You can use the component selectors to rearrange the order of components or replicate them.
• You can also use them as write masks on the left side of an assignment to select which components are modified.
• Another way to get at individual vector components or matrix components is to use array subscript notation.
– vec v4 = (1.0, 2.0, 3.0, 4.0);– v4[2], v4.b, v4.z, v4.p
• All of them are the ways to access the third component of v4.
– For matrices, providing a single array index accesses the corresponding matrix column as a vector. Providing a second array index accesses the corresponding vector component.
Flow control
• Loops– for, while, and do/while loops are all supported with the same syntax
as in C/C++, and they can be nested.
• if/else– You can use if and if/else clauses to select between multiple blocks of
code. These conditionals can also be nested.
Function
• All shaders must define a main function, which is the place where execution begins.
– void main() { … }
• Subroutines– Arrays are allowed as arguments, but not as return types.– Structures are allowed as arguments and return types.– There are 4 optional qualifiers for arguments.
– Recursive functions are not allowed.
VERTEX SHADER
Vertex shader• Inputs
– Matrices for geometric transformations and A set of vertex attributes including vertex coordinates, normal vector, vertex color, material properties, texture coordinates, and so on.
• Processing– Vertex transformation
• the vertex position is transformed from object space to clip space. – Lighting – Texture Coordinate Generation and Transformation
• Outputs– Clip-space position, front-facing and back-facing primary and secondary colors,
texture coordinates, …– User-defined varying variables.
Application
• Moving vertices– Morphing – Wave motion– Fractals– Particle systems– Skinning
• Lighting– More realistic lighting models– Cartoon shaders
Built-in vertex shader variables
• Built-in attribute input variables– Vertex attributes are fed by calling functions such as
glVertex*(), glNormal*(), glColor*(), glTexCoord*() , and so on.
Built-in vertex shader variables• Special output variables
• Varying output variables– They will be interpolated and passed to fragment shader.
Simple vertex shader
– Vertex coordinates which are specified by glVertex*() function are transformed to clip coordinates by the matrix gl_ModelViewProjectionMatrix , which is produced by multiplying modelview matrix and projection matrix.
– The prefix “gl_” indicates built-in variable.
void main(){
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;gl_FrontColor = gl_Color;
}
FRAGMENT SHADER
Fragment shader• Inputs
– Fragment Data whose values are produced by interpolating between outputs of vertex shader.
• front-facing and back-facing primary and secondary colors, texture coordinates, user-defined varying variables, …
• Processing– Texture lookup, color sum and blending, fog, …
• Outputs– Fragment color and depth
Application
• Per fragment lighting calculations
• Texture mapping
• Image processing
environment mapping bump mapping
Built-in fragment shader variables
• Input variables
• Output Variables
Simple fragment shader
– gl_FrontColor is produced by interpolating vertex colors which are the output of vertex shader.
– The prefix “gl_” indicates built-in variable.
void main(){
gl_FragColor = gl_FrontColor;}
SETUP FOR USING GLSL SHADER
Examples:Gouraud shading vs Phong shading• Gouraud shading • Phong shading
Conventional OpenGL rendering pipeline• Only support modified Phong illumination model for
lighting calculation.
• Only support Gouraud shading for shading faces.– Interpolate vertex shades across each polygon.
• It may be less efficient than programmable pipeline – Programmable pipeline allows to avoid unnecessary
operations and produce more compact program.
glew library
• OpenGL extensions are needed in order to use GLSL shader.
• GLEW(OpenGL Extension Wrangler) library allows to use extension functionalities of OpenGL.
– You can get at http://glew.sourceforge.net
– or from SDKs which provided by graphics hardware vendors (such as nVidia OpenGL SDK).
• Install glew.h, glew32.lib, and glew.dll files in the same manner as installing the glut library.
• At first, call glewInit() function which bind the function pointers declared in glew.h header file to the extension functions implemented in graphics driver.
Setup Steps
• Step 1: Create Shaders– Create handles to shaders
• Step 2: Specify Shaders– load strings that contain shader source
• Step 3: Compiling Shaders– Actually compile source (check for errors)
• Step 4: Creating Program Objects– Program object controls the shaders
• Step 5: Attach Shaders to Programs– Attach shaders to program obj via handle
• Step 6: Link Shaders to Programs– Another step similar to attach
• Step 7: Enable Program– Finally, let GPU know shaders are ready
App Setup (SetupRC function)GLhandleARB vShader, fShader, prog; // handles to objects
// Step 1: Create a vertex & fragment shader objectvShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
// Step 2: Load source code strings into shadersglShaderSourceARB(vShader, 1, &VS_String, NULL);glShaderSourceARB(fShader, 1, &FS_String, NULL);
// Step 3: Compile the vertex, fragment shaders.glCompileShaderARB(vShader);glCompileShaderARB(fShader);
// Step 4: Create a program objectprog = glCreateProgramObjectARB();
// Step 5: Attach the two compiled shadersglAttachObjectARB(prog, vShader);glAttachObjectARB(prog, fShader);
// Step 6: Link the program objectglLinkProgramARB(prog);
// Step 7: Finally, install program object as part of current stateglUseProgramObjectARB(prog);
Loading shader source codesGLhandleARB vShader, fShader, prog; // handles to objects
// Step 1: Create a vertex & fragment shader objectvShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
// Step 2: Load source code strings into shadersglShaderSourceARB(vShader, 1, &VS_String, NULL);glShaderSourceARB(fShader, 1, &FS_String, NULL);
// Step 3: Compile the vertex, fragment shaders.glCompileShaderARB(vShader);glCompileShaderARB(fShader);
// Step 4: Create a program objectprog = glCreateProgramObjectARB();
// Step 5: Attach the two compiled shadersglAttachObjectARB(prog, vShader);glAttachObjectARB(prog, fShader);
// Step 6: Link the program objectglLinkProgramARB(prog);
// Step 7: Finally, install program object as part of current stateglUseProgramObjectARB(prog);
Error checkingGLhandleARB vShader, fShader, prog; // handles to objects
// Step 1: Create a vertex & fragment shader objectvShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
// Step 2: Load source code strings into shadersglShaderSourceARB(vShader, 1, &VS_String, NULL);glShaderSourceARB(fShader, 1, &FS_String, NULL);
// Step 3: Compile the vertex, fragment shaders.glCompileShaderARB(vShader);glCompileShaderARB(fShader);
// Step 4: Create a program objectprog = glCreateProgramObjectARB();
// Step 5: Attach the two compiled shadersglAttachObjectARB(prog, vShader);glAttachObjectARB(prog, fShader);
// Step 6: Link the program objectglLinkProgramARB(prog);
// Step 7: Finally, install program object as part of current stateglUseProgramObjectARB(prog);
......
...
Vertex shader (phong_shading.vert)
Uniform Inputs
Attribute inputs
Outputs
output
Fragment shader (phong_shading.frag)
Uniform inputs
Attribute inputs
void RenderScene(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);
...glRotatef(xRotLight, 1.0f, 0.0f, 0.0f);glRotatef(yRotLight, 0.0f, 1.0f, 0.0f);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glPopMatrix();
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);glMaterialfv(GL_FRONT, GL_SPECULAR,materialSpecular);glMateriali(GL_FRONT,GL_SHININESS,100);glColor3f(0.0f, 1.0f, 0.0);
…
// Fixed-pipeline rendering on the leftglViewport(0, 0, width/2, height);glUseProgramObjectARB(0);glutSolidTeapot(100.0);
// Programmable rendering on the rightglViewport(width/2, 0, width/2, height);glUseProgramObjectARB(myShaderProgram);glutSolidTeapot(100.0);
glBegin(GL_TRIANGLES) glNormal3f(...) glColor3f(...) glVertex3f(...)
Set custom attribute/uniform values(without the “gl_” prefix)
• The symbolic table for attribute/uniform variables is generated when a program is linked.
• Query the linked program object for the attribute/uniform variable specified by name and get the index of the variable.– GLint i =glGetAttribLocation(P,”myAttrib”)
GLint j =glGetUniformLocation(P,”myUniform”)
• Specify the value of the attribute/uniform variable for the current program object using the index.– glVertexAttrib1f(i,value)
glUniform1f(j,value)
– glVertexAttribPointer(i,…) // passing attributes using vertex array