目录
简介
着色器中变量声明: attribute、varing、uniform。设置attribute、uniform。预定义变量。const变量。
变量特点
1. Attribute 变量
用于接收顶点数据,只能在顶点着色器中声明和使用。
attribute vec3 a_position;
2. Uniform 变量
用于在 JavaScript 代码中设置并在着色器程序中保持不变的值,可以在顶点着色器和片元着色器中声明和使用。但是必现要保证变量名唯一,即顶点着色器和片元着色器的uniform变量不能相同。
uniform mat4 u_modelMatrix;
3. Varying 变量
用于在顶点着色器和片元着色器之间传递数据,顶点着色器中声明的 varying 变量的值会被插值后传递给片元着色器。
varying vec4 v_color;
4. Const 变量
在着色器中声明的常量值,在整个着色器程序中保持不变。
const float PI = 3.14159265359;
5. 预定义变量
WebGL 中内置了一些预定义的特殊变量,如 gl_Position(顶点着色器中)和 gl_FragColor(片元着色器中),它们分别用于设置顶点位置和片元颜色。
示例:
1. 顶点着色器示例
// 编译顶点着色器
var vertexShaderSource = `
attribute vec3 a_position;
attribute vec4 a_color;
attribute vec2 a_texcoord;
uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix;
uniform mat4 u_projectionMatrix;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * vec4(a_position, 1.0);
v_color = a_color;
v_texcoord = a_texcoord;
}
`;
2. 片元着色器示例:
// 编译片元着色器
var fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_FragColor = v_color;
}
`;
设置attribute示例
// 设置顶点属性
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
var colorAttributeLocation = gl.getAttribLocation(program, "a_color");
var texcoordAttributeLocation = gl.getAttribLocation(program, "a_texcoord");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.enableVertexAttribArray(texcoordAttributeLocation);
设置uniform示例
// 计算模型、视图和投影矩阵
var modelMatrix = mat4.create(); // 模型矩阵
var viewMatrix = mat4.create(); // 视图矩阵
var projectionMatrix = mat4.create(); // 投影矩阵
// 设置模型矩阵
mat4.translate(modelMatrix, modelMatrix, [0.0, 0.0, -5.0]);
// 设置视图矩阵
mat4.lookAt(viewMatrix, [0, 0, 5], [0, 0, 0], [0, 1, 0]);
// 设置投影矩阵
mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 0.1, 100);
// 将模型、视图和投影矩阵传递给顶点着色器
var modelMatrixUniformLocation = gl.getUniformLocation(program, "u_modelMatrix");
gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);
var viewMatrixUniformLocation = gl.getUniformLocation(program, "u_viewMatrix");
gl.uniformMatrix4fv(viewMatrixUniformLocation, false, viewMatrix);
var projectionMatrixUniformLocation = gl.getUniformLocation(program, "u_projectionMatrix");
gl.uniformMatrix4fv(projectionMatrixUniformLocation, false, projectionMatrix);
完整代码示例:
// 获取 WebGL 上下文
var canvas = document.getElementById("webgl-canvas");
var gl = canvas.getContext("webgl");
// 编译顶点着色器
var vertexShaderSource = `
attribute vec3 a_position;
attribute vec4 a_color;
attribute vec2 a_texcoord;
uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix;
uniform mat4 u_projectionMatrix;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * vec4(a_position, 1.0);
v_color = a_color;
v_texcoord = a_texcoord;
}
`;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
// 编译片元着色器
var fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
void main() {
gl_FragColor = v_color;
}
`;
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
// 创建着色器程序并链接
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 设置顶点属性
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
var colorAttributeLocation = gl.getAttribLocation(program, "a_color");
var texcoordAttributeLocation = gl.getAttribLocation(program, "a_texcoord");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.enableVertexAttribArray(texcoordAttributeLocation);
// 计算模型、视图和投影矩阵
var modelMatrix = mat4.create(); // 模型矩阵
var viewMatrix = mat4.create(); // 视图矩阵
var projectionMatrix = mat4.create(); // 投影矩阵
// 设置模型矩阵
mat4.translate(modelMatrix, modelMatrix, [0.0, 0.0, -5.0]);
// 设置视图矩阵
mat4.lookAt(viewMatrix, [0, 0, 5], [0, 0, 0], [0, 1, 0]);
// 设置投影矩阵
mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 0.1, 100);
// 将模型、视图和投影矩阵传递给顶点着色器
var modelMatrixUniformLocation = gl.getUniformLocation(program, "u_modelMatrix");
gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);
var viewMatrixUniformLocation = gl.getUniformLocation(program, "u_viewMatrix");
gl.uniformMatrix4fv(viewMatrixUniformLocation, false, viewMatrix);
var projectionMatrixUniformLocation = gl.getUniformLocation(program, "u_projectionMatrix");
gl.uniformMatrix4fv(projectionMatrixUniformLocation, false, projectionMatrix);
// 顶点数据
var vertices = [
-0.5, -0.5, 0.0, // 顶点位置
1.0, 0.0, 0.0, 1.0, // 顶点颜色,红色
0.0, 0.0, // 顶点纹理坐标
0.5, -0.5, 0.0,
0.0, 1.0, 0.0, 1.0, // 顶点颜色,绿色
1.0, 0.0,
0.0, 0.5, 0.0,
0.0, 0.0, 1.0, 1.0, // 顶点颜色,蓝色
0.5, 1.0
];
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// 将顶点位置属性绑定到缓冲区
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 8 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(colorAttributeLocation, 4, gl.FLOAT, false, 8 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribPointer(texcoordAttributeLocation, 2, gl.FLOAT, false, 8 * Float32Array.BYTES_PER_ELEMENT, 7 * Float32Array.BYTES_PER_ELEMENT)