前几次对图形图形内部多是 以纯色填充,但是现实中已经有许多好的图片了我们没必要一点点画,这一章就是将图片以纹理的形式加载到片元中,主要过程如下,首先是定义点的坐标的attribute变量用于在javascript中 赋值,接下来定义varying 的vec2的变量用于将纹理坐标从顶点着色器传给片元着色器 在片元着色器中定义取样器左右存储纹理图像和相关参数,接下来就是为各个变量赋值,赋值方法与前面一直,先是创建缓冲区,绑定矩阵,写入数据,获取变量存储地址,再就是写入缓冲区数据,最后激活变量,这样就为顶点坐标和纹理坐标赋值了,最后是对取样器赋值 取样器是uniform的 先创建纹理对象,获取取样器地址,获取图像对象,设置图像Y轴反转,因为无法对纹理对象直接操作所以指定纹理单员,激活单元,将纹理对象和纹理单元绑定,配置纹理参数,配置纹理图像,最后取样器赋值,然后画图形。
接下来是代码:
<!DOCTYPE html>
<html>
<head>
<title>TexturedQuad.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script src="js/cuon-matrix.js"></script>
<script src="js/cuon-utils.js"></script>
<script src="js/webgl-debug.js"></script>
<script src="js/webgl-utils.js"></script>
<script type="text/javascript">
var VSHADER_SOURCE=//定点着色器
'attribute vec4 a_Position;
'+//定义vec4的变量 并且声明该变量是attribute型的
'attribute float a_PointSize;
'+
'attribute vec2 a_TextCoord;
'+
'varying vec2 v_TextCoord;
'+
'void main(){
'+
'gl_Position=a_Position;
'+//将attribute的变量赋值给内部
'gl_PointSize=a_PointSize;
'+
'v_TextCoord=a_TextCoord;
'+//将数据传给片元着色器
'}
';
var FSHADER_SOURCE=//片元着色器
'precision mediump float;
' +
'uniform sampler2D u_Sampler;
'+
'varying vec2 v_TextCoord;
'+
'void main(){
'+
'gl_FragColor=texture2D(u_Sampler,v_TextCoord);
'+//
'}
';
function main(){
var canvas=document.getElementById("webgl");
var gl=getWebGLContext(canvas);
if(!gl){
console.log("gl load fail!");
return;
}
if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){//初始化着色器
console.log("fail init shader()!");
return ;
}
var n=initVertexBuffers(gl);//将顶点坐标和纹理坐标赋值
if(n<0){
console.log("failed to set the positions of the vertices");
return;
}
gl.clearColor(0.0, 0.0, 1.0, 1.0);
initTextures(gl,n);
}
function initVertexBuffers(gl){
var verticesTextCoords=new Float32Array([
-0.5,0.5,2,-0.3,1.7,
-0.5,-0.5,2,-0.3,-0.2,
0.5,0.5,2,1.7,1.7,
0.5,-0.5,2,1.7,-0.2,
]);//类型化数组
var n=4;//点的个数
var vertexTexcoordBuffer=gl.createBuffer();//在webGL中创建缓冲区
if(!vertexTexcoordBuffer){
console.log("failed to create the buffer object!");
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER,vertexTexcoordBuffer);//将缓冲区与ARRAY_BUFFER绑定就是指定了缓冲区的用途
gl.bufferData(gl.ARRAY_BUFFER,verticesTextCoords,gl.STATIC_DRAW);//往缓冲区写数据 STATIC_DRAW对缓冲区优化 将顶点坐标和纹理坐标放进缓冲区
var FSize=verticesTextCoords.BYTES_PER_ELEMENT;//数组中每个元素的字节大小
//alert(FSize);
//设置顶点坐标 从缓冲区取出坐标
var a_Position=gl.getAttribLocation(gl.program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,5*FSize,0);//将缓冲区的数据传入分配给attribute对象 2是定点的分量个数 3*FSize表示相邻两个顶点间相距的字节数也可以理解为每隔3*FSize字节取俩值 是这些 0表示它的其实 偏移量就是从哪开始的
gl.enableVertexAttribArray(a_Position);//开启attribute变量
//将纹理坐标分配给webgl
var a_TextCoord=gl.getAttribLocation(gl.program,'a_TextCoord');
gl.vertexAttribPointer(a_TextCoord,2,gl.FLOAT,false,5*FSize,3*FSize);
gl.enableVertexAttribArray(a_TextCoord);
//设置点的大小
var a_PointSize=gl.getAttribLocation(gl.program,'a_PointSize');
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,5*FSize,2*FSize);
gl.enableVertexAttribArray(a_PointSize);
return n;
}
function initTextures(gl,n){
//alert(n);
var texture=gl.createTexture();//创建纹理对象 用来管理纹理
if(!texture){
console.log("failed to texture");
return false;
}
//u_Sampler是用来存储纹理的
var u_Sampler=gl.getUniformLocation(gl.program,'u_Sampler');
if(!u_Sampler){
console.log("failed to u_Sampler");
return false;
}
//加载图片创建图片对象异步加载图片加载完后调用loadTexture函数 未完成前也继续执行下面的代码
var image=new Image();
image.onload=function(){
loadTexture(gl,n,texture,u_Sampler,image);//将纹理单元的图像以及参数传给取样器
};
image.src="image/sky.jpg";
return true;
}
function loadTexture(gl,n,texture,u_Sampler,image){
//alert(image.height);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);//对图像进行Y轴反转
gl.activeTexture(gl.TEXTURE0);//开启0号单元
//console.log(gl.activeTexture(gl.TEXTURE0));
gl.bindTexture(gl.TEXTURE_2D,texture);//将纹理对象绑定到纹理单元中 因为没法直接操作纹理对象但是可以操作纹理单元
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//配置纹理的参数
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);//在X轴上不足会自动填充
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.MIRRORED_REPEAT);//在y轴上不足的灰自动tian
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);//配置纹理图像
gl.uniform1i(u_Sampler,0);//将0单元的纹理传给纹理取样器
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP,0,n);
}
</script>
</head>
<body onload="main()">
<canvas id="webgl" width="600" height="400"></canvas>
</body>
</html>