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

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

<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 type="text/javascript" src="loadData.js"></script><!--加载数据的代码移动到了这个js文件中-->

<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);
    else if(u_iShadowMode == 4) gl_FragColor = vec4(0.0, 0.5, 0.5, 1.0);
}
</script>

<script>

var mouseDown = false;

var mousePosition = [0, 0];
var rotateMat4 = null;
var rotatePosV3 =  [0, 0, 0];;//记录离圆心的偏移,2D,弄成vec3只是为了方便执行加减操作

var textureObject = null;

var shadowMat4 = null;//预先计算好的阴影矩阵
var jsConeMat4 = null;
var perspectiveMat4 = null;//预先计算好的投影矩阵

function LoadData()

{
    LoadCubeData("cube", "cubeIndex", "cubeNormals");
 LoadTextureData();
 LoadShadowPlaneData("shadowPlane", "shadowMat4");
 LoadConeData("cone", "jsConeMat4");
 LoadPerspectiveMat4("perspectiveMat4");

    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.depthMask(true);
    webgl.disable(webgl.BLEND);
    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.enable(webgl.CULL_FACE);

    //画平面

    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.Scale([0.5, 0.5, 0.5]);
    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.depthMask(true);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 0);
    jsMatrix.Identity();
    jsMatrix.Scale([0.5, 0.5, 0.5]);
    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);
   
    //画大立方体,除了混合指令,其他基本上和画小立方体相同
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Position, "cube", 0, 0);
    oJSWebGL.JS_SetCurrentBuffer("cubeIndex");
    webgl.enableVertexAttribArray(oJSWebGLProgram.a_v3Position);
    webgl.disableVertexAttribArray(oJSWebGLProgram.a_v3Normal);
    webgl.enable(webgl.DEPTH_TEST);
    webgl.depthFunc(webgl.LEQUAL);
    webgl.depthMask(false);
    webgl.uniform1i(oJSWebGLProgram.u_iShadowMode, 4);
    jsMatrix.Identity();
    jsMatrix.Transform(rotateMat4, perspectiveMat4);
    webgl.uniformMatrix4fv(oJSWebGLProgram.u_m4ModelView, false, jsMatrix.GetValue());
    oJSWebGL.JS_VertexAttribPointer(oJSWebGLProgram.a_v3Normal, "cubeNormals", 0, 0);
    //设置混合
    webgl.enable(webgl.BLEND);//首先要启用混合
    webgl.blendEquation(webgl.FUNC_ADD);//相加
    webgl.blendFunc(webgl.SRC_COLOR, webgl.DST_COLOR);//源色和现有色的相加
    webgl.drawElements(webgl.TRIANGLES, 36, webgl.UNSIGNED_BYTE, 0);
}

//这些事件代码仍然只适合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>将加载数据的代码转到了loadData.js文件中。<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>

 

loadData.js文件的内容:

function LoadTriangleData(bufferName)

{
    var jsTriangleData = [
        0.0, 1.0, 0.0,//上顶点
        1.0, 0.0, 0.0,//右顶点
        -1.0, -1.0, 0.0];//左顶点
       
    oJSWebGL.JS_LoadArrayBuffer(bufferName, new Float32Array(jsTriangleData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);
}
function LoadCubeData(cubeBufferName, cubeIndexBufferName, cubeNormalsBufferName)
//"cube", "cubeIndex", "cubeNormals"
{
    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(cubeBufferName, new Float32Array(jsCubeData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);//加载之后,可以通过oJSWebGL.jsBuffers.cube进行访问

    var jsCubeIndex = [

            2, 1, 0,      3, 2, 0,    // Front face
            6, 5, 4,      7, 6, 4,    // Back face
            10, 9, 8,     11, 10, 8,  // Top face
            14, 13, 12,   15, 14, 12, // Bottom face
            18, 17, 16,   19, 18, 16, // Right face
            22, 21, 20,   23, 22, 20  // Left face
    ];
    oJSWebGL.JS_LoadElementArrayBuffer(cubeIndexBufferName, 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(cubeNormalsBufferName, new Float32Array(jsCubeNormals), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);//加载之后,可以通过oJSWebGL.jsBuffers.cubeNormals进行访问
}
function LoadTextureData()
{
    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'));
}
function LoadShadowPlaneData(bufferName, shadowMat4Name)
//"shadowPlane", "shadowMat4"
{
    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(bufferName, new Float32Array(jsShadowPlaneData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);
 
 eval(shadowMat4Name+" = mat4.create();");
    eval("gltMakeShadowMatrix([[-1, -1, 1], [1, -1, 1], [0, -0.25, -1]], [-1, 1, 0, 1], "+shadowMat4Name+");");
}
function LoadConeData(coneBufferName, jsConeMat4Name)
//"cone", "jsConeMat4"
{
    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(coneBufferName, new Float32Array(jsConeData), webgl.STATIC_DRAW, 3, webgl.FLOAT, false);
 
    eval(jsConeMat4Name+" = new CJSMat4();");
    eval(jsConeMat4Name+".Identity();");
    eval(jsConeMat4Name+".RotateX(Math.PI/2);");
    eval(jsConeMat4Name+".Translate([0, 0, 0.3]);");
}
function LoadPerspectiveMat4(mat4Name)//"perspectiveMat4"
{
    var lookAtMat4 = mat4.create();
    mat4.lookAt([0, 0, 1], [0,0,0], [0,1,0], lookAtMat4);
    eval(mat4Name+" = mat4.create();");
    var wh = oJSWebGL.Viewport();
    eval("mat4.perspective(60, wh[0]/wh[1], 0.1, 2, "+mat4Name+");");
    eval("mat4.multiply("+mat4Name+", lookAtMat4, "+mat4Name+");");
}

 

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

你可能感兴趣的文章
Sending the User to Another App
查看>>
kmsg_dump
查看>>
Getting a Result from an Activity
查看>>
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)
查看>>