๐Ÿ“š preface

GLSL ES programming language is based on OpenGL shader language (GLSL), after deleting and simplifying some functions formed. When you look at the ES version, you will probably think of GLSL ES on mobile phones, game consoles and other devices, which can reduce the power consumption of the hardware, but also reduce the performance overhead.

After all this talk about WebGL, it’s time to mention Khronos:

Khronos is an industry association focused on specifying open standards, focusing on specifying free apis that enable hardware acceleration for multimedia created or played on a variety of platforms and devices. The well-known OpenGL, OpenGL ES, WebGL are designated by the organization standards, see more visible website.

โŒจ ๏ธ grammar

๐Ÿงฉ basis

  1. GLSL ESIs case sensitive, for example:NiuniuandniuniuSo that corresponds to two different variables;
  2. For every statement;End, some friends writeJavaScriptWill get used to not adding at the end of the statementA semicolon, but inGLSL ESIn can pay attention to;
  3. Every shader program needs onemain()Function, just likeThe C languageLike, every shader program comes frommainStart to execute, butGLSL ESIn themain()Function andNo arguments are acceptedAnd it has to bevoidType;
  4. Single-line comments are used//, and multi-line comments are/ * comment * /;
  5. GLSL ESTwo data value types are supported:
    1. Numeric types:GLSL ESThe value without a decimal point is considered as an integer, and the value with a decimal point is considered as a floating point.
    2. Boolean value type:trueandfalseNeedless to say.
// Here are two different variables
uniform mat4 u_ModelMatrix;
uniform mat4 u_modelMatrix;

The main() function accepts no arguments */
void main() {
  // Shader program code
  // ...
}
Copy the code

๐Ÿง™ came ๏ธ variables

  1. The rules for variable names are the same as in other languages: they can only be named bya-z,A-Z,0-9As well as_And the first character of the variable name cannot be a number;
  2. Not togl_,webgl_or_webglAt the beginning, these prefixes have beenOpenGL ESRetained.

GLSL ES keyword:

attribute bool break bvec2 bvec3 bvec4
const continue discard do else false
float for highp if in inout
Int invariant ivec2 ivec3 ivec4 lowp
mat2 mat3 mat4 meduimp out precision
return sampler2D samplerCube struct true uniform
varying vec2 vec3 vec4 void while

Reserved words for GLSL ES (for future versions of GLSL ES) :

asm cast class default double dvec2
dvec3 dvec4 enum extern external fixed
flat fvec2 fvec3 fvec4 goto half
hvec2 hvec3 hvec4 inline input interface
long namespace noinline output packed public
sampler1D sampler1DShadow sampler2DRect sampler2DRectShadow smpler2DShadow smpler3D
sampler3DRect short sizeof static superp switch
template this typedef union unsigned using
volatile

โ™ป๏ธ Basic types and type conversions

float fnumber = 1.1;	/ / floating point number
int inumber = 1;	/ / integer
bool blogic = true;	/ / the Boolean

// Cast
int fresult = int(fnumber);	// Remove the decimal part, for example: 3.14 to 3
bool bresult = int(blogic);	// Convert true to 1 and false to 0

int iresult = float(inumber);	// Convert an integer to a floating point number, for example, 3 to 3.0
bresult = float(blogic);	// Convert Boolean to float, true to 1.0, false to 0.0

iresult = bool(inumber);	// Convert integers to Booleans, 0 to false, and other non-0 numbers to true
fresult = bool(fnumber);	// Convert integers to Booleans, 0.0 to false, and all non-0.0 numbers to true
Copy the code

๐Ÿ”ด Vectors and matrices

Vector and matrix types:

category GLSL ESThe data type describe
vector vec2/vec3/vec4 A vector with 2, 3, or 4 floating point elements
ivec2/ivec3/ivec4 A vector with 2, 3, or 4 integer elements
bvec2/bvec3/bvec4 A vector with 2, 3, or 4 elements of Boolean type
matrix mat2/mat3/mat4 2×2, 3×3, 4×4 float element matrix

Vector constructor

vec3 v3 = vec3(1.0.0.0.0.5);	// Set vector v3 to (1.0, 0.0, 0.5)
vec2 v2 = vec2(v3);	// Set v2 to (1.0, 0.0) using the first two values of v3
vec4 v4 = vec4(1.0);	// Set v4 to (1.0, 1.0, 1.0, 1.0)

// You can also combine multiple vectors into a single vector, for example:
vec4 v4_2 = vec4(v2, v4);	// Set v4_2 to (1.0, 0.0, 1.0, 1.0), and continue filling with elements from the second parameter v4 if v2 is not filled
Copy the code

Matrix constructor

Methods a

The matrix constructor is used in much the same way as the vector constructor, but make sure that the elements stored in the matrix are in main column order!

mat4 m4 = mat4(1.0.2.0.3.0.4.0.5.0.6.0.7.0.8.0.9.0.10.0.11.0.12.0.13.0.14.0.15.0.16.0);
Copy the code

The 4 x 4 matrix constructed above actually corresponds to:

Way 2

You can also pass one or more vectors into the matrix constructor to construct the matrix using the elements of the vectors in the main order of columns:

vec2 v2_1 = vec2(1.0.3.0);
vec2 v2_2 = vec2(2.0.4.0);
mat2 m2_1 = mat2(v2_1, v2_2);
/ / 1.0 2.0 โ”Œ โ”
/ / 3.0 4.0 โ”” โ”˜

vec4 v4 = vec4(1.0.3.0.2.0.4.0);
mat2 m2_2 = mat2(v4);
/ / 1.0 2.0 โ”Œ โ”
/ / 3.0 4.0 โ”” โ”˜
Copy the code
Methods three

It is also possible to construct a matrix using a combination of floating-point numbers and vectors:

vec2 v2 = vec2(2.0.4.0);
mat2 m2 = mat2(1.0.3.0, v2);
/ / 1.0 2.0 โ”Œ โ”
/ / 3.0 4.0 โ”” โ”˜
Copy the code
Methods four

If you want to construct the identity matrix, there is a simpler way:

mat3 m3 = mat3(1.0);
/ / โ”Œ โ” 1.0 0.0 0.0
/ / | | 0.0 1.0 0.0
/ / โ”” 0.0 0.0 1.0 โ”˜
Copy the code

Access the elements of vectors and matrices

Access vector elements

Since vectors can store vertex coordinates, color, and texture coordinates, GLSL ES has the concept of component names for readability:

category describe
x/y/z/w To get the vertex coordinate components
r/g/b/a To get the color component
s/t/p/q Gets the texture coordinate component

It can be obtained directly by:

vec4 v4 = vec4(1.0.1.0.1.0.0.0);

// v4.x;
// v4.y;
// v4.r;
Copy the code

In fact, x, r, or s of any vector returns the first component, and likewise y/g/t returns the second component. We can also assign values to other vectors by:

vec4 v4 = vec4(0.0.1.0.1.0.0.5);

vec2 v2 = v4.xy;
vec3 v3 = v4.yzw;
Copy the code

In the above code, multiple component names of the same set can be extracted from the vector simultaneously by placing them together in the dot operator, a process also known as mixing. Of course, the aggregate component name can also be used as an lvalue in an assignment expression:

vec4 position;
position.xw = vec2(1.0.2.0);
Copy the code
Accessing matrix elements
mat4 m4 = mat4(1.0.2.0.3.0.4.0.5.0.6.0.7.0.8.0.9.0.10.0.11.0.12.0.13.0.14.0.15.0.16.0);
Copy the code

We can access the elements in the matrix just like we can access the two-dimensional array in JS: m4[0][0], which obtains the first element 1.0 in M4. As mentioned in the previous introduction, we can use vectors to create the matrix, of course, we can also obtain the vectors in the matrix:

vec4 v4 = m4[0];	// (1.0, 2.0, 3.0, 4.0)
Copy the code

We can also use the dot operator to get the component value:

float m1_2 = m4[0].x;	// Set m1_2 to the first element in the first column of M4
m1_2 = m4[0] [1];	// Set m1_2 to the second element in the first column of M4
Copy the code

operation

Vector operation
vec2 v2_1 = (1.0.2.0);
vec2 v2_2 = (0.1.0.2);
float f = 0.5;

/ / add
v2_1 = v2_1 + v2_2;	/ / (1.1, 2.2) - (v2_1. X + v2_2. X, v2_1. Y + v2_2. Y)
v2_1 = v2_1 + f;	X + f, y + f, y + f)
Copy the code
Matrix operations
mat2 m2_1, m2_2;
vec2 v2;
float f;

/ / add
m2_1 + f; // m2_1[0].x + f; m2_1[0].y + f; m2_1[1].x + f; m2_1[1].y + f;

// The matrix is right multiplied by the vector
vec2 v2_result = m2_1 * v2;	// v2_result.x = m2_1[0].x * v2.x + m2_1[1].x * v2.y;
				// v2_result.y = m2_1[0].y * v2.x + m2_1[1].y * v2.y;

// Multiply the matrix left by the vector
v2_result = v2 * m2_1;	// v2_result.x = v2.x * m2_1[0].x + v2.y * m2_1[0].y;
			// v2_result.y = v2.x * m2_1[1].x + v2.y * m2_1[1].y;

// Matrix multiplication
mat2 m2_result = m2_1 * m2_2;	// m2_result[0].x = m2_1[0].x * m2_2[0].x + m2_1[1].x * m2_2[0].y;
				// m2_result[1].x = m2_1[0].x * m2_2[1].x + m2_1[1].x * m2_2[1].y;
				// m2_result[0].y = m2_1[0].y * m2_2[0].x + m2_1[1].y * m2_2[0].y;
				// m2_result[1].y = m2_1[0].y * m2_2[1].x + m2_1[1].y * m2_2[1].y;
Copy the code

๐Ÿ— structure

In GLSL ES, you can define structures using the struct keyword:

// Define the structure
struct light {
  vec4 color;
  vec3 position;
}

// Declare a variable of type light
light light_1;

// You can also use this method to define and declare a variable of type struct
struct light {
  vec4 color;
  vec3 position;
} light_1;
Copy the code

A structure has a standard constructor whose name is the same as the name of the structure. The order of the constructor arguments must be the same as the order of the members in the struct definition: light_1 = light(vec4(0.0, 1.0, 1.0, 0.5), vec3(1.0, 0.5, 0.0)); . And members can be accessed via the dot operator: vec4 color = light_1.color; .

๐Ÿงช sampler

GLSL ES has a built-in type called a sampler. We must access textures through variables of this type, and the sampler variables can only be uniform. There are two basic types of samplers: sampler2D and samplerCube, such as:

uniform sampler2D u_Sampler;
Copy the code

Also, the only thing that can be assigned to the sampler variable is the texture unit number, which must be assigned using the gl.Uniform1i () method provided by WebGL. For example, gl.Uniform1i (u_Sampler, 0) was used to pass the texture unit number 0 to the shader in the previous article.

๐Ÿ”š conclusion

This is a summary of the basic variable types and basic syntax of GLSL ES. There is no explanation of flow control, conditional statement and so on. It is consistent with the use of for/if else. Discard is added to the for loop in addition to break and continue. Discard can only be used in the fragment shader to discard processing of the current fragment.

GLSL ES grammar foundation introduced here, welcome to pay attention to the public number: Refactor, the following will be more fun and useful articles to share with you, thank you for reading ๐Ÿ”š