HTML部分
<script type="text/javascript" src="gl-matrix.js"></script> <canvas id="myCanvas" width="400" height="400" style="border: 1px solid red"></canvas>
JavaScript部分
以下两点若不注意texture2D有可能取不到值,一片黑色。
老的显卡只支持图片尺寸为2的n次幂的纹理图片。
TEXTURE_MAG_FILTER和TEXTURE_MIN_FILTER参数需要制定。
const vertex = `
attribute vec3 v3Position;
uniform mat4 u_matrix;
attribute vec2 inUv;
varying vec2 outUv;
void main) {
gl_Position = u_matrix * vec4v3Position, 1.0);
outUv = inUv;
}
`;
// texture2Du_texture, vec2outUv.x, outUv.y));
// texture2Du_texture, outUv;
// 从纹理texture中根据outUv坐标取色素rgba
const fragment = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 outUv;
void main) {
gl_FragColor = texture2Du_texture, vec2outUv.x, outUv.y));
}
`;
let canvas = document.getElementById'myCanvas');
let webgl = canvas.getContext'webgl');
const data_position = new Float32Array[
// x y z u v
30, 30, 0, 0.0, 0.0,
330, 30, 0, 2.0, 0.0,
330, 330, 0, 2.0, 2.0,
30, 30, 0, 0.0, 0.0,
330, 330, 0, 2.0, 2.0,
30, 330, 0, 0.0, 2.0
]);
const data_mat4 = glMatrix.mat4.ortho[], 0, canvas.clientWidth, canvas.clientHeight, 0, -10, 10);
// 第一步:编译程序
let program = createProgramwebgl, vertex, fragment);
// 第二步:建立buffer
let buffer_position = bindBufferWidthDatawebgl, webgl.ARRAY_BUFFER, data_position); // 创建数据缓冲区
// 第三步:变量绑定
let v3Position = bindVertexAttributePointerwebgl, program, "v3Position", 3, 20, 0); // 绑定顶点输入变量v3Position的指针和取数方式
let inUv = bindVertexAttributePointerwebgl, program, "inUv", 2, 20, 12); // 绑定顶点输入变量inUv坐标的指针和取数方式
let matrix = setUniformMatrixwebgl, program, 'u_matrix', data_mat4); // 设置全局变量u_matrix的值
let img = new Image);
img.onload = ImageLoaded;
img.src = '/static/imgs/sky.png';
function ImageLoaded) {
var texture = webgl.createTexture);
webgl.activeTexturewebgl.TEXTURE1); // webgl有32个问题里图片,激活第二个纹理图片,一般使用第一个webgl.TEXTURE0
webgl.bindTexturewebgl.TEXTURE_2D, texture); // 设置webgl的TEXTURE1为TEXTURE_2D,实例为创建的texture变量
// 设置纹理图片的参数
webgl.texImage2Dwebgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, img);
// 图片的真实大小为256*256,实际绘制时的区域有可能大于图片实际尺寸,也有可能小于图片实际尺寸
// 用于定义大于或小于真实尺寸时的图片算法,NEAREST效率高,LINEAR效率低但效果好,图片较小时看不出差别
webgl.texParameteriwebgl.TEXTURE_2D,webgl.TEXTURE_MAG_FILTER,webgl.NEAREST);
webgl.texParameteriwebgl.TEXTURE_2D,webgl.TEXTURE_MIN_FILTER,webgl.NEAREST);
// 一般UV坐标或ST坐标处于0到1之间,有时也会超过1,超过1时的显示方式
// gl.REPEAT 平铺
// gl.MIRRORED_REPEAT 镜像(倒影)平铺
// gl.CLAMP_TO_EDGE 使用边缘颜色填充
webgl.texParameteriwebgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.REPEAT); // 横向
webgl.texParameteriwebgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.REPEAT); // 纵向
let u_texture = webgl.getUniformLocationprogram, "u_texture"); // 获取全局变量u_texture
webgl.uniform1iu_texture, 1); // 将全局变量赋值为webgl的第二个纹理图片
clearCanvaswebgl);
webgl.drawArrayswebgl.TRIANGLES, 0, 6);
};
函数
/**
* 编译shader源码并与webgl绑定,返回program对象
* @param {*} webgl
* @param {*} vertex
* @param {*} fragment
*/
function createProgramwebgl, vertex, fragment) {
// 创建程序
let shader_vertex = webgl.createShaderwebgl.VERTEX_SHADER);
let shader_fragment = webgl.createShaderwebgl.FRAGMENT_SHADER);
webgl.shaderSourceshader_vertex, vertex);
webgl.shaderSourceshader_fragment, fragment);
// 编译源码
webgl.compileShadershader_vertex);
webgl.compileShadershader_fragment);
if webgl.getShaderParametershader_vertex, webgl.COMPILE_STATUS) === false) {
console.error'Compile Shader Error: shader_vertex,' + webgl.getShaderInfoLogshader_vertex));
}
if webgl.getShaderParametershader_fragment, webgl.COMPILE_STATUS) === false) {
console.error'Compile Shader Error: shader_fragment,' + webgl.getShaderInfoLogshader_fragment));
}
// 创建执行程序
let program = webgl.createProgram);
webgl.attachShaderprogram, shader_vertex);
webgl.attachShaderprogram, shader_fragment);
// 连接context和program
webgl.linkProgramprogram);
ifwebgl.getProgramParameterprogram, webgl.LINK_STATUS) === false) {
console.errorwebgl.getProgramInfoLogprogram));
}
webgl.useProgramprogram);
return program;
}
/**
* 向webgl添加buffer并传入data
* @param {*} webgl
* @param {*} target 数据类型,gl.ARRAY_BUFFER
* @param {*} data
*/
function bindBufferWidthDatawebgl, target, data) {
let buffer = webgl.createBuffer);
webgl.bindBuffertarget, buffer);
webgl.bufferDatatarget, data, webgl.STATIC_DRAW); // 内存数据传入显存
}
/**
* 建立JS变量和顶点输入变量的引用,返回JS变量
* @param {*} webgl
* @param {*} program
* @param {String} varName Shader中的变量名
* @param {Number} varSize 变量维度
* @param {Number} stride 每段数据长度
* @param {Number} offset 每段中的偏移量
*/
function bindVertexAttributePointerwebgl, program, varName, varSize, stride, offset) {
var pointer = webgl.getAttribLocationprogram, varName);
webgl.vertexAttribPointerpointer, varSize, webgl.FLOAT, false, stride, offset);
webgl.enableVertexAttribArraypointer);
return pointer;
}
/**
* 向Shader传入mat4类型的全局变量
* @param {*} webgl
* @param {*} program
* @param {String} varName 变量名称
* @param {mat4} data 变量值
*/
function setUniformMatrixwebgl, program, varName, data) {
let matrix = webgl.getUniformLocationprogram, 'u_matrix');
webgl.uniformMatrix4fvmatrix, false, data); // r g b a
return matrix;
}
function clearCanvaswebgl) {
webgl.clearColor0.7, 0.7, 0.7, 1);
webgl.clearwebgl.COLOR_BUFFER_BIT);
}




