## CS424 Notes, 23 January 2012

- About Coordinate Systems
- We start with some leftover material on coordinate systems from Friday's class.

- Minimal Vertex and Fragment Shaders
- Here are just about the simplest shaders you can use to get something on the screen.
When a primitive is drawn, any fragments in that primitive are colored yellow. To get
any primitives at all, we need an attribute to specify its vertices, and the vertex shader
has to assign a value to
`gl_POSITION`representing the coordinates in the default coordinate system.**Vertex shader source code:**attribute vec2 vertexCoords; void main() { gl_Position = vec4(vertexCoords.x, vertexCoords.y, 0.0, 1.0); }**Fragment shader source code:**void main() { gl_FragColor = vec4(1.0,1.0,0.0,1.0); } - Suppose that we wanted to be able to draw different primitives in different colors.
What would we have to add to these shaders? Where? [Answer: A uniform variable in the
fragment shader.] Here is a fragment shader that does this.
precision mediump float; uniform vec4 color; void main() { gl_FragColor = color; }

(The "precision mediump float will require some explanation.) - Suppose that we wanted to be able to assign different colors to different vertices in
the same primitive, with the colors "interpolated" to the interiors of the primitives?
What would we have to add to the shader programs? [Answer: An attribute to vertex shader
to represent the vertex colors, and a varying variable to both the vertex and fragment
shaders.] You will
**do**this on Thursday.

- Here are just about the simplest shaders you can use to get something on the screen.
When a primitive is drawn, any fragments in that primitive are colored yellow. To get
any primitives at all, we need an attribute to specify its vertices, and the vertex shader
has to assign a value to
- About the vertex shader language
- The language is GLSL ES 1.0. It is based on C.
- The only control structures that you can depend on are
**if**and simple**for**loops, although**while**and**do**loops seem to be an (optional?) part of the specification. There is no**switch**. - You can have functions, arrays, and structs. Non-constant array indices might not work in some cases, though they should always work with arrays that are uniform variables.
- Both the vertex shader and the fragment shader must have a function
`void main()`. This is the function that is called for each vertex/fragment in the primitive. - Predefined types include
float int bool (int/bool might actually be implemented as float) vec2 ivec2 bvec2 (vectors containing 2 float/int/bool values) vec3 ivec3 bvec3 (vectors containing 3 float/int/bool values) vec4 ivec4 bvec4 (vectors containing 4 float/int/bool values) mat2 (2-by-2 matrices of floats) mat3 (3-by-3 matrices of floats) mat4 (3-by-3 matrices of floats)

The vector and matrix types are useful in the kinds of math that are used in graphics. - Variables can be declared with the qualifiers
`attribute`,`uniform`,`varying`. (`attribute`can only be used in vertex shaders.) - Variables of type
*int*and*float*can be declared as`highp`,`mediump`, or`lowp`. For example:uniform lowp vec4 color;

These are*precision qualifiers*. They exist to allow the GPU to use lower precision computations when appropriate. Fragment shaders are not required to support`highp`! And in fragment shaders, there is no default precision, so you have to specify one for each integer or floating point variable! (See page 3 of the WebGL Quick Reference Card.) - The declaration "
`precision mediump float`" says that all subsequent floats will be meduim precision.

- Constructors, indexing, and swizzlers for vecs
- If
`vctr`is of type*vec4*, you can refer to the four elements of`vctr`as`vctr[0]`, ...,`vctr[3]`**or**, more commonly, as`vctr.x`,`vctr.y`,`vctr.z`,`vctr.w`. You can**also**use`vctr.r`,`vctr.g`,`vctr.b`,`vctr.a`(since*vec4*can be used to represent colors as well as coordinates). Similarly for*vec2*,*ivec4*, etc. - Matrices can be indexed just like 2-dimensional arrays (
`m[2][0]`), but the indexing uses column-major order. That is, the first index specifies the column and the second index specifies the row. - If
`vctr`is a*vec4*, then`vctr.xy`is the*vec2*made up of the numbers`vctr.x`and`vctr.y`. You could do`vctr.yx`, which puts the y-value before the x-value. You could do`vctr.xx`, which uses two copies of the x-value. Similarly for`vctr.xyz`,`vctr.zy`,`vctr.xxzz`, etc. (This is known as*swizzling*.) - Vector values are made with
*constructors*such as`vec3(1.0,2.3,3.1)`. You can use swizzlers in constructors to provide more than one number at a time, for example,`vec3(0.0,vctr.xy)`or`vec4(vertexCoords.xy,0.0,1.0)`. - There are also constructors for matrices.

- If
- Operators and functions
- The shader language has most of C's operators (but
**not**the bitwise logical operators like`&`,`|`, and`<<`). - The arithmetic operators
`+`,`-`,`*`and`/`are extended to work with vectors and matrices. In particular,`+`and`-`are used for vector addition and subtraction, and`*`is used to do matrix multiplication or to multiply a matrix by a vector. We will learn about this when we need it, mostly to do lighting computations. - You can also operate on a vector and a float. For example, if
`vctr`is a vector,`vctr*2.0`will create the vector that is obtained by multiplying each component of`vctr`by 2.0 - There are many predefined functions, including a lot that are specifically useful in graphics. Take a look at page 4 of the WebGL Quick Reference Card.

- The shader language has most of C's operators (but
- Examples
`gl_Position`is a special, predefined variable of type*vec4*in the vertex shader. The vertex shader should always assign a value to this variable. The*w*-coordinate of this vector should be 1.0 for now. It will be a while before we see why four coordinates are used for 3D graphics.`gl_FragColor`is a special, predefined variable of type*vec4*in the fragment shader. The fragment shader should assign a value to this varaible, unless it wants to disgard the fragment entirely. (To discard the fragment, the fragment shader uses the build-in command`discard;`which will terminate the fragment shader and stop any further processing of that fragment.)- Suppose that you have two colors represented by variables
*c1*and*c2*of type*vec3*, with RGB components in the range 0.0 to 1.0. Suppose you want*gl_FragColor*to be a color that blends 30% of*c1*with 70% of*c2*. you could say:gl_FragColor = c1 * 0.3 + c2 * 0.7;

As it turns out, this is such a common operation that there is a built-in function for doing it, so you could also say:gl_FragColor = mix(c1,c2,0.3);

The function*mix(x,y,a)*computes`x*a+y*(1-a)`, and it works when x and y are*float*,*vec2*,*vec3*, or*vec4*.