创建动画3D WebGL演示

本文是一篇3D WebGL演示教程,介绍了如何使用HTML5 canvas创建3D对象并进行动画处理。作者逐步指导读者从HTML设置到CSS样式,再到JS文件的使用,包括webgl-utils.js、glMatrix库和script.js的实现,最终完成3D对象的绘制和动画效果。
摘要由CSDN通过智能技术生成
Making 3D WebGL demonstration
Making 3D WebGL demonstration

3D WebGL demonstration tutorial. Today we continue HTML5 canvas examples. And today we will try to begin learning WebGL. In my demonstration I will show you how to initialize WebGL and draw simple 3D object. Also we will animate this object too.

3D WebGL演示教程。 今天,我们继续HTML5 canvas示例。 今天,我们将尝试开始学习WebGL。 在我的演示中,我将向您展示如何初始化WebGL和绘制简单的3D对象。 此外,我们还将为该对象设置动画。

Here are our demo and downloadable package:

这是我们的演示和可下载的软件包:

现场演示

[sociallocker]

[社交储物柜]

打包下载

[/sociallocker]

[/ sociallocker]

Ok, download the example files and lets start coding !

好的,下载示例文件并开始编码!

步骤1. HTML (Step 1. HTML)

Here are html source code of our demo. As you can see – just empty page.

这是我们演示的html源代码。 如您所见–只是空白页。

index.html (index.html)

<!DOCTYPE html>
<html lang="en" >
<head>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="js/glMatrix-0.9.5.min.js"></script>
    <script type="text/javascript" src="js/webgl-utils.js"></script>
    <script type="text/javascript" src="js/script.js"></script>
    <title>WebGL demonstration | Script Tutorials</title>
</head>
<body onload="initWebGl();">
    <div class="example">
        <h3><a href="https://www.script-tutorials.com/making-3d-webgl-demonstration/">WebGL demonstration | Script Tutorials</a></h3>
        <canvas id="panel" width="500" height="333"></canvas>
        <div style="clear:both;"></div>
    </div>
</body>
</html>

<!DOCTYPE html>
<html lang="en" >
<head>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="js/glMatrix-0.9.5.min.js"></script>
    <script type="text/javascript" src="js/webgl-utils.js"></script>
    <script type="text/javascript" src="js/script.js"></script>
    <title>WebGL demonstration | Script Tutorials</title>
</head>
<body onload="initWebGl();">
    <div class="example">
        <h3><a href="https://www.script-tutorials.com/making-3d-webgl-demonstration/">WebGL demonstration | Script Tutorials</a></h3>
        <canvas id="panel" width="500" height="333"></canvas>
        <div style="clear:both;"></div>
    </div>
</body>
</html>

步骤2. CSS (Step 2. CSS)

Here are used CSS styles.

这是使用CSS样式。

css / main.css (css/main.css)

body {
    background:#eee;
    font-family:Verdana, Helvetica, Arial, sans-serif;
    margin:0;
    padding:0
}
.example {
    background:#fff;
    width:500px;
    font-size:80%;
    border:1px #000 solid;
    margin:20px auto;
    padding:15px;
    position:relative;
    -moz-border-radius: 3px;
    -webkit-border-radius:3px
}
h3 {
    text-align:center;
}

body {
    background:#eee;
    font-family:Verdana, Helvetica, Arial, sans-serif;
    margin:0;
    padding:0
}
.example {
    background:#fff;
    width:500px;
    font-size:80%;
    border:1px #000 solid;
    margin:20px auto;
    padding:15px;
    position:relative;
    -moz-border-radius: 3px;
    -webkit-border-radius:3px
}
h3 {
    text-align:center;
}

步骤3. JS (Step 3. JS)

js / webgl-utils.js和js / glMatrix-0.9.5.min.js (js/webgl-utils.js and js/glMatrix-0.9.5.min.js)

These files we will use in project for working with WebGL. Both files will in our package.

我们将在项目中使用这些文件来使用WebGL。 这两个文件都将放在我们的程序包中。

js / script.js (js/script.js)

var gl; // global WebGL object
var shaderProgram;
function initGL(canvas) {
    try {
        gl = canvas.getContext('experimental-webgl');
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
    } catch (e) {}
    if (! gl) {
        alert('Can`t initialise WebGL, not supported');
    }
}
function getShader(gl, type) {
    var str = '';
    var shader;
    if (type == 'x-fragment') {
        str = "#ifdef GL_ES\n"+
"precision highp float;\n"+
"#endif\n"+
"varying vec4 vColor;\n"+
"void main(void) {\n"+
"    gl_FragColor = vColor;\n"+
"}\n";
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (type == 'x-vertex') {
        str = "attribute vec3 aVertexPosition;\n"+
"attribute vec4 aVertexColor;\n"+
"uniform mat4 uMVMatrix;\n"+
"uniform mat4 uPMatrix;\n"+
"varying vec4 vColor;\n"+
"void main(void) {\n"+
"    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\n"+
"    vColor = aVertexColor;\n"+
"}\n";
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }
    gl.shaderSource(shader, str);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }
    return shader;
}
function initShaders() {
    var fragmentShader = getShader(gl, 'x-fragment');
    var vertexShader = getShader(gl, 'x-vertex');
    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert('Can`t initialise shaders');
    }
    gl.useProgram(shaderProgram);
    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
    shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, 'aVertexColor');
    gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, 'uPMatrix');
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, 'uMVMatrix');
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
    var copy = mat4.create();
    mat4.set(mvMatrix, copy);
    mvMatrixStack.push(copy);
}
function mvPopMatrix() {
    if (mvMatrixStack.length == 0) {
        throw 'Invalid popMatrix!';
    }
    mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
    return degrees * Math.PI / 180;
}
var objVertexPositionBuffer;
var objVertexColorBuffer;
function initObjBuffers() {
    objVertexPositionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer);
    var vertices = [
         1.0,  2.0,  -1.0,
        -1.0,  2.0,  -1.0,
         1.0, -2.0,  -1.0,
        -1.0, -2.0,  -1.0,
         1.0,  2.0,  1.0,
        -1.0,  2.0,  1.0,
         1.0, -2.0,  1.0,
        -1.0, -2.0,  1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    objVertexPositionBuffer.itemSize = 3;
    objVertexPositionBuffer.numItems = 8;
    objVertexColorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexColorBuffer);
    var colors = [
        1.0, 0.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 0.5,
        0.0, 1.0, 0.0, 1.0,
        0.0, 0.0, 1.0, 1.0,
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 0.5,
        1.0, 0.0, 0.0, 1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    objVertexColorBuffer.itemSize = 4;
    objVertexColorBuffer.numItems = 8;
}
var iObjDeg = 0;
function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix, [0.0, 0.0, -10.0]);
    mvPushMatrix();
    mat4.rotate(mvMatrix, degToRad(iObjDeg), [1, 1, 1]);
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, objVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexColorBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, objVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, objVertexPositionBuffer.numItems);
    mvPopMatrix();
}
function drawFrame() {
    requestAnimFrame(drawFrame);
    drawScene();
    iObjDeg += 3; // 3 degrees per frame
}
function initWebGl() {
    var canvas = document.getElementById('panel');
    initGL(canvas);
    initShaders()
    initObjBuffers();
    gl.clearColor(1.0, 0.5, 0.3, 1.0);
    gl.enable(gl.DEPTH_TEST);
    drawFrame();
}

var gl; // global WebGL object
var shaderProgram;
function initGL(canvas) {
    try {
        gl = canvas.getContext('experimental-webgl');
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
    } catch (e) {}
    if (! gl) {
        alert('Can`t initialise WebGL, not supported');
    }
}
function getShader(gl, type) {
    var str = '';
    var shader;
    if (type == 'x-fragment') {
        str = "#ifdef GL_ES\n"+
"precision highp float;\n"+
"#endif\n"+
"varying vec4 vColor;\n"+
"void main(void) {\n"+
"    gl_FragColor = vColor;\n"+
"}\n";
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (type == 'x-vertex') {
        str = "attribute vec3 aVertexPosition;\n"+
"attribute vec4 aVertexColor;\n"+
"uniform mat4 uMVMatrix;\n"+
"uniform mat4 uPMatrix;\n"+
"varying vec4 vColor;\n"+
"void main(void) {\n"+
"    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\n"+
"    vColor = aVertexColor;\n"+
"}\n";
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }
    gl.shaderSource(shader, str);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }
    return shader;
}
function initShaders() {
    var fragmentShader = getShader(gl, 'x-fragment');
    var vertexShader = getShader(gl, 'x-vertex');
    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert('Can`t initialise shaders');
    }
    gl.useProgram(shaderProgram);
    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
    shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, 'aVertexColor');
    gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, 'uPMatrix');
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, 'uMVMatrix');
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
    var copy = mat4.create();
    mat4.set(mvMatrix, copy);
    mvMatrixStack.push(copy);
}
function mvPopMatrix() {
    if (mvMatrixStack.length == 0) {
        throw 'Invalid popMatrix!';
    }
    mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
    return degrees * Math.PI / 180;
}
var objVertexPositionBuffer;
var objVertexColorBuffer;
function initObjBuffers() {
    objVertexPositionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer);
    var vertices = [
         1.0,  2.0,  -1.0,
        -1.0,  2.0,  -1.0,
         1.0, -2.0,  -1.0,
        -1.0, -2.0,  -1.0,
         1.0,  2.0,  1.0,
        -1.0,  2.0,  1.0,
         1.0, -2.0,  1.0,
        -1.0, -2.0,  1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    objVertexPositionBuffer.itemSize = 3;
    objVertexPositionBuffer.numItems = 8;
    objVertexColorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexColorBuffer);
    var colors = [
        1.0, 0.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 0.5,
        0.0, 1.0, 0.0, 1.0,
        0.0, 0.0, 1.0, 1.0,
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 0.5,
        1.0, 0.0, 0.0, 1.0,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    objVertexColorBuffer.itemSize = 4;
    objVertexColorBuffer.numItems = 8;
}
var iObjDeg = 0;
function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix, [0.0, 0.0, -10.0]);
    mvPushMatrix();
    mat4.rotate(mvMatrix, degToRad(iObjDeg), [1, 1, 1]);
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, objVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
    gl.bindBuffer(gl.ARRAY_BUFFER, objVertexColorBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, objVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, objVertexPositionBuffer.numItems);
    mvPopMatrix();
}
function drawFrame() {
    requestAnimFrame(drawFrame);
    drawScene();
    iObjDeg += 3; // 3 degrees per frame
}
function initWebGl() {
    var canvas = document.getElementById('panel');
    initGL(canvas);
    initShaders()
    initObjBuffers();
    gl.clearColor(1.0, 0.5, 0.3, 1.0);
    gl.enable(gl.DEPTH_TEST);
    drawFrame();
}

Pretty big code, isn’t it? but anyway – here are all necessary to draw our demo. Since page loaded – we performing few initializations (initGL, initShaders, initObjBuffers functions), then we defining color for our scene (via gl.clearColor), and after – drawing our scene (drawFrame function). In this function we using ‘requestAnimFrame’ to define function which will calling periodically when WebGL will need to draw next frame.

相当大的代码,不是吗? 但无论如何–这是绘制演示的所有必要条件。 由于页面加载-我们执行了很少的初始化(initGL,initShaders,initObjBuffers函数),因此我们定义了场景的颜色(通过gl.clearColor),然后绘制了场景(drawFrame函数)。 在此函数中,我们使用“ requestAnimFrame”定义函数,该函数将在WebGL需要绘制下一帧时定期调用。

现场演示

结论 (Conclusion)

Not bad, isn`t it? Possible today we made first step to next generation. And possible that in coming future we will start a series of articles related with game development with HTML5. Welcome back!

还不错,不是吗? 今天,我们有可能迈向下一代。 可能在将来,我们将开始一系列与HTML5游戏开发相关的文章。 欢迎回来!

翻译自: https://www.script-tutorials.com/making-3d-webgl-demonstration/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值