320 likes | 559 Views
95.4002. Shaders. Shaders. Shaders are programs that you can download onto the card Can be used for manipulating triangle vertices and pixels (you can modify vertices and pixels but not create them). A NEW KIND OF SHADER (NOT MUCH IN USE YET) ALLOW VERTICES TO BE CREATED… .
E N D
95.4002 Shaders
Shaders • Shaders are programs that you can download onto the card • Can be used for manipulating triangle vertices and pixels (you can modify vertices and pixels but not create them). A NEW KIND OF SHADER (NOT MUCH IN USE YET) ALLOW VERTICES TO BE CREATED…
The Programs are in a C-Like Language • Those shaders that modify vertices are called vertex shaders. • Those shaders that modify pixels are called pixel shaders(or fragment shaders). • Those shaders that create vertices are called geometry shaders(not discussed any further in these notes). You can’t just have a vertex shader or a pixel shader. You need both.
How it works • Given a triangle for the card to draw. • 3vertex shadersare run each producing output…; e.g., texture coordinate. • If there are 10,000 pixels in the triangle, 10,000 pixel shaders are run whose input is an interpolated value of the texture coordinate…; each produces a 1 pixel output… If anything is a bottleneck, it’s the pixel shader.
Many Steps To Running a Shader glShaderSource glCompileShader glCreateShader glAttachShader source source compile attach sample.vert glCreateProgram create program sample.frag glCreateShader glShaderSource glCompileShader glAttachShader source source compile attach glLinkProgram glUseProgram link use
And a Few Steps To Discarding a Shader glDetachShader glDeleteShader sample.vert detach delete glDeleteProgram program delete program glDetachShader glDeleteShader sample.frag detach delete
Variables: 3 Categories Globals: can be set permanently and changed any time; accessible by both shaders uniform Vertex shader: vertex information like position, normal, texture coord. Pixelshader: output of vertex shader in Vertex shader: output to pixel shader. Pixelshader: pixel to draw out
Variables: 3 Categories (Another Viewpoint) in Vertex data: position, texture coordinates sample.vert Transfer data is interpolated; e.g., texture coordinate out Globals uniform 3 choices: smooth, noperspective, flat in Transfer data which was interpolated sample.frag out ONE color
Shader versions • We will be usingversion 130 which permits access to openGL variables. • Newer versions eliminate those entirely in favor of variables that are ENTIRELY USER DEFINED… • Source code for vertex and pixel shaders are in SEPARATE FILES. Soon, we’ll have to switch to version 140 or 40 which is even newer… Then EVERYTHING HAS TO BE PASSED VIA USER NAMES
sample.vert #version 130 //Implied in variables: gl_Vertex, gl_Normal, gl_MultiTexCoord0, gl_MultiTexCoord1, gl_Color… //Matrices available: gl_ModelViewMatrix, gl_ProjectionMatrix //Goal of shader: // 1. To compute gl_Position in projection coordinates. // 2. To pass along information needed by pixel shader; e.g., texure coordinates and color //The globals… uniform float brightness; //For use by the vertex shader… uniform mat4 unused; //But WHAT IF we wanted to use it… //uniform sampler2D texture; //For use by the pixel shader… //The information passed along. Note: smooth is default rather than noperspective or flat… out vec2 smooth textureCoordinate; out vec4 smooth pixelColor; void main () { textureCoordinate = gl_MultiTexCoord0.xy; //From vec4 to vec2… gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * gl_Vertex); pixelColor= vec4 (gl_Color.xyz * brightness, gl_Color.a); } Interpolated for pixel shader Matrices operate right to left All matrices are transposed CONCEPTUALLY
sample.frag #version 130 //Implied in variables: gl_Vertex, gl_Normal, gl_MultiTexCoord0, gl_MultiTexCoord1, gl_Color… //Matrices available: gl_ModelViewMatrix, gl_ProjectionMatrix //Goal of shader: // 1. To receive information from vertex shader. // 2. To compute final pixel color //The globals… //uniform float brightNess; //For use by the vertex shader… uniform sampler2D texture; //For use by the pixel shader… //The information passed along. Note: smooth is default rather than noperspective or flat… invec2 smooth textureCoordinate; invec4 smooth pixelColor; out vec4 finalColor; //Or special built-in variable gl_FragColor void main () { vec4 textureColor = texture2D (texture, textureCoordinate); //gl_FragColor = textureColor * pixelColor; finalColor= textureColor * pixelColor; } Set up in engine by activating the texture on texture unit 0 Interpolated for pixel shader Available in version 130
Arithmetic Data Types • float, int, uint, bool. • vec , ivec , uvec , bvec , • mat2, mat3, mat4, matcr • arrays; e.g., vec4 points [10]; 234 234 234 234 1 0 0 tx mat43 = 0 1 0 ty 0 0 1 tz To discard perspective column Internally, EVERYTHING is a float…
Texture Data Types are called SAMPLERS • sampler1Dtexture0; • sampler2Dtexture1; //Standard one • samplerCubetexture2; //6 Pictures • sampler2DShadowtexture3; //Depth texture • samplerBuffertexture4; //Texture Buffer • sampler2DArraytexture5 [3]; //??? There are many more…
Conversion • No automatic conversion; use swizzlingxyzw or rgba or stpq. • vec4 data0; float data1 = data0.x; vec2 data2 = data0.xy; vec3 data3 = data0.xyz; vec4 data4 = data0.xyzw; //Swizzle not needed Swizzle can change the order and duplicate; e.g., data0.xzyy
Constructors are Used To Initialize • vec4 color = vec4 (1.0, 1.0, 1.0, 0.5); • vec4 data = vec4 (1.0); //Initializes all to 1.0 • mat4 matrix = mat4 (1.0); //Diagonals 1.0; others 0.0 • mat4test = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,tx, ty, tz, 1.0}; • vec4 translation = test [3]; //Can index columns column [0] column [1] column [2] column [3] Matrices are CONCEPTUALLY columns…
A Huge Library Of Functions • Operators: +,-,++,--,*,/,&&,||,<<,>>, … • Functions: radians (degrees), degrees (radians), sin, cos, tan, asin, acos, atan, pow (x,y), exp (x), log, sqrt, inversesqrt, abs, sign, trunc, round, ceil, min, max, clamp (x,min,max), mix (x,y,t) //lerp Look them up as you need them…
Making the Connection From Engine To Shader… • Need to describe vertex layouts in engine. • Need to initialize uniforms in engine. • Need to activate textures with texture and also map them to samplers in the engine. • Need to tell the card to now use a pair of specific shaders… Let’s consider each case one by one…
Describing Vertex Layouts in the Engine … void activateVertices () { glBindBuffer (GL_ARRAY_BUFFER, verticesBuffer); long stride = sizeof (GamePoint); long doubleSize = sizeof (double); glVertexPointer (3, GL_DOUBLE, stride, (void *) (0)); glEnableClientState (GL_VERTEX_ARRAY); glTexCoordPointer (2, GL_DOUBLE, stride, (void *) (3 * doubleSize)); glEnableClientState (GL_TEXTURE_COORD_ARRAY); glNormalPointer (GL_DOUBLE, stride, (void *) (5 * doubleSize)); glEnableClientState (GL_NORMAL_ARRAY); } This is a version 130 technique (OLD WAY);see faceGroup.h
Describing Vertex Layouts in the Engine: Step 1 • Lookup the names of the components of your vertex in the vertex shader…; e.g., SUPPOSE YOUR SHADER CONTAINS • in vec4 vertexPosition; in vec2 vertexTextureCoordinate0; in vec3 vertexNormal; This is a version 140 technique (NEW WAY).
Describing Vertex Layouts in the Engine: Step 2 void activateVertices (Glint shaderProgram, void *vertices) { long stride = sizeof (GamePoint); const bool no = false; //Don’t normalize… Glint p = shaderProgram; long index; if ((index = glGetAttribLocation (p, "vertexPosition")) != -1) {glVertexAttribPointer (index, 3, GL_DOUBLE, no, stride, &vertices->x); glEnableVertexAttribArray (index);} if ((index = glGetAttribLocation (p, "vertexTextureCoordinate0")) != -1) { glVertexAttribPointer (index, 2, GL_DOUBLE, no, stride, &vertices->tx); glEnableVertexAttribArray (index);} if ((index = glGetAttribLocation (p, "vertexNormal")) != -1) { glVertexAttribPointer (index, 3, GL_DOUBLE, no, stride, &vertices->nx); glEnableVertexAttribArray (index);} } a component is a vec4 how much of a component to use…
Initializing Uniforms in the Engine … void initializeGlobals (Glint shaderProgram) { //Recall: uniform float brightness; //For use by the vertex shader… //Recall: uniform mat4 unused; Glint p = shaderProgram; long index; if ((index = glGetUniformLocation (p, "brightness")) != -1) { float brightness = 0.8; glUniform1f (index, brightness); //long howMany = 10; //If we had declared uniform float brightness [10]; //glUniform1f (index, howMany, brightness); //Array version… if ((index = glGetUniformLocation (p, “unused")) != -1) { const boolnoTranspose = GL_FALSE; FloatTransformation transformation = Transformation::Identity.asFloat(); glUniformMatrix4fv (index, 1, noTranspose, &transformation);} } a component is a vec4 how much of a component to use…; 1, 2, 3, or 4. Needs float transformations how many transformations
Activating Textures/Samplers in the Engine … • Textures need to be activated in the normal way…e.g., assuming multiple texture coord… • glActiveTexture (GL_TEXTURE0); //or 1, 2, .. • glBindTexture (textureHandle); • glEnable (GL_TEXTURE_2D); //Ignored • Tell the shader which texture unit to use… long index; if ((index = glGetUniformLocation (p, “texture")) != -1) { glUniform1i (index, 0);| } texture unit
Telling the Card To Use A Particular Shader… glUseProgram (shaderProgram);
Demos Demos
“simple” VERTEX Shader (“simple.vert”) #version 130 //Implied in variables: gl_Vertex, gl_Normal, gl_MultiTexCoord0, gl_MultiTexCoord1, gl_Color… //Matrices available: gl_ModelViewMatrix, gl_ProjectionMatrix, … uniform float brightness; //For use by the vertex shader… //The information passed along. Note: smooth is default rather than noperspective or flat… out vec2 textureCoordinate; out vec4 pixelColor; void main () { textureCoordinate = gl_MultiTexCoord0.xy; //From vec4 to vec2… gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * gl_Vertex); pixelColor = vec4 (gl_Color.xyz * brightness, gl_Color.a); } pass through via out MUST transform position
“simple” PIXEL Shader (“simple.frag”) #version 130 uniformsampler2D texture; //For use by the pixel shader… invec2 textureCoordinate; in vec4 pixelColor; out vec4 finalColor; //Or special built-in variable gl_FragColor void main () { vec4 textureColor = texture2D (texture, textureCoordinate); finalColor = textureColor * pixelColor; } pass through via in MUST output color
“diffuse” VERTEX Shader (“diffuse.vert”) #version 130 uniform vec3 lightDirection; out vec3 lightDirectionInCameraSpace; outvec3 normalInCameraSpace; out vec2 textureCoordinate; out vec4 pixelColor; //Like before… void main () { //Convert the normal to camera space and pass along //with the camera light direction also in camera space. mat3 rotationOnly = mat3 (gl_ModelViewMatrix); lightDirectionInCameraSpace = lightDirection; normalInCameraSpace = rotationOnly * gl_Normal; //inverse transpose… textureCoordinate = gl_MultiTexCoord0.xy; //From vec4 to vec2… gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * gl_Vertex); pixelColor = gl_Color; } pass through via out MUST transform position Should have used
“diffuse” PIXEL Shader (“diffuse.frag”) #version 130 uniform sampler2D texture; in vec3 lightDirectionInCameraSpace; in vec3 normalInCameraSpace; in vec2 textureCoordinate; in vec4 pixelColor; //Like before… out vec4 finalColor; //Or special built-in variable gl_FragColor void main () { vec4 textureColor = texture2D (texture, textureCoordinate); vec4 unlitColor = textureColor * pixelColor; //Like before but renamed… vec3 normalVector = normalize (normalInCameraSpace); vec3 lightVector = lightDirectionInCameraSpace; //It's constant... //Dot product gives 0 when 90 degrees, maximum when 0 degrees... float diffuse = dot (normalVector, lightVector); finalColor = unlitColor * diffuse; } pass through via in diffuse scales color
“specular” VERTEX Shader (“specular.vert”) #version 130 SAME AS “diffuse.vert”
“specular” PIXEL Shader (“specular.frag”) #version 130 //Variables SAME AS “Diffuse” shader void () { vec4 textureColor = texture2D (texture, textureCoordinate); vec4 unlitColor = textureColor * pixelColor; vec3 normalVector = normalize (normalInCameraSpace); vec3 lightVector = lightDirectionInCameraSpace; //It's constant... vec3 eyeVector = vec3 (0.0, 0.0, 1.0); //NEW NEW float diffuse = dot (normalVector, lightVector); vec3 halfAngle = normalize (eyeVector + lightVector); //NEW NEW float specular = max (dot (normalVector, halfAngle), 0.0); //NEW NEW finalColor = unlitColor * diffuse + unlitColor * (4.0 * pow (specular, 32.0)); }
“wobbler” VERTEX Shader (“wobbler.vert”) #version 130 SAME AS “specular.frag” but changed how position is computed uniform float time; //To control the sin wave… //Compute a modified vertex before transforming it... float timeFrequency = 8.0; float spaceFrequency = 4.0; float amount = 0.5 * (0.75 + sin (time * timeFrequency + (gl_Vertex.x + gl_Vertex.z) * spaceFrequency)); vec4 position = vec4 ( gl_Vertex.xyz + gl_Normal * amount * 0.215, gl_Vertex.w);
“wobbler” PIXEL Shader (“wobbler.frag”) #version 130 SAME AS “specular.frag”