博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebGL自学教程——WebGL示例:13.0 代码整理
阅读量:4217 次
发布时间:2019-05-26

本文共 12316 字,大约阅读时间需要 41 分钟。

 
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
<script type="text/javascript" src="glMatrix-0.9.5.js"></script>
<script type="text/javascript" src="glt.js"></script>
<script type="text/javascript" src="gl-0.1.js"></script><!--此文件已作了一些修改-->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 a_v3Position;
attribute vec3 a_v3Normal;
uniform mat4 u_m4ModelView;
varying vec3 v_v3TexCoord;
uniform int u_iShadowMode;
varying vec3 v_v3Position;
varying vec3 v_v3Normal;
void main(void)
{
    gl_Position = u_m4ModelView * vec4(a_v3Position, 1.0);
   
    if(u_iShadowMode == 0)
    {
        v_v3TexCoord = a_v3Position;
        v_v3Position = a_v3Position;
        v_v3Normal = vec3(u_m4ModelView * vec4(a_v3Normal, 1.0));
    }
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
#else
    precision mediump float;
#endif
uniform samplerCube u_samplerCube;
varying vec3 v_v3TexCoord;
uniform int u_iShadowMode;
varying vec3 v_v3Position;
varying vec3 v_v3Normal;
uniform bool u_bUseLighting;
uniform vec3 u_v3AmbientScale;
uniform vec3 u_v3PointLightPosition;
uniform vec3 u_v3PointLightScale;
void main(void)
{
    if(u_iShadowMode == 0)
    {
        vec3 v3ColorScale;
        if(!u_bUseLighting) v3ColorScale = vec3(1.0, 1.0, 1.0);
        else
        {
            vec3 v3PLV = u_v3PointLightPosition - v_v3Position;
            if(dot(v_v3Normal, v3PLV) > 0.0)//可以被点光源照射到
            {
                //求出顶点到点光源的距离,假设在距离0-1.5范围内线性衰减;当然也可以使用其他的光照公式
                float f = max(0.0, 1.0 - length(v3PLV) / 2.0);//要注意的是,示例中旋转的只有立方体,光源的位置并没有变动
               
                v3ColorScale = u_v3AmbientScale + u_v3PointLightScale * f;//将衰减后的点光源颜色比例合并到环境光
            }
            else v3ColorScale = u_v3AmbientScale;
        }
       
        vec4 color = textureCube(u_samplerCube, v_v3TexCoord);
        gl_FragColor = vec4(color.rgb * v3ColorScale, color.a);
    }
    else if(u_iShadowMode == 1) gl_FragColor = vec4(0.7, 0.7, 0.7, 1.0);
    else if(u_iShadowMode == 2) gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    else if(u_iShadowMode == 3) gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
</script>
<script>
var textureObject = null;
var shadowMat4 = null;//预先计算好的阴影矩阵
var mouseDown = false;
var mousePosition = [0, 0];
var perspectiveMat4 = null;//预先计算好的投影矩阵
var rotateMat4 = null;
var rotatePosV3 =  [0, 0, 0];;//记录离圆心的偏移,2D,弄成vec3只是为了方便执行加减操作
var jsConeMat4 = null;
function LoadData()
{
    var jsCubeData = [
            // Front face
            -0.3, -0.3,  0.3,
             0.3, -0.3,  0.3,
             0.3,  0.3,  0.3,
            -0.3,  0.3,  0.3,
            // Back face
            -0.3, -0.3, -0.3,
            -0.3,  0.3, -0.3,
             0.3,  0.3, -0.3,
             0.3, -0.3, -0.3,
            // Top face
            -0.3,  0.3, -0.3,
            -0.3,  0.3,  0.3,
             0.3,  0.3,  0.3,
             0.3,  0.3, -0.3,
            // Bottom face
            -0.3, -0.3, -0.3,
             0.3, -0.3, -0.3,
             0.3, -0.3,  0.3,
            -0.3, -0.3,  0.3,
            // Right face
             0.3, -0.3, -0.3,
             0.3,  0.3, -0.3,
             0.3,  0.3,  0.3,
             0.3, -0.3,  0.3,
            // Left face
            -0.3, -0.3, -0.3,
            -0.3, -0.3,  0.3,
            -0.3,  0.3,  0.3,
            -0.3,  0.3, -0.3,
    ];
    oJSWebGL.JS_LoadArrayBuffer("cube", new Float32Array(jsCubeData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);//加载之后,可以通过oJSWebGL.jsBuffers.cube进行访问
    var jsCubeIndex = [
            0, 1, 2,      0, 2, 3,    // Front face
            4, 5, 6,      4, 6, 7,    // Back face
            8, 9, 10,     8, 10, 11,  // Top face
            12, 13, 14,   12, 14, 15, // Bottom face
            16, 17, 18,   16, 18, 19, // Right face
            20, 21, 22,   20, 22, 23  // Left face
    ];
    oJSWebGL.JS_LoadElementArrayBuffer("cubeIndex", new Uint8Array(jsCubeIndex), webgl.STATIC_DRAW, 3, webgl.UNSIGNED_BYTE, false);//加载之后,可以通过oJSWebGL.jsBuffers.cubeIndex进行访问
    
    var jsCubeNormals = [
            // Front face
             0.0,  0.0,  1.0,
             0.0,  0.0,  1.0,
             0.0,  0.0,  1.0,
             0.0,  0.0,  1.0,
            // Back face
             0.0,  0.0, -1.0,
             0.0,  0.0, -1.0,
             0.0,  0.0, -1.0,
             0.0,  0.0, -1.0,
            // Top face
             0.0,  1.0,  0.0,
             0.0,  1.0,  0.0,
             0.0,  1.0,  0.0,
             0.0,  1.0,  0.0,
            // Bottom face
             0.0, -1.0,  0.0,
             0.0, -1.0,  0.0,
             0.0, -1.0,  0.0,
             0.0, -1.0,  0.0,
            // Right face
             1.0,  0.0,  0.0,
             1.0,  0.0,  0.0,
             1.0,  0.0,  0.0,
             1.0,  0.0,  0.0,
            // Left face
            -1.0,  0.0,  0.0,
            -1.0,  0.0,  0.0,
            -1.0,  0.0,  0.0,
            -1.0,  0.0,  0.0,
    ];
    oJSWebGL.JS_LoadArrayBuffer("cubeNormals", new Float32Array(jsCubeNormals), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);//加载之后,可以通过oJSWebGL.jsBuffers.cubeNormals进行访问
   
    textureObject = webgl.createTexture();
    webgl.bindTexture(webgl.TEXTURE_CUBE_MAP, textureObject);
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture1'));
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture2'));
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture3'));
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture4'));
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture5'));
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, document.getElementById('myTexture6'));
 
 
    var jsShadowPlaneData = [-1.0, -1.0, 1.0,   -1.0,-0.25,-1.0,   1.0,-0.25,-1.0,   1.0, -1.0, 1.0];
    oJSWebGL.JS_LoadArrayBuffer("shadowPlane", new Float32Array(jsShadowPlaneData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);
    shadowMat4 = mat4.create();
    gltMakeShadowMatrix([[-1, -1, 1], [1, -1, 1], [0, -0.25, -1]], [-1, 1, 0, 1], shadowMat4);//预先计算好阴影矩阵,这样就不用重复计算
 
    var lookAtMat4 = mat4.create();
    mat4.lookAt([0, 0, 1], [0,0,0], [0,1,0], lookAtMat4);
    perspectiveMat4 = mat4.create();
    var wh = oJSWebGL.Viewport();
    mat4.perspective(60, wh[0]/wh[1], 0.1, 2, perspectiveMat4);
    mat4.multiply(perspectiveMat4, lookAtMat4, perspectiveMat4);
    var jsConeData = [0, 0.2, 0];//圆锥的顶部顶点为(0, 0.2, 0)
    for(var i=0; i<13; ++i)//计算圆锥顶部圆面上的12个点;圆的半径为0.1
    {
        //保证各个顶点为顺时针顺序
        var radians = -i*30*Math.PI/180;
        jsConeData[jsConeData.length] = parseInt(0.1 * Math.cos(radians)*1000)/1000;
        jsConeData[jsConeData.length] = 0;
        jsConeData[jsConeData.length] = -parseInt(0.1 * Math.sin(radians)*1000)/1000;
    }
    oJSWebGL.JS_LoadArrayBuffer("cone", new Float32Array(jsConeData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);
    jsConeMat4 = new CJSMat4();
    jsConeMat4.Identity();
    jsConeMat4.RotateX(Math.PI/2);
    jsConeMat4.Translate([0, 0, 0.3]);
    rotateMat4 = mat4.create();
    mat4.identity(rotateMat4);
    return 0;
}
function RenderScene()
{
    webgl.clearColor(0.0, 0.0, 0.0, 1.0);
    webgl.clearDepth(1.0);
    webgl.clear(webgl.COLOR_BUFFER_BIT|webgl.DEPTH_BUFFER_BIT);
   
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST);
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST);
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE);
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE);
    oJSWebGL.BindTextureUnit(webgl.TEXTURE0, webgl.TEXTURE_CUBE_MAP, textureObject);//直观
    webgl.uniform1i(oJSWebGLProgram.u_samplerCube, 0);
   
    webgl.frontFace(webgl.CW);
    webgl.cullFace(webgl.BACK);
    //画平面
    webgl.disable(webgl.DEPTH_TEST);//相当于地面,禁止深度测试,此时深度缓冲中值保持1.0不变,表示可以被任何其它物体所遮挡
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Position, "shadowPlane", 0, 0);
    webgl.enableVertexAttribArray(oJSWebGLProgram.a_v3Position);
    webgl.disableVertexAttribArray(oJSWebGLProgram.a_v3Normal);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 2);
    //只需要透视投影
    webgl.uniformMatrix4fv(oJSWebGLProgram.u_m4ModelView, false, perspectiveMat4);
    webgl.drawArrays(webgl.TRIANGLE_FAN, 0, 4);
    var jsMatrix = new CJSMat4();
    //画立方体
    //先旋转,再透视投影
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Position, "cube", 0, 0);
    oJSWebGL.JS_SetCurrentBuffer("cubeIndex");
    webgl.enableVertexAttribArray(oJSWebGLProgram.a_v3Position);
    //画阴影
    webgl.disable(webgl.DEPTH_TEST);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 1);
    webgl.disableVertexAttribArray(oJSWebGLProgram.a_v3Normal);
    jsMatrix.Identity();
    jsMatrix.Transform(rotateMat4, shadowMat4, perspectiveMat4);
    webgl.uniformMatrix4fv(oJSWebGLProgram.u_m4ModelView, false, jsMatrix.GetValue());
    webgl.drawElements(webgl.TRIANGLES, 36, webgl.UNSIGNED_BYTE, 0);
    //画立方体
    webgl.uniform1i(oJSWebGLProgram.u_bUseLighting, document.getElementById("lighting").checked);
    webgl.uniform3f(oJSWebGLProgram.u_v3AmbientScale,
                parseFloat(document.getElementById("ambientR").value),
                parseFloat(document.getElementById("ambientG").value),
                parseFloat(document.getElementById("ambientB").value));
     webgl.uniform3fv(oJSWebGLProgram.u_v3PointLightPosition, [-1, 1, 0]);
     webgl.uniform3f(oJSWebGLProgram.u_v3PointLightScale,
                parseFloat(document.getElementById("pointR").value),
                parseFloat(document.getElementById("pointG").value),
                parseFloat(document.getElementById("pointB").value));
    webgl.enable(webgl.DEPTH_TEST);
    webgl.depthFunc(webgl.LEQUAL);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 0);
    jsMatrix.Identity();
    jsMatrix.Transform(rotateMat4, perspectiveMat4);
    webgl.uniformMatrix4fv(oJSWebGLProgram.u_m4ModelView, false, jsMatrix.GetValue());
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Normal, "cubeNormals", 0, 0);
    webgl.enableVertexAttribArray(oJSWebGLProgram.a_v3Normal);
    webgl.drawElements(webgl.TRIANGLES, 36, webgl.UNSIGNED_BYTE, 0);
   
    //画圆锥
    webgl.enable(webgl.DEPTH_TEST);
    webgl.depthFunc(webgl.LEQUAL);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 3);   
    jsMatrix.Identity();
    jsMatrix.Transform(jsConeMat4, rotateMat4, perspectiveMat4);
    webgl.uniformMatrix4fv(oJSWebGLProgram.u_m4ModelView, false, jsMatrix.GetValue());
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Position, "cone", 0, 0);
    webgl.enableVertexAttribArray(oJSWebGLProgram.a_v3Position);
    webgl.disableVertexAttribArray(oJSWebGLProgram.a_v3Normal);
    webgl.drawArrays(webgl.TRIANGLE_FAN, 0, 14);
}
//这些事件代码仍然只适合FF浏览器
function OnMouseDown(e)
{
    mouseDown = true;
    mousePosition = [parseInt(e.screenX), parseInt(e.screenY)];
}
function OnMouseUp(e)
{
    mouseDown = false;
    vec3.add(rotatePosV3, [parseInt(e.screenX)-mousePosition[0], parseInt(e.screenY)-mousePosition[1], 0]);
}
function OnMouseMove(e)
{
    if(!mouseDown) return;
    var tV3 = [];
    vec3.add(rotatePosV3, [parseInt(e.screenX)-mousePosition[0], parseInt(e.screenY)-mousePosition[1], 0], tV3);//上次偏移加拖动形成的临时偏移成为本次拖动的最终偏移
    mat4.identity(rotateMat4);//首先设置为单位矩阵,然后再构造成旋转矩阵
    if(tV3[0] == 0 && tV3[1] == 0) return;
    //根据位移,计算出当前的方向
    var v3 = null;
    var wh = oJSWebGL.Viewport();
    var r = Math.min(wh[0], wh[1])/2;
    var l = Math.sqrt(tV3[0]*tV3[0] + tV3[1] * tV3[1]);
    if(l <= r) v3 = [tV3[0], tV3[1], Math.sqrt(r*r - l*l)];
    else v3 = [r*tV3[0]/l, r*tV3[1]/l, 0];
    v3[1] = - v3[1];
    var radians = Math.acos(vec3.dot([0,0,1], v3)/r);
    var vn = [];
    gltGetNormalVector([0,0,0], [0,0,1], v3, vn);//或vec3.cross([0,0,1], v3, vn);
   
    mat4.rotate(rotateMat4, radians, vn);
}
var oJSWebGL = null;
var oJSWebGLProgram = null;
var webgl = null;
function Init()
{
    oJSWebGL  = new CJSWebGL ('myCanvas');
    try
    {
        if(!oJSWebGL.Init()) throw oJSWebGL.error;
        webgl = oJSWebGL.webgl;
        oJSWebGLProgram = oJSWebGL.JS_SetupProgramObject("shader-vs", "shader-fs", true);
        if(oJSWebGLProgram  == null) throw oJSWebGL.error;//如果oJSWebGLProgram生成成功,则各个活动属性和活动uniform的位置/索引都将自动保存到oJSWebGLProgram对象下的同名变量
       
        if(LoadData() != 0) throw "error:LoadData()!";
       
        oJSWebGL.SetMouseCallback(OnMouseDown, OnMouseMove, OnMouseUp);
        oJSWebGL.SetRender(RenderScene, 300);
    }
    catch(e){alert(e);}
}
</script>
</head>
<body οnlοad='Init()'>
<p>在12章第二个例子的基础之上,我对代码作了一些整理,在gl.js文件中:<br>
1. 一些名称由CWebGL*改为CJSWebGL*。<br>
2. 添加类CJSWebGLBuffer。<br>
3. CJSWebGL类添加了一些函数以提供直观或便捷的操作。<br>
4. CJSWebGL类中,返回值为CWebGL*类型的函数的名称,添加JS_前缀。<br>
5. CJSWebGL类中,直接或间接使用CWebGL*类型数据的函数的名称,添加JS_前缀。<br>
6. 添加类CJSMat4,对glMatrix-0.9.5.js文件中的mat4类作了部分再封装,简化了一些矩阵操作。<br>
<br>
<canvas id="myCanvas" style="border:1px solid red;" width='600px' height='450px'></canvas><table>
<tr><td>光照控制:</td><td colspan=3><input type="checkbox" id="lighting" checked />启用光照</td></tr>
<tr><td>环境光(比例):</td>
            <td>R: <input type="text" id="ambientR" value="0.5"></td>
            <td>G: <input type="text" id="ambientG" value="0.5"></td>
            <td>B: <input type="text" id="ambientB" value="0.5"></td></tr>
<tr><td>点光源(比例):</td>
            <td>R: <input type="text" id="pointR" value="1.0"></td>
            <td>G: <input type="text" id="pointG" value="1.0"></td>
            <td>B: <input type="text" id="pointB" value="1.0"></td></tr>
</table><br>
<img id="myTexture1" src='cubeTexture1.bmp'>
<img id="myTexture2" src='cubeTexture2.bmp'>
<img id="myTexture3" src='cubeTexture3.bmp'><br>
<img id="myTexture4" src='cubeTexture4.bmp'>
<img id="myTexture5" src='cubeTexture5.bmp'>
<img id="myTexture6" src='cubeTexture6.bmp'>   
</body>
</html>

转载地址:http://prami.baihongyu.com/

你可能感兴趣的文章
Allowing Other Apps to Start Your Activity
查看>>
dev/mem
查看>>
pfn_valid 源码分析
查看>>
dev/kmem 和dev/mem的区别
查看>>
test-definitions/blob/master/auto-test/bigdata/bigdata.sh
查看>>
/test-definitions/blob/master/auto-test/blktrace/blktrace.sh
查看>>
test-definitions/blob/master/auto-test/blogbench/blogbench.sh
查看>>
test-definitions/blob/master/auto-test/boost/boost.sh
查看>>
Java多态性理解
查看>>
Intellij Idea 工具在java文件中怎么避免 import .*包,以及import包顺序的问题
查看>>
IDEA Properties中文unicode转码问题
查看>>
Oracle中Blob转换成Clob
查看>>
Linux如何查看so中函数名
查看>>
自动管理代码的android.mk
查看>>
cocos2dx 2.2.6编译记录(1)
查看>>
makefile学习网站
查看>>
C 编写lua模块(1)
查看>>
Lua教程:Lua调用C/C++函数(4)
查看>>
win下创建win32控制台工程,执行lua脚本
查看>>
cocos2dx android启动错误
查看>>