webgl学习笔记五-纹理

时间:2023-03-09 15:57:43
webgl学习笔记五-纹理

写在前面

建议先阅读下前面我的三篇文章。

webgl学习笔记一-绘图单点

webgl学习笔记二-绘图多点

webgl学习笔记三-平移旋转缩放

术语 :

  • 纹理 :图像
  • 图形装配区域 :顶点着色器顶点坐标信息
  • 装配图形 : 片元着色器装配
  • 光栅化 :显示在屏幕上的三角形是由片元(像素)组成的,所以还需要将图形转化为片元,这个过程被称为光栅化。
  • 纹理图像:映射的这个图像称为纹理图像
  • 纹素 : 组成纹理图像的像素称为纹素
  • 纹理坐标 : 是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色;

纹理绘图流程

  重点介绍纹理的流程。

  • 创建纹理对象
  • 加载纹理图像
  • 配置属性

demo

  • html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <canvas id="canvas" width="200px" height="200px"></canvas> </body>
</html>
  • JavaScript
<script>

    window.onload = function () {

        //顶点着色器程序
var VSHADER_SOURCE =
"attribute vec4 a_Position;" +
"attribute vec2 a_TextCoord;" + // 接受纹理坐标
"varying vec2 v_TexCoord;" + // 传递纹理坐标
"void main() {" +
//设置坐标
"gl_Position = a_Position; " + // 设置坐标
//设置纹素
"v_TexCoord = a_TextCoord; " + // 设置纹理坐标
"} "; //片元着色器
var FSHADER_SOURCE =
"precision mediump float;" + //需要声明浮点数精度,否则报错No precision specified for (float)
"uniform sampler2D u_Sampler;" + // 取样器
"varying vec2 v_TexCoord;" + // 接受纹理坐标
"void main() {" +
//设置颜色
"gl_FragColor = texture2D(u_Sampler, v_TexCoord);" + // 设置颜色
"}"; //获取canvas元素
var canvas = document.getElementById('canvas');
//获取绘制webgl绘图上下文
var gl = canvas.getContext('webgl');
if (!gl) {
console.log("Failed");
return;
}
//编译着色器
// (1)创建Shader(着色器)对象
// (2)将着色器程序附加到Shader上
// (3)编译程序
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, VSHADER_SOURCE);
gl.compileShader(vertShader); var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, FSHADER_SOURCE);
gl.compileShader(fragShader);
//合并程序
// (1)创建一个程序对象
// (2)附加着色器
// (3)链接着色器
// (4)使用程序
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram); gl.clearColor(0.0, 0.0, 0.0, 1.0); var n = initBuffers(gl, shaderProgram);
initTexture(gl, shaderProgram, n); gl.clear(gl.COLOR_BUFFER_BIT); //绘制一个点
gl.drawArrays(gl.POINTS, 0, 1);
} // 使用缓冲区对象向顶点传入多个顶点数据
function initBuffers(gl, shaderProgram) {
//顶点坐标和颜色
var vertices = 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;//点的个数
//创建缓冲区对象
var vertexBuffer = gl.createBuffer(); //将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
//向缓冲区写入数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var FSIZE = vertices.BYTES_PER_ELEMENT; //获取坐标点
var a_Position = gl.getAttribLocation(shaderProgram, "a_Position");
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
//连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position); //获取Color坐标点
var a_TextCoord = gl.getAttribLocation(shaderProgram, "a_TextCoord");
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_TextCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
//连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_TextCoord);
return n;
} // 初始创建纹理,创建image对象
function initTexture(gl, shaderProgram, n) {
//创建纹理对象
var texture = gl.createTexture();
//获取u_Sampler的存储位置
var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler'); //创建image对象
var image = new Image(); //加载纹理
image.onload = function () {
loadTexture(gl, n, texture, u_Sampler, image);
};
// 浏览器开始加载图片 注意:一定是2^mx2^n尺寸的图片
image.src = "../../resources/st2_256*128.png";
return true; } // 加载纹理图像,配置属性
function loadTexture(gl, n, texture, u_Sampler, image) { //1.对纹理图像进行Y轴反转
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
//2.开启0号纹理单元
gl.activeTexture(gl.TEXTURE0);
//3.向target绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture); //4.配置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
//5.配置纹理图像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); //6.将0号纹理图像传递给着色器
gl.uniform1i(u_Sampler, 0);
// 清空 <canvas>
gl.clear(gl.COLOR_BUFFER_BIT); //绘制矩形
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); } </script>