WebGL入门课程04-颜色与纹理
[TOC]
十三、WebGL颜色与纹理
- 将非坐标数据传入顶点着色器
- vertexAttrbPosition()的步进和偏移参数
- varying变量、绘制彩色三角形
- 在矩形表面贴上图像
- 使用多幅纹理
关键:创建多个缓冲区对象
- 创建缓冲区对象
- 将缓冲区绑定到target上
- 将顶点坐标信息写入缓冲区对象
- 将缓冲区对象分配给对应的attribute变量
- 开启attribute变量
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>将非顶点信息传入顶点</title>
<style>
#web12 {
width: 750px;
height: 500px;
}
</style>
<script src="matrix.js"></script>
<script src="lib.js"></script>
</head>
<body>
<canvas id="web12"></canvas>
<script>
let canvas = document.querySelector("#web12");
let gl = canvas.getContext('webgl');
let VERTEX_SHADER = '' +
'attribute vec4 a_pos;' +
'attribute float a_size;' +
'void main(){' +
'gl_Position=a_pos;' +
'gl_PointSize=a_size;' +
'}';
let FRAG_SHADER = '' +
'void main(){' +
'gl_FragColor=vec4(1.0,0.5,0.0,1.0);' +
'}';
let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
let dataVertices = new Float32Array([
-0.3, 0.0,
0.0, 0.3,
0.3, 0.0
]);
bufferInit(gl, dataVertices, "a_pos", program);
let dataSize = new Float32Array([
10.0, 20.0, 30.0
]);
let bufferSize = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferSize);
gl.bufferData(gl.ARRAY_BUFFER, dataSize, gl.STATIC_DRAW);
let a_size = gl.getAttribLocation(program, 'a_size');
gl.vertexAttribPointer(a_size, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_size);
gl.drawArrays(gl.POINTS, 0, 3);
</script>
</body>
</html>
十四、vertexAttriPointer()的步进和偏移参数
可以将顶点的坐标和大小数据按照某种方式交错组织:
十五、varying变量、绘制彩色三角形
varying变量的作用是从顶点着色器向片元着色器中传递数据。
怎么传?
顶点着色器与片元着色器中有类型和命名都相同的varying变量,顶点着色器赋给变量的值就会被自动传入片元着色器
顶点着色器:varying vec4 v_color;
片元着色器:varying vec4 v_color;
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>将非顶点信息传入顶点</title>
<style>
#web12 {
width: 750px;
height: 500px;
}
</style>
<script src="matrix.js"></script>
<script src="lib.js"></script>
</head>
<body>
<canvas id="web12"></canvas>
<script>
let canvas = document.querySelector("#web12");
let gl = canvas.getContext('webgl');
let VERTEX_SHADER = '' +
'attribute vec4 a_pos;' +
'attribute vec4 a_color;' +
'varying vec4 v_color;' +
'void main(){' +
'gl_Position=a_pos;' +
'v_color=a_color;' +
'gl_PointSize=20.0;' +
'}';
let FRAG_SHADER = '' +
'precision lowp float;' +
'varying vec4 v_color;' +
'void main(){' +
'gl_FragColor=v_color;' +
'}';
let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
let dataVertices = new Float32Array([
-0.3, -0.4, 1.0, 0.0, 0.0,
0.0, 0.3, 0.0, 1.0, 0.0,
0.3, -0.4, 0.0, 0.0, 1.0,
]);
let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, dataVertices, gl.STATIC_DRAW);
let a_pos = gl.getAttribLocation(program, "a_pos");
let a_color = gl.getAttribLocation(program, "a_color");
let FSIZE = dataVertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_pos);
gl.enableVertexAttribArray(a_color);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
十六、在矩形表面上贴上图像
纹理映射就是将一张图像映射到一个几何图形的便面上去。这张被贴的图称为纹理或者纹理图像。
组成纹理图像的像素又被称为纹素
遵循四步:
- 准备好纹理图像
- 为几何图形配置纹理映射方式
- 加载图像,配置以便于WebGL使用
- 在片元着色器中将相应的纹素抽出来,将其颜色赋给片元
纹理坐标在WebGL中是二维的,为了获取纹素的颜色
配置和加载纹理的步骤:
- 创建纹理对象
- 加载图片
- 图像y轴反转
- 激活纹理单元
- 绑定纹理对象
- 配置纹理参数
- 将纹理图像分配给纹理对象
- 将纹理单元传递给片元着色器
配置和加载纹理的关键函数:
createTextur()
Image.onload()
pixesStorei()
activeTexture()
binTexture()
texParameteri()
texImage2D()
uniform1i()
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>纹理</title>
<style>
#web12 {
width: 750px;
height: 500px;
}
</style>
<script src="lib.js"></script>
</head>
<body>
<canvas id="web12"></canvas>
<script>
//==========================第一部分==========================
let canvas = document.querySelector("#web12");
let gl = canvas.getContext('webgl');
let VERTEX_SHADER = `
attribute vec4 a_pos;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main(){
gl_Position=a_pos;
v_TexCoord=a_TexCoord;
}`;
//==========================第二部分==========================
//片元着色器
let FRAG_SHADER = `
precision lowp float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main(){
gl_FragColor=texture2D(u_Sampler,v_TexCoord);
}`;
let program = initShader(gl, VERTEX_SHADER, FRAG_SHADER);
//==========================第三部分==========================
//准备顶点信息以及纹理顶点信息
let dataVertices = 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
]);
let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, dataVertices, gl.STATIC_DRAW);
let a_pos = gl.getAttribLocation(program, "a_pos");
let a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
let FSIZE = dataVertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, FSIZE * 4, 0);
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_pos);
gl.enableVertexAttribArray(a_TexCoord);
//==========================第四部分==========================
//配置和加载纹理
initTextures(gl);
function initTextures(gl) {
let texture = gl.createTexture(); //创建纹理对象
let u_Sampler = gl.getUniformLocation(program, 'u_Sampler'); //获取位置
let image = new Image();
image.src = 'sky.jpg';//此处图片大小一定要为256*256,
image.onload = function () {
loadTexture(gl, texture, u_Sampler, image, 0);
};
return true;
}
//==========================第五部分==========================
//为WebGL配置纹理
function loadTexture(gl, texture, u_Sampler, image, texUnit) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);//对纹理图像进行Y轴翻转
gl.activeTexture(gl.TEXTURE0);//开启0号纹理单元
gl.bindTexture(gl.TEXTURE_2D, texture);//向target绑定纹理对象
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//配置纹理参数
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);//配置纹理图像
gl.uniform1i(u_Sampler, texUnit);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//由于异步加载,所以写在这里
}
</script>
</body>
</html>