导语
颜色缓冲区
图形装配
// 顶点着色器
const VSHADER_SOURCE =
`attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
}`;
// 片段着色器
const FSHADER_SOURCE =
`void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}`;
光栅化
// 顶点着色器
const VSHADER_SOURCE =
`attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}`;
// 片段着色器
const FSHADER_SOURCE =
`varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}`;
纹理贴图
-
加载好需要的纹理图像
-
设置纹理坐标
-
对纹理进行配置
-
片段着色器抽出纹素并赋值给片元
function main() {
const canvas = document.getElementById('webgl');
const webgl = getWebGLContext(canvas);
webgl.images = {};
// 初始化之前先加载图片
loadImage([
`src/images/0.jpeg`,
], webgl).then((gl) => {
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const n = initVertexBuffers(gl);
initTextures(gl, n, 0);
});
}
function initVertexBuffers(gl) {
// 顶点坐标和纹理图像坐标
const vertices = new Float32Array([
-0.3, 0.7, 0.0, 0.0, 1.0,
-0.3, -0.7, 0.0, 0.0, 0.0,
0.3, 0.7, 0.0, 1.0, 1.0,
0.3, -0.7, 0.0, 1.0, 0.0,
]);
const FSIZE = vertices.BYTES_PER_ELEMENT;
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
const a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 5, FSIZE * 3);
gl.enableVertexAttribArray(a_TexCoord);
return 4;
}
function initTextures(gl, n, index) {
// 创建纹理对象
const texture = gl.createTexture();
const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
const image = gl.images[index];
// WebGL纹理坐标中的纵轴方向和PNG,JPG等图片容器的Y轴方向是反的,所以先反转Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 激活纹理单元,开启index号纹理单元
gl.activeTexture(gl[`TEXTURE${index}`]);
// 绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);
// 配置纹理对象的参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 将纹理图像分配给纹理对象
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
// 将纹理单元编号传给着色器
gl.uniform1i(u_Sampler, index);
// 绘制
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}
-
伸展(gl.TEXTURE_MAX_FILTER): 绘制图形比纹理图像大的时候怎么取纹素,默认值gl.LINEAR
-
收缩(gl.TEXTURE_MIN_FILTER): 绘制图形比纹理图像小的时候怎么取纹素, 默认值gl.NEAREST_MIP_LINEAR
-
水平填充(gl.TEXTURE_WRAP_S): 定义绘制图形水平方向如何填充,默认值gl.REPEAT
-
垂直填充(gl.TEXTURE_WRAP_T): 定义绘制图形垂直方向如何填充,默认值gl.REPEAT
const VSHADER_SOURCE =
`attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
gl_Position = a_Position;
v_TexCoord = a_TexCoord;
}`;
const FSHADER_SOURCE =
`precision mediump float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main() {
gl_FragColor = texture2D(u_Sampler, v_TexCoord);
}`;
多纹理实现
本文由云+社区发表,作者:ivweb qcyhust