1 of 43

Shader Programming

with GLSL

Instructor: Christopher Rasmussen (cer@cis.udel.edu)

February 24, 2023 ❖ Lecture 9

2 of 43

Outline

  • GLSL tutorial
    • Portions adapted from CIS 565 “GPU Programming & Architecture” slides (Patrick Cozzi, instructor) at U. Pennsylvania
  • Texturing and GLSL
  • HW #1 due on Monday

3 of 43

OpenGL from 3.0

from Orange Book

Vertex shader

  • Operates on single vertex, executed in parallel
  • Input includes position, color, normals, etc.
  • Must take care of:
    • Model, view, and perspective transformations
    • Texture coordinate generation & transformations
    • Normal transformations
    • Lighting per vertex

Fragment shader

  • Operates on single fragment, executed in parallel
  • Fragment = info necessary for pixel...but might not get drawn
  • Must set color, can use:
    • Per-pixel lighting (aka shading, next week)
    • Fog (depth-dependent color)
    • Access/apply textures
    • Blending, convolution

4 of 43

Other Shader types

  • Geometry shader
    • Can "emit" more vertices -- can use for splines, terrain generation, particle spawning, etc.
  • Compute shader
    • Do calculations that (mostly) don't lead to rendering
  • Primitive shader (AMD)
    • Combines aspects of vertex shader, compute shader, and fixed function primitive assembly
  • Mesh shader (Nvidia)
    • Operates on multiple primitives or meshlets for efficiency and produces triangles for rasterizer

5 of 43

GLSL (GL Shading Language)

  • High-level (C-like) language for vertex, fragment, & other shader programs
    • Links on course page to "Orange book," tutorials
  • Compiler, linker tightly integrated with OpenGL driver…part of “core” for OpenGL > 3.0
  • Alternatives
    • HLSL (Microsoft, only on Windows/XBox with Direct3D), PSSL for PS4...not sure about PS5
    • Cg (created by Nvidia, cross platform, works with OpenGL, Direct3D, PS3). DISCONTINUED!

6 of 43

GLSL Syntax Overview

  • GLSL is like C without
    • Pointers, objects (but structs are still there)
    • Recursion
    • Gotos, switches
    • Dynamic memory allocation

7 of 43

GLSL Syntax Overview

  • GLSL is like C without
    • Pointers, objects (but structs are still there)
    • Recursion
    • Gotos, switches
    • Dynamic memory allocation
  • GLSL is like C with
    • Built-in vector, matrix and sampler types
    • Constructors
    • Good math library
    • Input and output qualifiers (aka designating variables for reading and variables for writing)

More details...and see last several slides for more functions

8 of 43

GLSL Syntax Overview

  • If you change your GLSL shader program(s), you don't need to recompile
  • They are loaded and compiled dynamically with LoadShaders() utility function in .cpp
  • If you want to change shader program name, make sure to change corresponding string in call to LoadShaders()
  • Multiple programs can be loaded and switched between -- we won't cover this

9 of 43

Original tutorial03 .vertexshader

#version 330 core

// Input vertex data, different for all executions of shader

layout(location = 0) in vec3 vertexPosition_modelspace;

// Values that stay constant for the whole mesh.

uniform mat4 MVP;

void main()

{

// Output position of the vertex (clip space) = MVP * position

gl_Position = MVP * vec4(vertexPosition_modelspace,1);

}

10 of 43

GLSL Syntax: Types

  • Scalar types: float, int, uint, bool
    • Can do casts: int i = int(0.0);
  • Vectors, matrices are first-class types:
    • vec2, vec3, vec4
    • ivec, bvec: Integer, boolean vectors
    • mat2, mat3, mat4 (2x2, 3x3, 4x4)
      • Can also do m x n; stored in column-major format
  • Samplers (aka textures)
    • sampler1D, sampler2D, sampler3D, etc.

11 of 43

GLSL Syntax: Vectors

  • Constructors

vec3 xyz = vec3(1.0, 2.0, 3.0);

vec3 xyz = vec3(1.0); // [1.0, 1.0, 1.0]

vec3 xyz = vec3(vec2(1.0, 2.0), 3.0);

vec4 xyzw = vec3(xyz, 1.0);

12 of 43

GLSL Syntax: Vectors

  • Constructors

  • Access components three ways
    • .x, .y, .z, .w position or direction
    • .r, .g, .b, .a color
    • .s, .t, .p, .q texture coordinate
    • But don’t mix
      • OK: myColor.xyz
      • No! myColor.xgb or vec3.xrs

vec3 xyz = vec3(1.0, 2.0, 3.0);

vec3 xyz = vec3(1.0); // [1.0, 1.0, 1.0]

vec3 xyz = vec3(vec2(1.0, 2.0), 3.0);

vec4 xyzw = vec3(xyz, 1.0);

13 of 43

GLSL Syntax: Matrices

  • Constructors

  • Accessing elements

mat3 i = mat3(1.0); // 3x3 identity matrix

mat2 m = mat2(1.0, 2.0, // [1.0 3.0]

3.0, 4.0); // [2.0 4.0]

float f = m[column][row];

float x = m[0].x; // x component of first column

vec2 yz = i[1].yz; // yz components of second column

Treat matrix as array of column vec2’s

Can "swizzle" (select or

rearrange components) too

14 of 43

GLSL Syntax: Vectors and Matrices

  • Matrix and vector operations are easy and fast:

vec3 xyz = // ...

vec3 v0 = 2.0 * xyz; // scale

vec3 v1 = v0 + xyz; // component-wise

vec3 v2 = v0 * xyz; // component-wise

float f = dot(v0, v1); // dot product

vec3 v2 = cross(v0, v1); // cross product

vec3 v3 = normalize(v2); // “unitize”

mat3 M = // ...

mat3 N = // ...

mat3 MN = M * N; // matrix * matrix

vec3 xyz2 = MN * xyz; // matrix * vector

15 of 43

Original tutorial03 .vertexshader

#version 330 core

// Input vertex data, different for all executions of shader

layout(location = 0) in vec3 vertexPosition_modelspace;

// Values that stay constant for the whole mesh

uniform mat4 MVP;

void main()

{

// Output position of the vertex (clip space) = MVP * position

gl_Position = MVP * vec4(vertexPosition_modelspace,1);

}

16 of 43

Type qualifiers

  • const
    • Variables that do not change (compile time constant)
  • uniform
    • Variables that may change per primitive
  • attribute
    • Variables that may change per vertex
  • varying
    • Variables that may change per fragment

17 of 43

Type qualifiers

  • const
    • Variables that do not change (compile time constant)
  • uniform
    • Variables that may change per primitive
  • attribute
    • Variables that may change per vertex
    • Passed from OpenGL app to vertex shaders (VS)
    • Read-only variable
  • varying
    • Variables that may change per fragment
    • Interpolated data between VS & fragment shader (FS)
    • Can be written in VS, read-only in FS

attribute, varying not used in OGL Tutorials

18 of 43

Type qualifiers

  • const
    • Variables that do not change (compile time constant)
  • uniform
    • Variables that may change per primitive
    • Passed from OpenGL app to shaders (see "MVP" variable in x_tutorial03.cpp) via glUniformMatrix4fv() and glGetUniformLocation()
    • Can be used in vertex or fragment shaders, where they are read-only

19 of 43

Original tutorial03 .vertexshader

#version 330 core

// Input vertex data, different for all executions of shader

layout(location = 0) in vec3 vertexPosition_modelspace;

// Values that stay constant for the whole mesh

uniform mat4 MVP;

void main()

{

// Output position of the vertex (clip space) = MVP * position

gl_Position = MVP * vec4(vertexPosition_modelspace,1);

}

20 of 43

Layout

  • How to get arrays of user-defined values into the vertex shader
  • Index specifies which attribute in vertex array to use
    • Position
    • Normal
    • Color
    • Etc.
  • See this for GLSL syntax & glVertexAttribPointer() in .cpp for references to vertex/color arrays

21 of 43

in, out qualifiers; "built-in" variables

  • in qualifier:
    • Shader-stage input variables
    • Given value by previous stage
    • Cannot be changed by user code
  • out qualifier
    • Shader-stage output variables
    • Passed to next stage of pipeline
    • Must be set at some point during shader execution
  • Built-in variables
    • gl_Position: Output of vertex shader
    • gl_FragCoord, gl_FragDepth: Inputs to fragment shader

22 of 43

Modified .vertexshader in HW #1

(additions to tutorial 3 version in bold)

#version 330 core

// Input vertex data, different for all executions of shader

layout(location = 0) in vec3 vertexPosition_modelspace;

layout(location = 1) in vec3 vertexColor;

// Values that stay constant for the whole mesh

uniform mat4 MVP;

out vec3 fragmentColor;

void main()

{

// Output position of the vertex (clip space) = MVP * position

gl_Position = MVP * vec4(vertexPosition_modelspace,1);

fragmentColor = vertexColor;

}

23 of 43

Old .fragmentshader in HW #1

#version 330 core

// Output data

out vec3 color;

void main()

{

// Output color = red

color = vec3(1,0,0);

}

24 of 43

Modified .fragmentshader in HW #1

#version 330 core

// Output data

out vec3 color;

in vec3 fragmentColor;

void main()

{

color = fragmentColor;

}

25 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here

26 of 43

Texture example: Keyboard handling

  • q = quit
  • Change background color: 'r', 'g', or 'b'
  • Change camera position: 'a'/'d' (X) or 'w'/'s' (Y)
  • x = toggle perspective/ortho projection
  • o = toggle blend/no blend
  • p = animate spin
  • Draw mode: 1 (points), 2 (lines), 3 (filled triangles)
  • z = return to default position
  • c = toggle 2-D pattern vs 3-D "city" model
  • t = rotate through 5 texture modes (uniform var)
    • 0 = only model color
    • 1 = only texture
    • 2 = average of model and texture color
    • 3 = component-wise product of model & texture color
    • 4 = animated noise pattern (see next slide)

27 of 43

More fun with fragment shaders

  • Adapted fragment shader from shadertoy.com (link broken)
  • System time sent as float uniform for animation, texture coords used as pattern function parameters
  • We will cover noise() later in semester

28 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here
    • UV texture coordinates -- the "map" between an image and the shape it is associated with

2-D Texture

3-D Shape

29 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here
    • UV texture coordinates

A texture "atlas" -- multiple patterns stored in single "texture" for time & memory efficiency

Credit to Christoph Kreusche

3-D scene

2-D texture source

30 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here
    • UV texture coordinates
    • Put UV coords in another vertex attribute array to send to shaders

31 of 43

Layout

  • How to get arrays of user-defined values into the vertex shader
  • Index specifies which attribute in vertex array to use
    • Position
    • Normal
    • Color
    • Etc.
  • See this for GLSL syntax & glVertexAttribPointer() in .cpp for references to vertex/color/UV arrays

32 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here
    • UV texture coordinates
    • Put UV coords in another vertex attribute array to send to shaders
    • Loading an image and binding current texture -- happens in common/texture.cpp's loadBMP_custom()

33 of 43

Basic Textures with OpenGL + GLSL

  • Look at tutorial #5; I added textures to our interactive "city" program here
    • UV texture coordinates
    • Put UV coords in another vertex attribute array to send to shaders
    • Loading an image and binding current texture -- happens in common/texture.cpp's loadBMP_custom()
    • Samplers and accessing texels in fragment shader with sampler1D, sampler2D, sampler3D, etc.

34 of 43

More GLSL language features/API

35 of 43

GLSL Built-in Functions

  • Selected vector, matrix functions

vec3 l, n; // = . . .

vec3 p, q; // = . . .

float f = length(l); // vector length

float d = distance(p, q); // dist between pts

mat4 m = // ...

mat4 t = transpose(m);

float d = determinant(m);

mat4 d = inverse(m);

36 of 43

GLSL Syntax: Vectors

  • Swizzle: select or rearrange components

vec4 c = vec4(0.5, 1.0, 0.8, 1.0);

vec3 rgb = c.rgb; // [0.5, 1.0, 0.8]

vec3 bgr = c.bgr; // [0.8, 1.0, 0.5]

vec3 rrr = c.rrr; // [0.5, 0.5, 0.5]

c.a = 0.5; // [0.5, 1.0, 0.8, 0.5]

c.rb = 0.0; // [0.0, 1.0, 0.0, 0.5]

float g = rgb[1]; // indexing, not swizzling

37 of 43

GLSL Built-in Functions

  • reflect(-l, n)
    • Given l and n, find r. Angle in equals angle out

  • refract()
  • faceforward()

n

l

r

38 of 43

GLSL Built-in Functions

  • Selected vector rational functions

vec3 p = vec3(1.0, 2.0, 3.0);

vec3 q = vec3(3.0, 2.0, 1.0);

bvec3 b = equal(p, q); // (F, T, F)

bvec3 b2 = lessThan(p, q); // (T, F, F)

bvec3 b3 = greaterThan(p, q); // (F, F, T)

bool b4 = any(b); // T

bool b5 = all(b); // F

39 of 43

GLSL Built-in Functions

  • Rewrite in one line of code

bool foo(vec3 p, vec3 q)

{

if (p.x < q.x)

return true;

else if (p.y < q.y)

return true;

else if (p.z < q.z)

return true;

return false;

}

return any(lessThan(p, q));

40 of 43

GLSL Built-in Functions

  • Selected trigonometry functions

float s = sin(theta);

float c = cos(theta);

float t = tan(theta);

float phi = asin(s);

// ...

vec3 angles = vec3(/* ... */);

vec3 vs = sin(angles);

Works on vectors component-wise

Angles are measured

in radians

41 of 43

GLSL Built-in Functions

  • Exponential Functions

float xToTheY = pow(x, y);

float eToTheX = exp(x);

float twoToTheX = exp2(x);

float l = log(x); // ln

float l2 = log2(x); // log2

float s = sqrt(x);

float is = inversesqrt(x);

42 of 43

GLSL Built-in Functions

  • Selected common functions

float ax = abs(x); // absolute value

float sx = sign(x); // -1.0, 0.0, 1.0

float m0 = min(x, y); // minimum value

float m1 = max(x, y); // maximum value

float c = clamp(x, 0.0, 1.0);

// many others: floor(), ceil(), …

43 of 43

GLSL Built-in Functions

  • mix(x, y, a) // linear interpolation
    • x, y: start, end of range
    • a: Interpolation value in range [0, 1]
  • step(edge, x)
    • Returns 0 if x < edge, 1 otherwise
  • smoothstep(edge1, edge2, x)
    • edge1 = value of lower edge of step
    • edge2 = value of upper
    • x = value to be interpolated along S-curve