5 创建多个缓冲区
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
/**
* 设置着色器
*/
function setShaders(gl) {
// 顶底着色气
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute float a_PointSize;\n' +
'void main() {\n' +
// vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
// w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
' gl_Position = a_Position;\n' + // 设置点的位置
' gl_PointSize = a_PointSize;\n' + // 设置点的大小
'}\n';
// 片元着色气
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform vec4 u_FragColor;\n' + // uniform变量
'void main() {\n' +
' gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
'}\n';
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
throw new TypeError("未能初始化着色器");
}
// gl.getUniformLocation 获取uniform变量的存储位置
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')
gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
}
function main() {
// 获取 <canvas> 元素
var canvas = document.getElementById('webgl');
// 获取 WebGL 绘图上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
var initVertexBuffers = function () {
// 1.创建缓冲区对象
var vertexBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
if (!vertexBuffer || !sizeBuffer) {
throw new TypeError("创建缓冲区失败");
}
var vertices = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
])
var sizes = new Float32Array([10.0, 20.0, 30.0])
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
throw new TypeError("无法获取变量的存储位置")
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
if (a_PointSize < 0) {
throw new TypeError("无法获取变量的存储位置")
}
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_PointSize);
return 3;
}
setShaders(gl);
var n = initVertexBuffers(gl);
// 设置背景颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
// gl.COLOR_BUFFER_BIT 颜色缓冲区
// 清空颜色缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
// gl.drawArrays(mode, first, count);
// mode 表示绘制的方式
// first 从那个顶点开始绘制
// count 绘制几个顶点
gl.drawArrays(gl.POINTS, 0, n);
}
main()
</script>
</body>
</html>
5.1vertexAttribPointer的进步和偏移参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
/**
* 设置着色器
*/
function setShaders(gl) {
// 顶底着色气
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute float a_PointSize;\n' +
'void main() {\n' +
// vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
// w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
' gl_Position = a_Position;\n' + // 设置点的位置
' gl_PointSize = a_PointSize;\n' + // 设置点的大小
'}\n';
// 片元着色气
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform vec4 u_FragColor;\n' + // uniform变量
'void main() {\n' +
' gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
'}\n';
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
throw new TypeError("未能初始化着色器");
}
// gl.getUniformLocation 获取uniform变量的存储位置
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')
gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
}
function main() {
// 获取 <canvas> 元素
var canvas = document.getElementById('webgl');
// 获取 WebGL 绘图上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
var initVertexBuffers = function () {
// 1.创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
throw new TypeError("创建缓冲区失败");
}
var vertices = new Float32Array([
0.0, 0.5, 10.0,
-0.5, -0.5, 20.0,
0.5, -0.5, 30.0
])
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
throw new TypeError("无法获取变量的存储位置")
}
var fsize = vertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 3, 0);
gl.enableVertexAttribArray(a_Position);
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
if (a_PointSize < 0) {
throw new TypeError("无法获取变量的存储位置")
}
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, fsize * 3, fsize * 2);
gl.enableVertexAttribArray(a_PointSize);
return 3;
}
setShaders(gl);
var n = initVertexBuffers(gl);
// 设置背景颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
// gl.COLOR_BUFFER_BIT 颜色缓冲区
// 清空颜色缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
// gl.drawArrays(mode, first, count);
// mode 表示绘制的方式
// first 从那个顶点开始绘制
// count 绘制几个顶点
gl.drawArrays(gl.POINTS, 0, n);
}
main()
</script>
</body>
</html>
5.2 修改颜色(varying变量)
一致的 (uniform变量)
可变的变量(varying变量)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
/**
* 设置着色器
*/
function setShaders(gl) {
// 顶底着色气
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute float a_PointSize;\n' +
'attribute vec4 a_Color;\n' +
'varying vec4 v_Color;\n' + // varying
'void main() {\n' +
' gl_Position = a_Position;\n' + // 设置点的位置
' gl_PointSize = a_PointSize;\n' +
' v_Color = a_Color;\n' + // 设置点的大小
'}\n';
// 片元着色气
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n' + // varying
'void main() {\n' +
' gl_FragColor = v_Color;\n' + // 设置颜色,rgba
'}\n';
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
throw new TypeError("未能初始化着色器");
}
// gl.getUniformLocation 获取uniform变量的存储位置
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')
gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
}
function main() {
// 获取 <canvas> 元素
var canvas = document.getElementById('webgl');
// 获取 WebGL 绘图上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
var initVertexBuffers = function () {
// 1.创建缓冲区对象
var vertexBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
if (!vertexBuffer) {
throw new TypeError("创建缓冲区失败");
}
var vertices = new Float32Array([
// 顶点坐标,大小,颜色
0.0, 0.5, 1.0, 0.0, 0.0,
-0.5, -0.5, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0,
])
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
throw new TypeError("无法获取变量的存储位置")
}
var fsize = vertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 5, 0);
gl.enableVertexAttribArray(a_Position);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
if (a_Color < 0) {
throw new TypeError("无法获取变量的存储位置")
}
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, fsize * 5, fsize * 2);
gl.enableVertexAttribArray(a_Color);
var sizes = new Float32Array([10.0, 20.0, 30.0])
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
if (a_PointSize < 0) {
throw new TypeError("无法获取变量的存储位置")
}
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_PointSize);
return 3;
}
setShaders(gl);
var n = initVertexBuffers(gl);
// 设置背景颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
// gl.COLOR_BUFFER_BIT 颜色缓冲区
// 清空颜色缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
// gl.drawArrays(mode, first, count);
// mode 表示绘制的方式
// first 从那个顶点开始绘制
// count 绘制几个顶点
// gl.drawArrays(gl.POINTS, 0, n);
gl.drawArrays(gl.TRIANGLES, 0, n); // 可以画出彩色三角形
}
main()
</script>
</body>
</html>
5.3 图形装配,光栅化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
// HelloTriangle_FragCoord.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform float u_Width;\n' +
'uniform float u_Height;\n' +
'void main() {\n' +
' gl_FragColor = vec4(gl_FragCoord.x/u_Width, 0.0, gl_FragCoord.y/u_Height, 1.0);\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Write the positions of vertices to a vertex shader
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the positions of the vertices');
return;
}
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the rectangle
gl.drawArrays(gl.TRIANGLES, 0, n);
}
function initVertexBuffers(gl) {
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3; // The number of vertices
// Create a buffer object
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// Write date into the buffer object
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// Pass the position of a point to a_Position variable
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
var u_Width = gl.getUniformLocation(gl.program, 'u_Width');
if (!u_Width) {
console.log('Failed to get the storage location of u_Width');
return;
}
var u_Height = gl.getUniformLocation(gl.program, 'u_Height');
if (!u_Height) {
console.log('Failed to get the storage location of u_Height');
return;
}
// Pass the width and hight of the <canvas>
gl.uniform1f(u_Width, gl.drawingBufferWidth);
gl.uniform1f(u_Height, gl.drawingBufferHeight);
// Enable the generic vertex attribute array
gl.enableVertexAttribArray(a_Position);
// Unbind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return n;
}
main();
</script>
</body>
</html>
5.3纹理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
// TexturedQuad.js (c) 2012 matsuda and kanda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' v_TexCoord = a_TexCoord;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型
// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型
'uniform sampler2D u_Sampler;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
// 纹理映射
// 使用GLSL ES内置函数texture2D来抽取纹素颜色。该函数返回
// gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA
' gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Set the vertex information
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the vertex information');
return;
}
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Set texture
if (!initTextures(gl, n)) {
console.log('Failed to intialize the texture.');
return;
}
}
function initVertexBuffers(gl) {
var verticesTexCoords = new Float32Array([
// 顶点坐标,纹理坐标
-0.5, 0.5, 0.0, 1.0,
-0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 1.0, 1.0,
0.5, -0.5, 1.0, 0.0,
]);
var n = 4;
// Create the buffer object
var vertexTexCoordBuffer = gl.createBuffer();
if (!vertexTexCoordBuffer) {
throw new TypeError("创建gl.Buffer失败")
}
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
//Get the storage location of a_Position, assign and enable buffer
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object
// Get the storage location of a_TexCoord
var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
if (a_TexCoord < 0) {
console.log('Failed to get the storage location of a_TexCoord');
return -1;
}
// Assign the buffer object to a_TexCoord variable
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer object
return n;
}
function initTextures(gl, n) {
// 创建纹理对象 gl.deleteTexture 删除纹理对象
var texture = gl.createTexture();
if (!texture) {
throw new TypeError("创建纹理对象失败");
}
// Get the storage location of u_Sampler
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
if (!u_Sampler) {
throw new TypeError("获取uniform变量失败");
}
var image = new Image(); // Create the image object
// 设置图片加载完成的事件
image.onload = function () { loadTexture(gl, n, texture, u_Sampler, image); };
// 加载图片
image.src = '../resources/sky.jpg';
return true;
}
function loadTexture(gl, n, texture, u_Sampler, image) {
// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,
// 需要对图像进行y轴反转,才能正确显示图片
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 开启0号纹理单元,激活纹理单元
// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元
// 在使用纹理单元前,需要激活
gl.activeTexture(gl.TEXTURE0);
// 绑定纹理对象
// gl.TEXTURE_2D 二维纹理
// gl.TEXTURE_CUBE_MAP 立方体纹理
gl.bindTexture(gl.TEXTURE_2D, texture);
// 配置纹理参数 gl.texParameteri(var1, var2, var3)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 纹理参数,下列值
// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR
// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR
// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET
// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET
// var3 = 纹理参数的值
// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量
// gl.LINEAR | gl.NEAREST
// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值
// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量
// gl.REPEAT 平铺式的重复纹理
// gl.MIRRORED_REPEAT 镜像对称式的重复纹理
// gl.CLAMP_TO_EDGE 使用纹理的边缘值
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 配置纹理图像
// gl.texImage2D(var1, var2, var3, var4, var5, var6)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及
// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA
// var4 = 纹理数据的格式,必须与var3的值一致
// var5 = 纹理的数据类型
// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节
// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特
// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特
// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特
// var6 = image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
// 将0号纹理传递给着色器中的取样器变量
// 也就是这个gl.TEXTURE0的编号传给u_Sampler
gl.uniform1i(u_Sampler, 0);
gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
}
main();
</script>
</body>
</html>
5.3.1 纹理texParameteri的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
// TexturedQuad.js (c) 2012 matsuda and kanda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' v_TexCoord = a_TexCoord;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型
// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型
'uniform sampler2D u_Sampler;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
// 纹理映射
// 使用GLSL ES内置函数texture2D来抽取纹素颜色。该函数返回
// gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA
' gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Set the vertex information
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the vertex information');
return;
}
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Set texture
if (!initTextures(gl, n)) {
console.log('Failed to intialize the texture.');
return;
}
}
function initVertexBuffers(gl) {
var verticesTexCoords = new Float32Array([
// 顶点坐标,纹理坐标
-0.5, 0.5, -0.3, 1.7,
-0.5, -0.5, -0.3, -0.2,
0.5, 0.5, 1.7, 1.7,
0.5, -0.5, 1.7, -0.2,
]);
var n = 4;
// Create the buffer object
var vertexTexCoordBuffer = gl.createBuffer();
if (!vertexTexCoordBuffer) {
throw new TypeError("创建gl.Buffer失败")
}
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
//Get the storage location of a_Position, assign and enable buffer
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object
// Get the storage location of a_TexCoord
var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
if (a_TexCoord < 0) {
console.log('Failed to get the storage location of a_TexCoord');
return -1;
}
// Assign the buffer object to a_TexCoord variable
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer object
return n;
}
function initTextures(gl, n) {
// 创建纹理对象 gl.deleteTexture 删除纹理对象
var texture = gl.createTexture();
if (!texture) {
throw new TypeError("创建纹理对象失败");
}
// Get the storage location of u_Sampler
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
if (!u_Sampler) {
throw new TypeError("获取uniform变量失败");
}
var image = new Image(); // Create the image object
// 设置图片加载完成的事件
image.onload = function () { loadTexture(gl, n, texture, u_Sampler, image); };
// 加载图片
image.src = '../resources/sky.jpg';
return true;
}
function loadTexture(gl, n, texture, u_Sampler, image) {
// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,
// 需要对图像进行y轴反转,才能正确显示图片
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 开启0号纹理单元,激活纹理单元
// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元
// 在使用纹理单元前,需要激活
gl.activeTexture(gl.TEXTURE0);
// 绑定纹理对象
// gl.TEXTURE_2D 二维纹理
// gl.TEXTURE_CUBE_MAP 立方体纹理
gl.bindTexture(gl.TEXTURE_2D, texture);
// 配置纹理参数 gl.texParameteri(var1, var2, var3)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 纹理参数,下列值
// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR
// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR
// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET
// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET
// var3 = 纹理参数的值
// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量
// gl.LINEAR | gl.NEAREST
// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值
// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量
// gl.REPEAT 平铺式的重复纹理
// gl.MIRRORED_REPEAT 镜像对称式的重复纹理
// gl.CLAMP_TO_EDGE 使用纹理的边缘值
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
// 配置纹理图像
// gl.texImage2D(var1, var2, var3, var4, var5, var6)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及
// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA
// var4 = 纹理数据的格式,必须与var3的值一致
// var5 = 纹理的数据类型
// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节
// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特
// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特
// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特
// var6 = image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
// 将0号纹理传递给着色器中的取样器变量
// 也就是这个gl.TEXTURE0的编号传给u_Sampler
gl.uniform1i(u_Sampler, 0);
gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
}
main();
</script>
</body>
</html>
5.3.2 使用多幅纹理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Clear canvas</title>
</head>
<body>
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas"
</canvas>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
// TexturedQuad.js (c) 2012 matsuda and kanda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec2 a_TexCoord;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' v_TexCoord = a_TexCoord;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
// sampler2D 绑定到gl.TEXTURE_2D上的纹理数据类型
// samplerCube 绑定到gl.TEXTURE_CUBE_MAP上的纹理数据类型
'uniform sampler2D u_Sampler0;\n' +
'uniform sampler2D u_Sampler1;\n' +
'varying vec2 v_TexCoord;\n' +
'void main() {\n' +
' vec4 color1 = texture2D(u_Sampler0, v_TexCoord);\n' +
' vec4 color0 = texture2D(u_Sampler1, v_TexCoord);\n' +
' gl_FragColor = color0 * color1;\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// Set the vertex information
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the vertex information');
return;
}
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Set texture
if (!initTextures(gl, n)) {
console.log('Failed to intialize the texture.');
return;
}
}
function initVertexBuffers(gl) {
var verticesTexCoords = new Float32Array([
// 顶点坐标,纹理坐标
-0.5, 0.5, 0.0, 1.0,
-0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 1.0, 1.0,
0.5, -0.5, 1.0, 0.0,
]);
var n = 4;
// Create the buffer object
var vertexTexCoordBuffer = gl.createBuffer();
if (!vertexTexCoordBuffer) {
throw new TypeError("创建gl.Buffer失败")
}
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
//Get the storage location of a_Position, assign and enable buffer
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object
// Get the storage location of a_TexCoord
var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
if (a_TexCoord < 0) {
console.log('Failed to get the storage location of a_TexCoord');
return -1;
}
// Assign the buffer object to a_TexCoord variable
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_TexCoord); // Enable the assignment of the buffer object
return n;
}
function initTextures(gl, n) {
// 创建纹理对象 gl.deleteTexture 删除纹理对象
var texture0 = gl.createTexture();
var texture1 = gl.createTexture();
if (!texture0 || !texture1) {
throw new TypeError("创建纹理对象失败");
}
// Get the storage location of u_Sampler
var u_Sampler0 = gl.getUniformLocation(gl.program, 'u_Sampler0');
var u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1');
if (!u_Sampler0 || !u_Sampler1) {
throw new TypeError("获取uniform变量失败");
}
var image0 = new Image();
var image1 = new Image();
// 设置图片加载完成的事件
image0.onload = function () { loadTexture(gl, n, texture0, u_Sampler0, image0, 0); };
image1.onload = function () { loadTexture(gl, n, texture1, u_Sampler1, image1, 1); };
// 加载图片
image0.src = '../resources/sky.jpg';
image1.src = '../resources/circle.gif';
return true;
}
var g_texUnit0 = false, g_texUnit1 = false;
function loadTexture(gl, n, texture, u_Sampler, image, texUnit) {
// 对纹理图像进行y轴反转,png,bmp,jpg等格式图片的坐标系统的Y轴方向是相反的,因此,
// 需要对图像进行y轴反转,才能正确显示图片
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 开启0号纹理单元,激活纹理单元
// gl.TEXTURE0 ~ gl.TEXTURE7 webgl至少支持8个纹理单元
// 在使用纹理单元前,需要激活
if (texUnit === 0) {
gl.activeTexture(gl.TEXTURE0);
g_texUnit0 = true;
} else {
gl.activeTexture(gl.TEXTURE1);
g_texUnit1 = true;
}
// 绑定纹理对象
// gl.TEXTURE_2D 二维纹理
// gl.TEXTURE_CUBE_MAP 立方体纹理
gl.bindTexture(gl.TEXTURE_2D, texture);
// 配置纹理参数 gl.texParameteri(var1, var2, var3)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 纹理参数,下列值
// gl.TEXTURE_MAG_FILTER 纹理放大 默认值 gl.LINEAR
// gl.TEXTURE_MIN_FILTER 纹理缩小 默认值 gl.NEAREST_MIPMAP_LINEAR
// gl.TEXTURE_WRAP_S 纹理水平填充 默认值 gl.REPAET
// gl.TEXTURE_WRAP_T 纹理垂直填充 默认值 gl.REPAET
// var3 = 纹理参数的值
// gl.TEXTURE_MAG_FILTER 和 gl.TEXTURE_MIN_FILTER 支持的常量
// gl.LINEAR | gl.NEAREST
// gl.LINEAR 比 gl.NEAREST质量更好,它使用距离新像素中心最近的四个像素的颜色值的加权平均,作为新像素的值
// gl.TEXTURE_WRAP_S 和 gl.TEXTURE_WRAP_T 支持的常量
// gl.REPEAT 平铺式的重复纹理
// gl.MIRRORED_REPEAT 镜像对称式的重复纹理
// gl.CLAMP_TO_EDGE 使用纹理的边缘值
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 配置纹理图像
// gl.texImage2D(var1, var2, var3, var4, var5, var6)
// var1 = gl.TEXTURE_2D 二维纹理 | gl.TEXTURE_CUBE_MAP 立方体纹理
// var2 = 传入0 ,实际上该参数是给金字塔纹理准备的,暂时不涉及
// var3 = 图片的内部格式,gl.RGB | gl.RGBA | gl.ALPHA | gl.LUMINANCE | gl.LUMINANCE_ALPHA
// var4 = 纹理数据的格式,必须与var3的值一致
// var5 = 纹理的数据类型
// gl.UNSIGNED_BYTE 无符号整型,每个符号占一个字节
// gl.UNSIGNED_SHORT_5_6_5 RGB: 每个分量分别占5、6、5比特
// gl.UNSIGNED_SHORT_4_4_4_4 RGBA: 每个分量分别占4、4、4、4比特
// gl.UNSIGNED_SHORT_5_5_5_1 RGBA: RGB每个分量分别占5比特,A分量占1比特
// var6 = image
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
// 将0号纹理传递给着色器中的取样器变量
// 也就是这个gl.TEXTURE0的编号传给u_Sampler
gl.uniform1i(u_Sampler, texUnit);
gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
if (g_texUnit0 && g_texUnit1) {
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
}
}
main();
</script>
</body>
</html>