本文介绍vue与WebGL结合给四边形添加纹理,文中部分代码及图片源自《WebGL编程指南》。
代码如下:
<template>
<div>
<canvas ref="myglCanvas" width="400" height="400"></canvas>
</div>
</template>
<script>
import Tools from "../lib/tools";
export default {
name: "glCanvas",
data() {
return {
VSHEADER_SOURCE: `attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main(){
gl_Position = a_Position;
v_TexCoord = a_TexCoord;
}`,
FSHEADER_SOURCE: `precision mediump float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main(){
gl_FragColor = texture2D(u_Sampler, v_TexCoord);;
}`,
gl: null
};
},
methods: {
setBuffer: function(gl) {
//第一个点,前两个数字表示位置,第三个数字表示大小,接下来三个数字表示颜色
let verticesTexCoords = new Float32Array([
// Vertex coordinates, texture coordinate
-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 n = 4; // The number of vertices
const fSize = verticesTexCoords.BYTES_PER_ELEMENT; //每个元素占的大小
// 创建缓冲区
let vertexTexCoordBuffer = gl.createBuffer();
if (!vertexTexCoordBuffer) {
console.log("Failed to create the buffer object");
return -1;
}
// 绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
// 将数据写入缓冲区
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
this.initBuffer(gl, "a_Position", 2, fSize * 4, 0);
this.initBuffer(gl, "a_TexCoord", 2, fSize * 4, fSize * 2);
// Set texture
if (!this.initTextures(gl, n)) {
console.log("Failed to intialize the texture.");
return;
}
// Unbind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, null);
return n;
},
/**
* 初始化缓冲区
* paramStr 变量名
* count 对象个数
* stride 步长
* offset 偏移量
*/
initBuffer: function(gl, paramStr, count, stride, offset) {
let a_param = this.gl.getAttribLocation(gl.program, paramStr);
if (a_param < 0) {
console.log(paramStr + " failed");
return -1;
}
// 将缓冲区对象分配给attribute对象
gl.vertexAttribPointer(a_param, count, gl.FLOAT, false, stride, offset);
// 开启attribute对象
gl.enableVertexAttribArray(a_param);
},
initTextures: function(gl, n) {
var texture = gl.createTexture(); // Create a texture object
if (!texture) {
console.log("Failed to create the texture object");
return false;
}
// Get the storage location of u_Sampler
var u_Sampler = gl.getUniformLocation(gl.program, "u_Sampler");
if (!u_Sampler) {
console.log("Failed to get the storage location of u_Sampler");
return false;
}
var image = new Image(); // Create the image object
if (!image) {
console.log("Failed to create the image object");
return false;
}
// Register the event handler to be called on loading an image
image.onload = function() {
//this.loadTexture(gl, n, texture, u_Sampler, image);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Flip the image's y axis
// Enable texture unit0
gl.activeTexture(gl.TEXTURE0);
// Bind the texture object to the target
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the texture parameters
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// Set the texture image
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGB,
gl.RGB,
gl.UNSIGNED_BYTE,
image
);
// Set the texture unit 0 to the sampler
gl.uniform1i(u_Sampler, 0);
gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
};
// Tell the browser to load an image
image.src = "../static/img/sky.JPG";
return true;
},
setGL: function() {
this.gl = this.$refs.myglCanvas.getContext("webgl");
}
},
mounted() {
this.setGL();
Tools.initShaders(this.gl, this.VSHEADER_SOURCE, this.FSHEADER_SOURCE);
let pointCount = this.setBuffer(this.gl);
if (pointCount < 0) {
console.log("set points failed");
return;
}
//设置背景色
this.gl.clearColor(0.0, 0.0, 0.0, 1);
//设置缓冲区颜色
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
}
};
</script>
<style scoped>
</style>
14行 在顶点着色器中定义纹理坐标;
15行 用于纹理坐标传递到片元着色器;
20-25行 在片元着色器中抽取纹素颜色,赋给当前片元;
32-48行 定义顶点坐标及其对应的纹理的坐标,其对应关系如下图:
54行 绑定a_TexCoord数据到缓冲区;
104-130行 配置和加载纹理
运行效果
更多内容请扫码关注我的微信公众号,或者在微信里搜索公众号webgis学习,我会不定期更新自己的webgis方面的学习心得。