My OpenGL thematic learning directory, hope to learn with you exchange progress!

  • OpenGL Learning (I) – Terminology understanding
  • OpenGL learning (2) — Xcode build OpenGL environment
  • OpenGL learning (three) – OpenGL base rendering
  • OpenGL learning (4) – front & back culling and depth testing
  • OpenGL Learning (5) – Cropping and Blending
  • OpenGL Learning (6) – Base textures
  • OpenGL Learning (7) — Summary of basic change Comprehensive Exercise practice
  • OpenGL ES Learning (8)
  • OpenGL learning (nine) — OpenGL ES preliminary exploration (next) GLKit
  • OpenGL learning (10) – GLSL syntax introduction
  • OpenGL learning (11) – using GLSL to load pictures
  • OpenGL learning (12) — OpenGL ES texture flipping strategy comparison

A list,

GLSL (OpenGL Shading Language) is a Language for Shading programming in OpenGL, that is, short custom programs written by developers that they execute on the graphics card’s GPU instead of a fixed part of the rendering pipeline, Make different layers in the render pipeline programmable. GLSL uses C as its basic high-level coloring language, avoiding the complexity of using assembly language or hardware specification language.

Variable naming

GLSL variables are named in a similar way to C. They can be named using letters, numbers, and underscores (_), but cannot start with a number. Also note that variable names cannot be prefixed with gl_, which is a GLSL reserved prefix for GLSL internal variables.

Data types

1. Basic data types

type describe
void withCThe language of thevoidSimilarly, represents an empty type. As the return type of a function, indicating that the function does not return a value.
bool Boolean type.truefalse, and expressions that can produce Booleans.
int Signed integer
uint Unsigned shaping
float floating-point

2. Special Type — Texture sampling type

type describe
sampler1D Used to reference the specified in the built-in texture functionHandle to 1D texture. Can only be used as a consistent variable or function parameter
sampler2D 2d texture handle
sampler3D Handle to 3d texture
samplerCube Cube Map texture handle
sampler1DShadow One-dimensional depth texture handle
sampler2DShadow 2d depth texture handle

3. Aggregate types (vector and matrix types)

(1) Vector type

type describe
vec2,vec3,vec4 2-component, 3-component, and 4-component floating point vectors
ivec2,ivec3,ivec4 2-component, 3-component, and 4-component integer vectors
uvec2,uvec3,uvec4 2-component, 3-component, and 4-component unsigned integer vectors
bvec2,vbec3,bvec4 2 -, 3 -, and 4-component Boolean vectors

A, 􏰴􏰜􏰷􏰸 vector declaration — 4-component float vector

vec4 V1;
Copy the code

B, 􏰴􏰜􏰷􏰸 declare vectors and construct them

vec4 V2 = vec4(1.2.3.4);
Copy the code

C, 􏰴􏰜􏰷􏰸 vector operation

vec4 v;
vec4 vOldPos = vec4(1.2.3.4);
vec4 vOffset = vec4(1.2.3.4);
// Note: Next assume that all the variables involved in the operation are defined and assigned.
v = vOldPos + vOffset;
v = vNewPos;
v += vec4(10.10.10.10);
v = vOldPos * vOffset;
v *= 5;
Copy the code

D, 􏰴􏰜􏰷􏰸 vector element acquisition (component selection)

The individual components of a vector can be denoted by {x,y,z,w}, {r,g,b,a} or {s,t,p,q}. These different notations are used for vertex, color, texture coordinates. You should not mix these notations in your choice of ingredients. Where the p in {s,t,p,q} replaces the r-coordinate of the texture because it is duplicated with the color R. Here are some examples of usage: for example, there are vectors v1 and v2:

vec3 v1 = {0.5.0.35.0.7};
vec4 v2 = {0.1.0.2.0.3.0.4};
Copy the code

By {x, y, z, w}, {r, g, b, b} or {s, t, p, q} to remove the element values in the vector. Through the x, y, z, w:

v2.x = 3.0f;
v2.xy = vec2(3.0f,4.0f);
v2.xyz = vec3(3.0f,4.0f,5.0f);
Copy the code

Through the r, g, b, a:

v2.r = 3.0f;
v2.rgba = vec4(1.0f,1.0f,1.0f,1.0f);
Copy the code

Through the s, t, q, r:

v2.stqr = vec2(1.0f, 0.0f, 0.0f, 1.0f);
Copy the code

Examples of errors:

float myQ = v1.q;// Error, array access out of bounds, q represents the fourth element
float myRY = v1.ry; // invalid
Copy the code

Vectors also support operating on all components at once

v1.x = v2.x +5.0f; 
v1.y = v2.y +4.0f; 
v1.z = v2.z +3.0f;
v1.xyz = v2.xyz + vec3(5.0f,4.0f,3.0f);
Copy the code

(2) Matrix type

type describe
Mat2 or mat2x2 Floating-point matrix type for 2×2
Mat3 or mat3x3 3×3 floating point matrix type
Mat4 or mat4x4 4×4 floating point matrix type
mat2x3 2 column 3 row floating point matrix (OpenGL matrix is column primary order)
mat2x4 Floating point matrix with 2 columns and 4 rows
mat3x2 Floating point matrix with 3 columns and 2 rows
mat3x4 Floating point matrix with 3 columns and 4 rows
mat4x2 Floating point matrix with 4 columns and 2 rows
mat4x3 Floating point matrix with 4 columns and 3 rows

Create matrix:

mat4 m1,m2,m3;
Copy the code

Construct element matrix:

mat4 m2 = mat4(1.0f,0.0f,0.0f,0.0f
                    0.0f,1.0f,0.0f,0.0f,
                    0.0f,0.0f,1.0f,0.0f,
                    0.0f,0.0f,0.0f,1.0f);
Copy the code

or

mat4 m4 = mat4(1.0f);
Copy the code

4, arrays,

Only one dimensional arrays can be used in GLSL. The type of an array can be any primitive type or structure. The following array declarations are legal:

float floatArray[4];
vec4 vecArray[2];
float a[4] = float[] (1.0.2.0.3.0.4.0);
vec2 c[2] = vec2[2] (vec2(1.0.2.0),vec2(3.0.4.0));
Copy the code

The array type has a built-in length() function that returns the length of the array.

lightPositions.length(a)// Return the length of the array
Copy the code

5. Structure

Structs can combine primitive types and arrays to form user-defined types. While defining a structure, you can define an instance of a structure. Or we can define it later.

struct fogStruct {
 vec4 color;
 float start;
 float end;
 vec3 points[3]; // Arrays of fixed size are legal
} fogVar;
Copy the code

Structs can be assigned by =, or by using ==,! = to determine whether the two structures are equal.

fogVar = fogStruct(vec4(1.0.0.0.0.0.1.0),0.5.2.0);
vec4 color = fogVar.color;
float start = fogVar.start;
Copy the code

3. Modifiers

1. Variable store qualifiers

qualifiers describe
(omitted by default) is a normal local variable, readable and writable, invisible and inaccessible to the outside world
const A constant value must be initialized at declaration time. It is read-only and cannot be modified
varying The output of the vertex shader is mainly responsible invertexfragmentPass variables between. Such as color or texture coordinates, as read-only input to the fragment shader. Must be a global variable declared by the global scope. It can be scalar, vector, matrix of floating-point type. Can’t be an array or structure.
uniform Consistent variable. The value of a consistent variable is constant during shader execution. withconstConstants differ in that this value is unknown at compile time and is initialized externally by the shader. Consistent variables are shared between vertex shaders and fragment shaders. It can only be declared globally.
attribute Represents read-only vertex data, used only in vertex shaders. The data comes from the current vertex state or vertex array. It must be declared globally, not inside a function. aattributeIt can be a scalar, vector, or matrix of floating-point type. Cannot be an array or structure
centorid varying In the absence of multiple sampling, andvaryingIt means the same thing. In the case of multiple sampling,centorid varyingEvaluate inside the rasterized graph rather than at a fixed location in the center of the fragment.
invariant (invariant) used to represent the output of the vertex shader and the input of any matching fragment shader. The values computed in different shaders must be consistent. All data flow and control flow, write oneinvariantThe variables are consistent. To ensure that the results are completely consistent, the compiler needs to discard potential optimizations that might lead to inconsistent values. Do not use this modifier unless necessary. Avoid in multi-pass renderingz-fightingIt might be used.

2. Function parameter qualifiers

GLSL allows custom functions, but arguments are passed in as values by default (the in qualifier), meaning that any variable is copied as it is passed in. If you want to pass parameters by reference, you need to add the function parameter qualifier.

qualifiers describe
in Used in a function parameter to indicate that the parameter is input. Changing the value in a function can have no adverse effects on the called function. This is the default modifier for function arguments
out Used in arguments to a function to indicate that the parameter is an output parameter whose value will change.
inout Parameter used in a function to indicate that the parameter is either an input parameter or an output parameter.

Parameters passed in Inout are similar to those passed by reference in other OOP languages. Parameters are read and written, and changes made to parameters within a function affect the parameters themselves. Eg:

vec4 getPosition(out vec4 p){ 
    p = vec4(0..0..0..1.);
    return v4;
}

void doubleSize(inout float size){
    size= size * 3.0  ;
}
Copy the code

3. Operation in GLSL

⚠️ Note that there are no implicit conversions in GLSL, even in multidimensional vectors, and assignments such as the following are incorrect:

/ / ⚠ ️ errors
int a = 2.0;
vec4 v4=vec4(1.0.1.0.2.1.0);
Copy the code

Float (int); float (int);

Float to int requires a display conversion, and the following expressions are correct:

int a = int(2.0);
float a = float(2);

int a = int(2.0) *2 + 1;
float a = float(2) *6.0+2.3;
Copy the code

2, float and vec(vector), mat(matrix) operation:

  • Component-by-component operations Vec, mat these types are composition of float, and when they operate with float, they operate separately with float on each component. This is called component-by-component operations. In GLSL, most operations involving VEC and MAT are component-by-component operations, but not all of them are. Exceptions are covered below. Component by component operations are linear, which means that veC and float are veC.

Int is unoperable with vec and mat, because each component in vec and mat is of type float and cannot be evaluated component by component with int.

Float: vec, mat: vec, mat: vec, mat

vec3 a  = vec3(1.0.2.0.3.0);
mat3 m  = mat3(1.0);
float s = 10.0;

vec3 b  = s * a; / / vec3 (10.0, 20.0, 30.0)
vec3 c  = a * s; / / vec3 (10.0, 20.0, 30.0)
mat3 m2 = s * m; / / = mat3 (10.0)
mat3 m3 = m * s; / / = mat3 (10.0)
Copy the code

3. Vec (vector) and VEC (vector) operations:

The operation between two vectors must first ensure that the order of the operands are the same, otherwise it cannot be calculated. For example: VEC3 * VEC2, VEC4 + VEC3, etc.

They are evaluated by the components of the two operands at the same position, and are essentially component-by-component. This may differ a little from the above, but vec and veC remain the same.

vec3 a = vec3(1.0.2.0.3.0);
vec3 b = vec3(0.1.0.2.0.3);
vec3 c = a + b; // = vec3(1.1, 2.2, 3.3);
vec3 d = a * b; // = vec3(0.1, 0.4, 0.9);
Copy the code

4. Vec (vector) and MAT (matrix):

The order of operands should be the same, and only multiplication operation exists between VEc and MAT. They are computed in the same way as matrix multiplication in linear algebra, not component by component.

vec2 v = vec2(10..20.);
mat2 m = mat2(1..2..3..4.);
vec2 w = m * v; // = vec2(1. * 10. + 3. * 20., 2. * 10. + 4. * 20.)

vec2 v = vec2(10..20.);
mat2 m = mat2(1..2..3..4.);
vec2 w = v * m; // = vec2(1. * 10. + 2. * 20., 3. * 10. + 4. * 20.)
Copy the code

5. Mat (matrix) and MAT (matrix):

⚠️ Ensure that the operands have the same order.

Among the operations of MAT and MAT, except that the multiplication is matrix multiplication in linear algebra, the other operations are still component-by-component operations. In short, only multiplication is special, and the rest are similar to VEC and VEC operations.

mat2 a = mat2(1..2..3..4.);
mat2 b = mat2(10..20..30..40.);
mat2 c = a * b; // mat2(1.*10.+3.*20.,2.*10.+4.*20.,1.* 30.+3.*40.,2.* 30.+4.*40.);

mat2 d = a+b;// mat2(1.+10.,2.+20.,3.+30.,4.+40);
Copy the code

4. Type conversion

GLSL can be explicitly converted via constructors as follows:

bool t= true;
bool f = false;

int a = int(t); // true converts to 1 or 1.0
int a1 = int(f);// false converts to 0 or 0.0

float b = float(t);
float b1 = float(f);

bool c = bool(0);// 0 or 0.0 is converted to false
bool c1 = bool(1);// Non-0 converts to true

bool d = bool(0.0);
bool d1 = bool(1.0);
Copy the code

Five, precision limitation

GLSL will generate a large number of floating point operations when rasterizing and coloring, which may not be able to withstand the current device, so GLSL provides three floating point precision, we can use the appropriate precision for different devices. Highp, mediump, lowp;

lowp float color;
varying mediump vec2 Coord;
lowp ivec2 foo(lowp mat3);
highp mat4 m;
Copy the code

We add the Precision Mediump float at the beginning of the fragment shader; The default precision is set so that all variables that do not have an explicit precision are treated with the default precision set.

Control statements

GLSL is syntactically very similar to C, with if else, for, while, do while, continue to jump into the next loop, and break to end the loop.

for (l = 0; l < numLights; l++) {
    if(! lightExists[l]);continue;
    color += light[l];
}

while (i < num) {
    sum += color[i];
    i++;
}

do {
    color += light[lightNum];
    lightNum--;
} while (lightNum > 0)
Copy the code

In addition to this, GLSL also adds a special control statement called discard, which immediately jumps out of the fragment shader without any statement down. No subsequent fragment coloring is performed and the fragment is not written to the frame buffer.

if (true)
    discard;
Copy the code

⚠️ Note that there is no recursion in the GLSL function!

The above summary refers to and partly extracts the following articles, thanks very much to the following authors for sharing! :

1, the author eats the code rabbit nest “primary GLSL shader (A)”

3, the author eats the code rabbit nest “primary GLSL shader (2)”

4. GLSL language basics by jeffasd

Reprint please note the original source, shall not be used for commercial communication – any more