实现效果
初始化shader
顶点着色器
<script id="vertexSource" type="x-shader/v-vertex">
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_transFromMatirx; //用于正方体旋转效果
varying vec4 v_Color;
void main(){
gl_Position= u_transFromMatirx * a_Position;
gl_PointSize= 20.0;
v_Color = a_Color;
}
</script>
片元着色器
<script id="fragmentSource" type="x-shader/v-fragment">
precision highp float; //精度
varying vec4 v_Color;
void main(){
gl_FragColor= v_Color;
}
</script>
创建程序program使用initShader 对着色器进行编译
export const initShader = (gl, vertexSource, fragmentSource) => {
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
return program;
};
着色器点数据颜色数据赋值
// 获取顶点着色器变量
let positionLocation = gl.getAttribLocation(program, "a_Position");
let colorLocation = gl.getAttribLocation(program, "a_Color");
let transFromMatirxLocaiton = gl.getUniformLocation(
program,
"u_transFromMatirx"
);
// 创建数据缓冲区
let points = new Float32Array();
let { vertics, index, color } = initCube(0.5); //initCube接收正方形的大小参数得到 正方形 定点、索引、颜色数据
//顶点
let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertics, gl.STATIC_DRAW);
//颜色
let colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, color, gl.STATIC_DRAW);
gl.vertexAttribPointer(
colorLocation,
3,
gl.FLOAT,
false,
3 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(colorLocation);
// 索引
let indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, index, gl.STATIC_DRAW);
gl.enable(gl.DEPTH_TEST); //开始深度缓冲区 防止正方形渲染出现异常问题
正方形 定点、索引、颜色数据
export const initCube = (h) => {
let pointsArr = new Float32Array(
[
[-h, h, h],
[-h, -h, h],
[h, -h, h],
[h, h, h],
[-h, h, -h],
[-h, -h, -h],
[h, -h, -h],
[h, h, -h],
].flat()
);
/**
*
* 0, 1, 2, 0, 2, 3, // 前
0, 3, 4, 0, 4, 5, // 右
0, 5, 6, 0, 6, 1, // 上
1, 6, 7, 1, 7, 2, // 左
7, 4, 3, 7, 3, 2, // 下
4, 7, 6, 4, 6, 5
*/
let index = new Uint8Array([
0, 1, 2, 0, 2, 3, // 前
3, 2, 6, 3, 6, 7, // 右
4, 0, 3, 4, 3, 7, // 上
4, 5, 1, 4, 1, 0, // 左
1, 5, 6, 1, 6, 2, // 下
4, 5, 6, 4, 6, 7 // 后
]);
let color = new Float32Array([
1.0,1.0,1.0,//v0 近平面 右上 颜色
1.0,0.0,1.0,//v1 近平面 左上 颜色
1.0,0.0,1.0,//v2 近平面 左下 颜色
1.0,1.0,0.0,//v3 近平面 右下 颜色
1.0,0.0,1.0,//v4 远平面 右下 颜色
1.0,1.0,1.0,//v5 远平面 左下 颜色
0.0,0.0,1.0,//v6 远平面 左上 颜色
0.0,1.0,1.0 //v7 远平面 右上 颜色
]);
return {
vertics: pointsArr,
index: index,
color:color
};
};
加上旋转效果
let rotateX = 0.005; //旋转角度
let rotateY = 0.005; //旋转角度
let transfiomMatrix = mat4.create(); //合成矩阵
let rotateYMatrix = mat4.create(); //y轴旋转
let rotateXMatrix = mat4.create(); //x轴旋转
const render = () => {
//y轴旋转
mat4.rotateY(rotateYMatrix, rotateYMatrix, rotateY);
//x轴旋转
mat4.rotateX(rotateXMatrix, rotateXMatrix, rotateX);
//旋转效果叠加
mat4.multiply(transfiomMatrix, rotateYMatrix, rotateXMatrix);
// 顶点着色器transfiomMatrix赋值
gl.uniformMatrix4fv(transFromMatirxLocaiton, false, transfiomMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
requestAnimationFrame(render);
};
render();
完成代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="500px" height="500px"></canvas>
<script src="/utils/gl-matrix.js"></script>
<script id="vertexSource" type="x-shader/v-vertex">
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_transFromMatirx;
varying vec4 v_Color;
void main(){
gl_Position= u_transFromMatirx * a_Position;
gl_PointSize= 20.0;
v_Color = a_Color;
}
</script>
<script id="fragmentSource" type="x-shader/v-fragment">
precision highp float;
uniform sampler2D u_Sampler;
varying vec4 v_Color;
void main(){
gl_FragColor= v_Color;
}
</script>
<script type="module">
import { initShader } from "./utils/shader.js";
import { initCube } from "./utils/createCube.js";
let canvas = document.getElementById("canvas");
let gl = canvas.getContext("webgl");
let mat4 = glMatrix.mat4;
const vsSource = document.getElementById("vertexSource").innerText;
const fsSource = document.getElementById("fragmentSource").innerText;
let program = initShader(gl, vsSource, fsSource);
let positionLocation = gl.getAttribLocation(program, "a_Position");
let colorLocation = gl.getAttribLocation(program, "a_Color");
let transFromMatirxLocaiton = gl.getUniformLocation(
program,
"u_transFromMatirx"
);
// 顶点
let points = new Float32Array();
let buffer = gl.createBuffer();
let { vertics, index, color } = initCube(0.5);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertics, gl.STATIC_DRAW);
gl.vertexAttribPointer(
positionLocation,
3,
gl.FLOAT,
false,
3 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(positionLocation);
let colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, color, gl.STATIC_DRAW);
gl.vertexAttribPointer(
colorLocation,
3,
gl.FLOAT,
false,
3 * Float32Array.BYTES_PER_ELEMENT,
0
);
gl.enableVertexAttribArray(colorLocation);
// 索引
let indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, index, gl.STATIC_DRAW);
gl.enable(gl.DEPTH_TEST);
let rotateX = 0.005;
let rotateY = 0.005;
let transfiomMatrix = mat4.create();
let rotateYMatrix = mat4.create();
let rotateXMatrix = mat4.create();
const render = () => {
mat4.rotateY(rotateYMatrix, rotateYMatrix, rotateY);
mat4.rotateX(rotateXMatrix, rotateXMatrix, rotateX);
mat4.multiply(transfiomMatrix, rotateYMatrix, rotateXMatrix);
gl.uniformMatrix4fv(transFromMatirxLocaiton, false, transfiomMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
requestAnimationFrame(render);
};
render();
</script>
</body>
</html>