console
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/gl-matrix/3.4.2/gl-matrix.js"></script>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css"
integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://fastly.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"
integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ"
crossorigin="anonymous"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
crossorigin="anonymous"></script>
<style type="text/css">
.myBtn {
position: absolute;
width: 150px;
display: flex;
flex-direction: column;
margin: 4px;
color:
}
</style>
<script id="vShader" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
varying vec4 vColor;
uniform mat4 uMVMatrix;
uniform mat4 uProjectMatrix;
void main(){
gl_Position = uProjectMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<script id="fShader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(){
gl_FragColor = vColor;
}
</script>
</head>
<body>
<div class="myBtn">
<button type="button" id="myButton2" data-loading-text="Loading..." class="btn btn-primary">
开始/暂停旋转摄像机
</button>
<button type="button" id="myButton" data-loading-text="Loading..." class="btn btn-primary">
开始/暂停旋转立方体
</button>
</div>
<canvas id="myCanvas" width="800" height="800"></canvas>
<script type="text/javascript">
let canvas;
let gl;
let shaderProgram;
let cubeBuffer;
let cubeAxisBuffer;
let axisBuffer;
let mVMatrix;
let projectionMatrix;
let mvMatrixStack;
let thetaCube = 0;
let thetaCamera = 45;
let rotateCube = false;
let rotateCamera = false;
let timer = -1;
function loadGlMatrix() {
window["mat2"] = glMatrix.mat2;
window["mat2d"] = glMatrix.mat2d;
window["mat3"] = glMatrix.mat3;
window["mat4"] = glMatrix.mat4;
window["quat"] = glMatrix.quat;
window["quat2"] = glMatrix.quat2;
window["vec2"] = glMatrix.vec2;
window["vec3"] = glMatrix.vec3;
window["vec4"] = glMatrix.vec4;
window["glMatrix"] = glMatrix.glMatrix;
mVMatrix = mat4.create();
projectionMatrix = mat4.create();
mvMatrixStack = [];
}
function loadGl() {
canvas = document.getElementById('myCanvas');
let context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (context) {
gl = context;
} else {
alert('不支持webgl');
}
}
function loadShader() {
var vShaderSource = document.getElementById('vShader').innerText;
var fShaderSource = document.getElementById('fShader').innerText;
let vShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vShader, vShaderSource);
gl.compileShader(vShader);
let fShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fShader, fShaderSource);
gl.compileShader(fShader);
if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS) | !gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
alert('程序编译失败');
return;
}
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vShader);
gl.attachShader(shaderProgram, fShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('程序连接失败');
return;
}
gl.useProgram(shaderProgram);
}
function setupAxisBuffers() {
let axisVertex = [
//x轴xyz, rgba
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
4.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
//y轴xyz, rgba
0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,
0.0, 4.0, 0.0, 0.0, 1.0, 0.0, 1.0,
//z轴xyz, rgba
0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 4.0, 0.0, 0.0, 1.0, 1.0,
];
axisBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, axisBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(axisVertex), gl.STATIC_DRAW);
}
function setupCubeBuffers() {
let cubeVertex = [
-1.0, -1.0, -1.0, 132, 94, 194, 255,
-1.0, 1.0, -1.0, 132, 94, 194, 255,
1.0, -1.0, -1.0, 132, 94, 194, 255,
-1.0, 1.0, -1.0, 132, 94, 194, 255,
1.0, 1.0, -1.0, 132, 94, 194, 255,
1.0, -1.0, -1.0, 132, 94, 194, 255,
-1.0, -1.0, 1.0, 214, 93, 177, 255,
1.0, -1.0, 1.0, 214, 93, 177, 255,
-1.0, 1.0, 1.0, 214, 93, 177, 255,
-1.0, 1.0, 1.0, 214, 93, 177, 255,
1.0, -1.0, 1.0, 214, 93, 177, 255,
1.0, 1.0, 1.0, 214, 93, 177, 255,
-1.0, 1.0, -1.0, 255, 111, 145, 255,
-1.0, 1.0, 1.0, 255, 111, 145, 255,
1.0, 1.0, -1.0, 255, 111, 145, 255,
-1.0, 1.0, 1.0, 255, 111, 145, 255,
1.0, 1.0, 1.0, 255, 111, 145, 255,
1.0, 1.0, -1.0, 255, 111, 145, 255,
-1.0, -1.0, -1.0, 255, 150, 113, 255,
1.0, -1.0, -1.0, 255, 150, 113, 255,
-1.0, -1.0, 1.0, 255, 150, 113, 255,
-1.0, -1.0, 1.0, 255, 150, 113, 255,
1.0, -1.0, -1.0, 255, 150, 113, 255,
1.0, -1.0, 1.0, 255, 150, 113, 255,
-1.0, -1.0, -1.0, 255, 199, 95, 255,
-1.0, -1.0, 1.0, 255, 199, 95, 255,
-1.0, 1.0, -1.0, 255, 199, 95, 255,
-1.0, -1.0, 1.0, 255, 199, 95, 255,
-1.0, 1.0, 1.0, 255, 199, 95, 255,
-1.0, 1.0, -1.0, 255, 199, 95, 255,
1.0, -1.0, -1.0, 249, 248, 113, 255,
1.0, 1.0, -1.0, 249, 248, 113, 255,
1.0, -1.0, 1.0, 249, 248, 113, 255,
1.0, -1.0, 1.0, 249, 248, 113, 255,
1.0, 1.0, -1.0, 249, 248, 113, 255,
1.0, 1.0, 1.0, 249, 248, 113, 255,
];
cubeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeBuffer);
let numberOfPoint = 36; //总节点数
let FLOATSIZE = Float32Array.BYTES_PER_ELEMENT; //每个元素4个字节
let UINTSIZE = Uint8Array.BYTES_PER_ELEMENT; //每个元素1个字节
let vertexSizeInBytes = 3 * FLOATSIZE + 4 * UINTSIZE;//每个顶点所占字节数
let realBuffer = new ArrayBuffer(numberOfPoint * vertexSizeInBytes);
var vertexSizeInFloats = vertexSizeInBytes / Float32Array.BYTES_PER_ELEMENT;
var positionView = new Float32Array(realBuffer);
var colorView = new Uint8Array(realBuffer);
var positionOffsetInFloats = 0;
var colorOffsetInBytes = 3 * FLOATSIZE;
var k = 0;
for (let i = 0; i < numberOfPoint; i++) {
positionView[positionOffsetInFloats] = cubeVertex[k];
positionView[1 + positionOffsetInFloats] = cubeVertex[k + 1];
positionView[2 + positionOffsetInFloats] = cubeVertex[k + 2];
colorView[colorOffsetInBytes] = cubeVertex[k + 3];
colorView[1 + colorOffsetInBytes] = cubeVertex[k + 4];
colorView[2 + colorOffsetInBytes] = cubeVertex[k + 5];
colorView[3 + colorOffsetInBytes] = cubeVertex[k + 6];
positionOffsetInFloats += vertexSizeInFloats;
colorOffsetInBytes += vertexSizeInBytes;
k += 7;
}
gl.bufferData(gl.ARRAY_BUFFER, realBuffer, gl.STATIC_DRAW);
}
function setupCubeAxisBuffers() {
let axisVertex = [
//x轴xyz, rgba
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
//y轴xyz, rgba
0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,
0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0,
//z轴xyz, rgba
0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0,
];
cubeAxisBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeAxisBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(axisVertex), gl.STATIC_DRAW);
}
function drawAxis() {
gl.bindBuffer(gl.ARRAY_BUFFER, axisBuffer);
let axisPositionIndex = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
let axisColorIndex = gl.getAttribLocation(shaderProgram, 'aVertexColor');
let FSIZE = Float32Array.BYTES_PER_ELEMENT;
gl.enableVertexAttribArray(axisPositionIndex);
gl.vertexAttribPointer(axisPositionIndex, 3, gl.FLOAT, false, FSIZE * 7, 0);
gl.enableVertexAttribArray(axisColorIndex);
gl.vertexAttribPointer(axisColorIndex, 4, gl.FLOAT, false, FSIZE * 7, FSIZE * 3);
gl.drawArrays(gl.LINES, 0, 6);
}
function drawCubeAxis() {
gl.bindBuffer(gl.ARRAY_BUFFER, cubeAxisBuffer);
let axisPositionIndex = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
let axisColorIndex = gl.getAttribLocation(shaderProgram, 'aVertexColor');
let FSIZE = Float32Array.BYTES_PER_ELEMENT;
gl.enableVertexAttribArray(axisPositionIndex);
gl.vertexAttribPointer(axisPositionIndex, 3, gl.FLOAT, false, FSIZE * 7, 0);
gl.enableVertexAttribArray(axisColorIndex);
gl.vertexAttribPointer(axisColorIndex, 4, gl.FLOAT, false, FSIZE * 7, FSIZE * 3);
gl.drawArrays(gl.LINES, 0, 6);
}
function drawCube() {
let numberOfPoint = 36; //总节点数
let FLOATSIZE = Float32Array.BYTES_PER_ELEMENT; //每个元素4个字节
let UINTSIZE = Uint8Array.BYTES_PER_ELEMENT; //每个元素1个字节
let vertexSizeInBytes = 3 * FLOATSIZE + 4 * UINTSIZE;//每个顶点所占字节数
gl.bindBuffer(gl.ARRAY_BUFFER, cubeBuffer);
gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexPosition'));
gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, 'aVertexPosition'), 3, gl.FLOAT, false, vertexSizeInBytes, 0);
gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexColor'));
gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, 'aVertexColor'), 4, gl.UNSIGNED_BYTE, true, vertexSizeInBytes, 3 * FLOATSIZE);
gl.drawArrays(gl.TRIANGLES, 0, numberOfPoint);
}
function setupBuffers() {
setupAxisBuffers();
setupCubeBuffers();
setupCubeAxisBuffers();
}
function draws() {
if (timer > 0) {
if (rotateCube && !rotateCamera) {
thetaCube += 1;
}else if (!rotateCube && rotateCamera) {
thetaCamera += 1;
}else if (rotateCube && rotateCamera) {
thetaCube += 1;
thetaCamera += 1;
}
}
radius = 8;
var x = Math.cos(glMatrix.toRadian(thetaCamera)) * radius;
var z = Math.sin(glMatrix.toRadian(thetaCamera)) * radius;
radius2 = 2;
var x2 = Math.cos(glMatrix.toRadian(thetaCube)) * radius2;
var z2 = Math.sin(glMatrix.toRadian(thetaCube)) * radius2;
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(projectionMatrix, glMatrix.toRadian(60), canvas.width / canvas.height, 0.1, 150);
mat4.identity(mVMatrix);
//alert(mat4.str(mVMatrix));
mat4.lookAt(mVMatrix, [x, 8, z], [0, 0, 0], [0, 1, 0]);
//alert(mat4.str(mVMatrix));
uploadModelViewMatrixToShader();
uploadProjectionMatrixToShader();
drawAxis();
pushMvMatrixStack();
let cameraMatrix = mat4.create();
mat4.targetTo(cameraMatrix, [x2, 2.0, z2], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
mat4.multiply(mVMatrix, mVMatrix, cameraMatrix);
uploadModelViewMatrixToShader();
drawCube();
drawCubeAxis();
popMvMatrixStack();
if (timer > 0) {
timer = window.requestAnimationFrame(draws);
}
}
$('#myButton').on('click', function () {
if (timer < 0) {
rotateCube = true;
startAnimate();
} else if (timer > 0) {
if (rotateCamera && !rotateCube) {
rotateCube = true;
}else if (rotateCamera && rotateCube) {
rotateCube = false;
}else if (!rotateCamera && rotateCube) {
rotateCube = false;
endAnimate();
}
}
});
$('#myButton2').on('click', function () {
if (timer < 0) {
rotateCamera = true;
startAnimate();
} else if(timer > 0){
if (rotateCube && !rotateCamera) {
rotateCamera = true;
}else if(rotateCube && rotateCamera){
rotateCamera = false;
} else if (!rotateCube && rotateCamera) {
rotateCamera = false;
endAnimate();
}
}
});
function popMvMatrixStack() {
if (mvMatrixStack.length > 0) {
mVMatrix = mvMatrixStack.pop();
} else {
alert('mvMatrixStack为空')
}
}
function pushMvMatrixStack() {
let copyToPush = mat4.create(mVMatrix);
mvMatrixStack.push(copyToPush);
}
function uploadModelViewMatrixToShader() {
let mvMatrixIndex = gl.getUniformLocation(shaderProgram, 'uMVMatrix');
gl.uniformMatrix4fv(mvMatrixIndex, false, mVMatrix);
}
function uploadProjectionMatrixToShader() {
let projectionMatrixIndex = gl.getUniformLocation(shaderProgram, 'uProjectMatrix');
gl.uniformMatrix4fv(projectionMatrixIndex, false, projectionMatrix);
}
$(window).load(function () {
loadGlMatrix();
loadGl();
loadShader();
setupBuffers();
draws();
});
function startAnimate() {
timer = 1;
draws();
}
function endAnimate() {
timer = -1;
window.cancelAnimationFrame(timer);
}
</script>
</body>
</html>