370 likes | 441 Views
GLSL Implementation. Paul Taylor 2009 Assignment Due Fri 5/6/2009. OpenGL Extensions in Windows. Our Goal: To use the extended features of OpenGL The Process: Finding out what extensions (functions) the machine Supports Recovering the Addresses of these extensions
E N D
GLSL Implementation Paul Taylor 2009 Assignment Due Fri 5/6/2009
OpenGL Extensions in Windows • Our Goal: To use the extended features of OpenGL • The Process: • Finding out what extensions (functions) the machine Supports • Recovering the Addresses of these extensions • Using the Recovered Extensions
GLSL • GLSL is an extension of OpenGL supported from Version 1.5 onwards • The Extension name is GL_ARB_shading_language_100
Finding Out what your Video Card Supports KluDX http://www.kludx.com/kludx.php • This little Program shows all of the available extensions your computer will support
Checking the OpenGL Version Get the Version String: char* openGLVersion = (char*)glGetString(GL_VERSION); Check the Version: if (strcmp(supportedExtensions, “1.5") >= 0) // Version is 1.5 or Above If this fails you need to exit the program nicely. (Tell the user their computer Sucks)
Loading Extensions in Windows Without using 3rd Party Libraries there are 2 Methods of Loading Extended Functions in Windows
Method 1 – by Hand Visit http://www.opengl.org/sdk/docs/man/xhtml/ Find the Function you want to add glCreateShader http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml
Header File // Include ONLY once!!!!! // GLuintglCreateShader(GLenumshaderType); typedefGLuint (WINAPI *GLCREATESHADERFN)(GLenumshaderType); GLCREATESHADERFN glCreateShaderFn;
Now you have the format of the Function Loading the Function wglGetProcAddress(" glCreateShader"); Code File glCreateShaderFn = (GLCREATESHADERFN) wglGetProcAddress(" glCreateShader"); if (glCreateShaderFn == NULL) return 1;
Now your function is ready to use GluintvertexShader = glCreateShaderFn(GL_VERTEX_SHADER); The problem with this method is it takes a LONG time to add all of the extensions you will need to use. Even for the most simple GLSL Shaders you will need to add each of the following extensions: • PFNGLCREATEPROGRAMPROC glCreateProgram; • PFNGLCREATESHADERPROC glCreateShader; • PFNGLATTACHSHADERPROC glAttachShader; • PFNGLSHADERSOURCEPROC glShaderSource; • PFNGLCOMPILESHADERPROC glCompileShader; • PFNGLGETSHADERIVPROC glGetShaderiv; • PFNGLLINKPROGRAMPROC glLinkProgram; • PFNGLUSEPROGRAMPROC glUseProgram; • PFNGLGETPROGRAMIVPROC glGetProgramiv; • PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; • PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
Glext.h http://oss.sgi.com/projects/ogl-sample/ABI/glext.h This header file contains almost all of the extension definitions you’ll ever require. For the others you’ll need to load them by hand as in Method 1
Method 2 • Find the function you want in glext.h • The two lines you need looks like: GLAPI GLuint APIENTRY glCreateShader (GLenum); typedefGLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); • Line 1 gives you the Function Prototype (Parameters for the Function) • Line 2 gives you the TypeDef needed to create the Function Pointer Header File: PFNGLCREATESHADERPROC glCreateShader; Code File: glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"); if (glCreateShader == NULL) // Error return 2;
You can now call the function GluintvertexShader = glCreateShader(GL_VERTEX_SHADER);
That was Ugly! • The Next Part of Using GLSL Shaders is much easier!
Utilising GLSL in you Application Creating GLSL Shaders and Programs Compiling GLSL Shaders Linking GLSL Programs Utilising GLSL Programs
Creating GLSL Shaders and Programs First you will need to create a program object Reference • ProgramObject = glCreateProgram(); This Object will hold your shaders and is the reference between them and OpenGL
Next you need to create the Vertex Shader and Pixel Shader References vertexShader = glCreateShader(GL_VERTEX_SHADER); pixelShader = glCreateShader(GL_FRAGMENT_SHADER); This just returns referrence IDs for use when creating the shaders
Attach Your Shaders glAttachShader(ProgramObject, vertexShader); glAttachShader(ProgramObject, pixelShader); This connects both your shader objects to your Program Object You then need to read your shader source into a memory block
intloadVertexShader(char* fileName) { vertexShader = glCreateShader(GL_VERTEX_SHADER); glAttachShader(ProgramObject, vertexShader); //Load Text File if (fileName == NULL) vertexShaderSource = readSourceFile(defaultVertexShader); else vertexShaderSource = readSourceFile(fileName); // Check for error if (vertexShaderSource == NULL) return 1; glShaderSource(vertexShader, 1, (const GLchar**) &vertexShaderSource, NULL); Errors(); return NULL; }
Then link the shader source to the shader glShaderSource(vertexShader, 1, (const GLchar**) &vertexShaderSource, NULL); For Both Shaders glShaderSource(pixelShader, 1, (const GLchar**) &pixelShaderSource, NULL);
Compiling GLSL Shaders glCompileShader(vertexShader); glCompileShader(pixelShader);
Checking For Errors int status; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) // Error! interrorLength = NULL; glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &errorLength);
Checking For Errors char* errorString = (char*) malloc((errorLength + 1) * sizeof(char)); errorString[errorLength] = NULL; glGetShaderInfoLog(vertexShader, errorLength, &errorLength, errorString); MessageBox(NULL, errorString, "Error Compiling Vertex Shader", MB_OK);
Linking GLSL Programs glLinkProgram(ProgramObject); // Error Checking glGetProgramiv(ProgramObject, GL_LINK_STATUS, &status); glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH, &errorLength); glGetProgramInfoLog(ProgramObject, errorLength, &errorLength, errorString);
Utilising GLSL Programs glUseProgram(ProgramObject);
Attributes, Uniforms, & Varyings (again) Remember Attributes change on a Per-Vertex Basis (Built in Attributes are like gl_Colour, gl_Vertex) A new Attribute could be Temperature // GLSL Vertex Shader attribute vec4 temperature void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_FrontColor = gl_Color * temperature; }
Uniforms • Uniforms are Set for the whole of the Object Render (Between glBegin and glEnd) • These little guys share data between the program, the vertex and the pixel shader • If your render was time based, time would be a good Uniform
Varyings • These guys are interpolated between vertices when rendering • The best example of a built in varying is the gl_FrontColor varying. When set to red at one vertex and Blue at another, the varying is automatically interpolated from red to blue by the hardware
Linking Attributes to the main OpenGL Program • Linking the Shader Variable to OpenGL GluintstupidColour; stupidColour = glGetAttribLocation(programObject, “attributeName”); • Using the Shader Variable Glfloat green[] = {0.0f,1.0f,0.0f,0.0f} glVertexAttrib4fv(stupidColour, green);
Uniforms are Similar • glGetUniformLocation(ProgamObject, “Uniform Name”); • glUniform1f(reference, float Value); For Debugging you can also access the values of Uniforms and the active Attributes glGetUniform glGetActiveUniform glGetActiveAttrib
Varyings don’t exist outside of the Video Card • Varyings are internal so there isn’t any special way to access them in OpenGL
Cg Shaders and OpenGL • Next Time!
Utilising Cg Shaders in your Program Cg Toolkit: http://developer.nvidia.com/object/cg_toolkit.html Cg Fx Runtime (Cg Compiler 1.1): http://developer.nvidia.com/object/cg_toolkit_1_1.html Cg Fx Viewer: http://developer.nvidia.com/object/IO_CgFXViewer.html
HLSL and XNA • HLSL for DirectX is outside of this subject, but excepting the linking and compiling the shaders work in the same manner as XNA.