OpenGL shaders and programming models that provide object persistence
COSC342
Lecture 22 19 May 2016 OpenGL shaders
É We discussed forms of local illumination in the ray tracing lectures.
É We also saw that there were reasons you might want to modify these: e.g. procedural textures for bump maps.
É Ideally the illumination calculations would be entirely programmable.
É OpenGL shaders facilitate high performance programmability.
É They have been available as extensions since OpenGL 1.5 (2003), but core within OpenGL 2.0 (2004).
É We will focus on vertex and fragment shaders, but there are other types: e.g. geometry shaders, and more recent shaders for tessellation and general computing.
COSC342 OpenGL shaders and programming models that provide object persistence 2 GL Shading Language—GLSL
É C-like syntax. (No surprises given the OpenGL lineage . . . )
É However, compared to ‘real’ use of C, GLSL programmers are further away from the actual hardware.
É Usually the GLSL code will be passed as a string into the OpenGL library you are using.
É Only supports limited number of data types: e.g. float, double,...
É Adds some special types of its own: e.g. vector types vec2, vec4.
É Unlike most software, GLSL is typically compiled every time you load your functions—there isn’t (yet...) a standardised GL machine code.
COSC342 OpenGL shaders and programming models that provide object persistence 3 GLSL on the hardware
É The GLSL syntax just provides a standard way to specify functions.
É Different vendors may use vastly different hardware implementations.
É (Or indeed the CPU may be doing the GLSL work, e.g. Mesa.)
É On any hardware accelerated system, the GLSL code will be run in a massively parallel way.
É Crucially, it’s usually a single-instruction multiple-data (SIMD) approach.
É This means that conditional branches and structures such as loops may be problematic. (Particularly if threads need to diverge.)
COSC342 OpenGL shaders and programming models that provide object persistence 4 Vertex shaders
É Vertex shaders run in the vertex processor: recall that this replaced the “Transform” stage of the GL pipeline.
É Vertex shaders are given inputs including:
É uniform variables that hold the same value for all vertices;
É attributes that provide data per vertex: e.g. position, normal, colour, texture coordinates.
É Vertex shaders produce results by:
É assigning to predefined variables such as gl position—the vertex’s screen-space position;
É setting custom vertex attributes whose values are to be interpolated and provided to fragment shaders.
COSC342 OpenGL shaders and programming models that provide object persistence 5 Fragment shaders
É Fragment shaders run in the fragment processor: recall that this replaced the “Shade” stage of the GL pipeline.
É e.g. you could use a fragment shader to implement Phong shading.
É Variables that were varying outputs of the vertex shader are (constant) inputs to the fragment shader.
É Fragment shaders cause effects by assigning to predefined variables.
É e.g. gl FragColour is a vec4 that the fragment shader can set to give this fragment (almost a pixel) an RGBA value.
É Fragment shaders can also set the depth value for z-buffering.
COSC342 OpenGL shaders and programming models that provide object persistence 6 GLSL implementation of flat, constant, blue shading
É Not a particularly useful type of shading, but it does give us usefully minimal shader code.
É Our vertex shader will just ensure that vertices are transformed to screen coordinates—
void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ; }
É Our fragment shader sets all fragments to be blue—
void main() { gl_FragColor= vec4(0.0, 0.0, 1.0, 1.0); }
COSC342 OpenGL shaders and programming models that provide object persistence 7 (Simplified) GLSL Gouraud shading
Vertex shader: varying vec4 color; void main() { vec3 n= normalize(gl_NormalMatrix * gl_Normal); vec3 l= normalize(vec3(gl_LightSource[0].position)); vec3 diffuseReflection = vec3(gl_LightSource[0]. diffuse ) * max(0.0, dot(n, l)); color = vec4(diffuseReflection, 1.0); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ; }
Fragment shader: varying vec4 color; void main() { gl_FragColor = color; }
COSC342 OpenGL shaders and programming models that provide object persistence 8 GLSL Phong shading sketch—vertex and fragment shaders varying vec4 e; varying vec3 n; void main() { e = gl_ModelViewMatrix * gl_Vertex; n = normalize(gl_NormalMatrix * gl_Normal); gl_Position = ... } varying vec4 e; varying vec3 n; void main() { vec3 nn = normalize(n); vec3ne=-normalize(vec3(e)); vec3 l = ...; vec3 specularReflection; if(dot(nn, l) < 0.0) specularReflection = vec3(0.0, 0.0, 0.0); else { specularReflection = vec3(gl_LightSource[index]. specular ) * vec3(gl_FrontMaterial.specular) * pow(max (0.0 , dot(reflect(-l, nn), ne)), gl_FrontMaterial. shininess); } gl_FragColor= vec4(ambient... + diffuse... + specularReflection, 1.0); }
COSC342 OpenGL shaders and programming models that provide object persistence 9 An aside: fractals
É Fractals are shapes that have infinite detail.
É (This implies that they must be procedurally generated.)
É Often they have self-similarity: e.g. recursive structures.
É You have encountered a fractal shape in COSC342 already: the Sierpinski Gasket (fractal triangle) in the first OpenGL lab.
É A fractal such as the figure to the right has a finite volume . . . but yet has an infinite surface area!
É Simple equations can produce intricate results: e.g. iterate z = z2 + c for n+1 n complex numbers z and c to generate the Mandelbrot set.
COSC342 OpenGL shaders and programming models that provide object persistence 10 A vertex shader for a procedural texture . . .
uniform float real;// fractal’s"x" uniform float imag;// fractal’s"y" uniform float w;// width uniform float h;// height
varying float xpos;// changes across polygon varying float ypos;
void main(void) { xpos = clamp(gl_Vertex.x, 0.0,1.0)*w+real; ypos = clamp(gl_Vertex.y, 0.0,1.0)*h+imag;
// perform update ofGLSL global variables gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ; }
COSC342 OpenGL shaders and programming models that provide object persistence 11 . . . and the corresponding fragment shader
varying float xpos,ypos; void main (void) { float iter = 0.0, square = 0.0, max_square = 3.0; float r = 0.0, i = 0.0; float rt = 0.0, it = 0.0; while(iter < 1.0 && square < max_square) { rt = (r*r) - (i*i) + xpos; it = (2.0 * r * i) + ypos; r = rt; i = it; square = (r*r)+(i*i); iter += 0.005; } gl_FragColor= vec4 (iter, sin(iter*20.00), sin(iter*2.00), 1.0); }
COSC342 OpenGL shaders and programming models that provide object persistence 12 Using the Pyglet library for Python to load GLSL
vertex_shader_src =""" uniform float real,w,imag,h; varying float xpos,ypos; void main(void){ xpos= clamp(gl_Vertex.x, 0.0,1.0)*w+real; ypos= clamp(gl_Vertex.y, 0.0,1.0)*h+imag; gl_Position= gl_ModelViewProjectionMatrix* gl_Vertex; } """ program = gl.glCreateProgram() vertex_shader = self.create_shader(vertex_shader_src, gl.GL_VERTEX_SHADER) gl.glAttachShader(self.program, vertex_shader) gl.glLinkProgram(self.program) message = self.get_program_log(self.program) if message: raise ShaderException(message)
COSC342 OpenGL shaders and programming models that provide object persistence 13 Maybe next time?
COSC342 OpenGL shaders and programming models that provide object persistence 14 Persistent object modelling
É In OpenGL, you draw it, and it’s on-screen (more or less). É ... however you can’t later ask OpenGL what objects were drawn.
É (Although you can ask OpenGL to tell you pixel values.)
É Nonetheless, you probably want the next frame you are going to draw to be closely related to the one you just drew.
É Ideally you could explain to a graphics framework what your objects are, and it can maintain this state for you.
É There are many ways to acquire this functionality, such as through game engines (e.g. Unity3D, Blender, etc.), and scene-graph libraries.
COSC342 OpenGL shaders and programming models that provide object persistence 15 Scene graphs
É When building a computer model of a bicycle—just as you would when building a real bicycle—you are likely to use discrete parts.
É A scene graph allows us to store a model that retains these constituent components.
COSC342 OpenGL shaders and programming models that provide object persistence 16 Parameterised scene graphs
É Duplicated objects in our scene should share the same nodes in the scene-graph.
É Note that we can use nodes to hold matrices, as well as geometry.
É The transformations in a matrix node will apply to all children of that node.
COSC342 OpenGL shaders and programming models that provide object persistence 17 Further decomposition of our bicycle scene graph
É In the case of our bicycle model, we can apply further geometric decomposition:
É a wheel is itself made up of subcomponents
...
COSC342 OpenGL shaders and programming models that provide object persistence 18 Standard Vector Graphics (SVG)
É The persistence mechanism for SVG is the HTML DOM.