WebGL自学教程——WebGL示例:gl-0.1.js

 function ShaderSourceFromScript(scriptID)
{
    var shaderScript = document.getElementById(scriptID);
    if (shaderScript == null) return "";

    var sourceCode = "";
    var child = shaderScript.firstChild;
    while (child)
    {
        if (child.nodeType == child.TEXT_NODE ) sourceCode += child.textContent;
        child = child.nextSibling;
    }

    return sourceCode;
}


function JS_MultiplyMat4()//按照转换先后顺序填入各个矩阵
{
    if(arguments.length < 1)
    {
        alert("JS_MultiplyMat4:参数不足!");
        return null;
    }
    var v = mat4.create(arguments[0]);
    for(var i=1; i<arguments.length; ++i) mat4.multiply(arguments[i], v, v);
    return v;
}

function CJSMat4()
{
    //转换操作都是针对当前矩阵进行
    //假设转换顺序为旋转1,平移2,旋转3,其他矩阵4,投影5,则:
    //1. 如果这些矩阵已经计算好:
    //        var jsMat4 = new CJSMat4();
    //        jsMat4.Identity();
    //        jsMat4.Transform(旋转1,平移2,旋转3,其他矩阵4,投影5);
    //        ....uniformMatrix4fv(..., jsMat4.GetValue);
    //2. 其他矩阵4,投影5已经计算好:
    //        var jsMat4 = new CJSMat4();
    //        jsMat4.Identity();
    //        jsMat4.Rotate(dir_1, radians_1);
    //        jsMat4.Translate(v3_2);
    //        jsMat4.Rotate(dir_3, radians_3);
    //        jsMat4.Transform(其他矩阵4,投影5);
    //        ....uniformMatrix4fv(..., jsMat4.GetValue);
    //        注意,最后在着色器中,必须把本类计算出的结果矩阵放在左边相乘,如:u_m4ModelView * vec4(a_v3Position, 1.0)
    //如果某些函数的参数是4*4的矩阵,则可以同时接受js数组、mat4类型和CJSMat4类型。

    this.GetValue = function(){return this._value;}

    this.Identity = function(){return mat4.identity(this._value);}//将当前矩阵转换为单位矩阵

    this.SetValue = function(value){return mat4.set(this._GetMat4(value), this._value);}//当前值=value

    this.Transpose = function(){return mat4.transpose(this._value);}

    this.Determinant = function(){return mat4.determinant(this._value);}

    this.Inverse = function(){return mat4.inverse(this._value);}

    this.ToRotationMat = function(){return mat4.toRotationMat(this._value);}//不改变当前对象的值

    this.ToMat3 = function(){return mat4.toMat3(this._value);}//不改变当前对象的值

    this.ToInverseMat3 = function(){return mat4.toInverseMat3(this._value);}//不改变当前对象的值

    this.LeftMultiply = function(right){return mat4.multiply(this._value, this._GetMat4(right), this._value);}//当前值=当前值*right

    this.RightMultiply = function(left){return mat4.multiply(this._GetMat4(left), this._value, this._value);}//当前值=left*当前值

    this.MultiplyVec3 = function(v3){return mat4.multiplyVec3(this._value, v3, this._value);}//当前值=当前值*v3

    this.MultiplyVec4 = function(v4){return mat4.multiplyVec4(this._value, v4, this._value);}//当前值=当前值*v4

    this.Translate = function(v3)
    {
        var tm = mat4.create();mat4.identity(tm);
        mat4.translate(tm, v3, tm);
        return this.RightMultiply(tm);
    }

    this.Scale = function(v3){return mat4.scale(this._value, v3);}

    this.Rotate = function(dir, radians)
    {
        var tm = mat4.create();mat4.identity(tm);
        mat4.rotate(tm, dir, radians, tm);
        return this.RightMultiply(tm);       
    }
    this.RotateX = function(radians)
    {
        var tm = mat4.create();mat4.identity(tm);
        mat4.rotateX(tm, radians, tm);
        return this.RightMultiply(tm);
    }
    this.RotateY = function(radians)
    {
        var tm = mat4.create();mat4.identity(tm);
        mat4.rotateY(tm, radians, tm);
        return this.RightMultiply(tm);
    }
    this.RotateZ = function(radians)
    {
        var tm = mat4.create();mat4.identity(tm);
        mat4.rotateZ(tm, radians, tm);
        return this.RightMultiply(tm);
    }

    this.Transform = function()//按照转换先后顺序填入各个矩阵
    {
        for(var i=0; i<arguments.length; ++i) this.RightMultiply(this._GetMat4(arguments[i]));
        return this._value;
    }

    this.ToString = function(){return mat4.str(this._value);}//不改变当前对象的值

    this._value = mat4.create();
    this._GetMat4 = function(v)
    {
        if(v.constructor == CJSMat4) return v.GetValue();
        else return v;
    }
}


function CJSWebGLProgram(webgl, programObject, vertexShaderObject, fragmentShaderObject)
{
    this.programObject = programObject;
    this.vertexShaderObject = vertexShaderObject;
    this.fragmentShaderObject = fragmentShaderObject;
   
    this._webgl = webgl;
   
    this.BindAttribLocation = function(index, name){this._webgl.bindAttribLocation(this.programObject, index, name);}
    this.GetAttribLocation = function(name){return this._webgl.getAttribLocation(this.programObject, name);}
   
    this.GetUniformLocation = function(name){return this._webgl.getUniformLocation(this.programObject, name);}
    this.GetUniform = function(location){return this._webgl.getUniform(this.programObject, location);}
   
    this.LoadLocations = function()
    {
        var n = this._webgl.getProgramParameter(this.programObject, this._webgl.ACTIVE_ATTRIBUTES);
        for(var i=0; i<n; ++i)
        {
            var ai = this._webgl.getActiveAttrib(this.programObject, i);
            this[ai.name] = this.GetAttribLocation(ai.name);
        }
       
        n = this._webgl.getProgramParameter(this.programObject, this._webgl.ACTIVE_UNIFORMS);
        for(var i=0; i<n; ++i)
        {
            var ai = this._webgl.getActiveUniform(this.programObject, i);
            this[ai.name] = this.GetUniformLocation (ai.name);
        }
    }
}
function CJSWebGLBuffer(bufferName, target, usage, size, type, normalized, buffer)
{
    this.bufferName= bufferName;
    this.target = target;
    this.usage = usage;
    this.size = size;
    this.type = type;
    this.normalized = normalized;
    this.buffer = buffer;
}
function CJSWebGL(canvasId)
{
    this.canvas = document.getElementById(canvasId);
    this.webgl = null;
   
    this.error = '';
   
    this.buffers = {};
    this.jsBuffers = {};
   
    this.JS_UseProgram = function(oJSWebGLProgram)
    {
        this._oJSWebGLProgram = oJSWebGLProgram ;
        this.webgl.useProgram(oJSWebGLProgram.programObject);
    }
    this.Viewport = function(){return [this.canvas.clientWidth, this.canvas.clientHeight];}
   
    this.Init = function()
    {
        try
        {
            if(this.canvas == null) throw "error:canvasId";
            this.webgl = this.canvas.getContext("experimental-webgl");
            this.webgl.viewport(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
            this._SetEvent(this.canvas, "onresize", this._OnResize);           

            return true;
        }
        catch(e)
        {
            this.error = "Init:\r\n" + e;
            return false;
        }
    }
   
    this.SetupShaderObject = function(program, type, scriptId)//return WebGLShader
    {
        var shaderObject = this.webgl.createShader(type);
        this.webgl.shaderSource(shaderObject , ShaderSourceFromScript(scriptId));
        this.webgl.compileShader(shaderObject );
        if(!this.webgl.getShaderParameter(shaderObject , this.webgl.COMPILE_STATUS))
        {
            this.error = this.webgl.getShaderInfoLog(shaderObject);
            this.webgl.deleteShader(shaderObject);
            return null;
        }
        if(program) this.webgl.attachShader(program, shaderObject);
        return shaderObject;
    }
    this.JS_SetupProgramObject = function(vertexShaderScriptId, fragmentShaderScriptId, useProgram)//return CJSWebGLProgram
    {
        var program = new CJSWebGLProgram(this.webgl, null, null, null);
        try
        {
            program.programObject = this.webgl.createProgram();
            program.vertexShaderObject = this.SetupShaderObject(program.programObject, this.webgl.VERTEX_SHADER, vertexShaderScriptId);
            if(program.vertexShaderObject == null) throw "vertexShader("+vertexShaderScriptId+"):\r\n" + this.error;
            program.fragmentShaderObject = this.SetupShaderObject(program.programObject, this.webgl.FRAGMENT_SHADER, fragmentShaderScriptId);
            if(program.fragmentShaderObject == null) throw "fragmentShader("+fragmentShaderScriptId+"):\r\n" + this.error;
            this.webgl.linkProgram(program.programObject);
            if(!this.webgl.getProgramParameter(program.programObject, this.webgl.LINK_STATUS)) throw this.webgl.getProgramInfoLog(program.programObject);
            if(useProgram) this.JS_UseProgram(program);
            program.LoadLocations();
            return program;

        }
        catch(e)
        {
            this.error = "SetupProgramObject:\r\n" + e;
            if(program.vertexShaderObject) this.webgl.deleteShader(program.vertexShaderObject);program.vertexShaderObject = null;
            if(program.fragmentShaderObject) this.webgl.deleteShader(program.fragmentShaderObject);program.fragmentShaderObject = null;
            if(program.programObject) this.webgl.deleteProgram(program.programObject);program.programObject = null;
            program = null;
            return null;
        }
    }
   
    this.SetupBuffer = function(target, typedArray, usage)//return WebGLBuffer
    {
        var buffer = this.webgl.createBuffer();
        this.webgl.bindBuffer(target, buffer);
        this.webgl.bufferData(target, typedArray, usage);
        return buffer;
    }
    this.SetupArrayBuffer = function(typedArray, usage)//return WebGLBuffer
    {
        return this.SetupBuffer(this.webgl.ARRAY_BUFFER, typedArray, usage);
    }
    this.SetupElementArrayBuffer = function(typedArray, usage)//return WebGLBuffer
    {
        return this.SetupBuffer(this.webgl.ELEMENT_ARRAY_BUFFER, typedArray, usage);
    }
   
    this.LoadBuffer = function(bufferName, target, typedArray, usage)//return WebGLBuffer,通过CJSWebGL.buffers[bufferName]进行访问
    {
        var buffer = this.SetupBuffer(target, typedArray, usage);
        this.buffers[bufferName] = buffer;
        return buffer;
    }
    this.LoadArrayBuffer = function(bufferName, typedArray, usage)//return WebGLBuffer,通过CJSWebGL.buffers[bufferName]进行访问
    {
        return this.LoadBuffer(bufferName, this.webgl.ARRAY_BUFFER, typedArray, usage);
    }
    this.LoadElementArrayBuffer = function(bufferName, typedArray, usage)//return WebGLBuffer,通过CJSWebGL.buffers[bufferName]进行访问
    {
        return this.LoadBuffer(bufferName, this.webgl.ELEMENT_ARRAY_BUFFER, typedArray, usage);
    }   
   
    this.JS_LoadBuffer = function(bufferName, target, typedArray, usage, size, type, normalized)//return CJSWebGLBuffer,通过CJSWebGL.jsBuffers[bufferName]进行访问
    {
        var buffer = this.SetupBuffer(target, typedArray, usage);
        var oJSWebGLBuffer = new CJSWebGLBuffer(bufferName, target, usage, size, type, normalized, buffer);
        this.jsBuffers[bufferName] = oJSWebGLBuffer;
        return oJSWebGLBuffer;
    }
    this.JS_LoadArrayBuffer = function(bufferName, typedArray, usage, size, type, normalized)//return CJSWebGLBuffer,通过CJSWebGL.jsBuffers[bufferName]进行访问
    {
        return this.JS_LoadBuffer(bufferName, this.webgl.ARRAY_BUFFER, typedArray, usage, size, type, normalized);
    }
    this.JS_LoadElementArrayBuffer = function(bufferName, typedArray, usage, size, type, normalized)//return CJSWebGLBuffer,通过CJSWebGL.jsBuffers[bufferName]进行访问
    {
        return this.JS_LoadBuffer(bufferName, this.webgl.ELEMENT_ARRAY_BUFFER, typedArray, usage, size, type, normalized);
    }
   
    this.BindTextureUnit = function(unit, target, textureObject)//绑定纹理单元和纹理对象,看起来直观些
    {
        this.webgl.activeTexture(unit);
        this.webgl.bindTexture(target, textureObject);
    }

    this.JS_SetCurrentBuffer = function(jsBufferName)
    {
        var oJSWebBuffer = this.jsBuffers[jsBufferName];
        this.webgl.bindBuffer(oJSWebBuffer.target, oJSWebBuffer.buffer);
    }
    this.JS_VertexAttribPointer = function(location, jsBufferName, stride, offset)
    {
        var oJSWebBuffer = this.jsBuffers[jsBufferName];
        this.webgl.bindBuffer(oJSWebBuffer.target, oJSWebBuffer.buffer);
        this.webgl.vertexAttribPointer(location, oJSWebBuffer.size, oJSWebBuffer.type, oJSWebBuffer.normalized, stride, offset);   
    }

   
   
    this.SetRender = function(onrender, interval)
    {
        if(this._interval)
        {
            window.clearInterval(this._interval);
            this._interval = null;
        }
        if(onrender && interval && onrender != '')
        {
            this._eventOnRender = onrender;
            window[this._id] = this;
            this._interval = window.setInterval("CJSWebGL_OnTimer('"+this._id+"')", interval);
        }
    }
    this.SetMouseCallback = function(down, move, up)
    {
        this._SetEvent(this.canvas, "onmousedown", down);
        this._SetEvent(this.canvas, "onmousemove", move);
        this._SetEvent(this.canvas, "onmouseup", up);
    }
    this.SetKeyboardCallback = function(down, up)
    {
        this._SetEvent(document, "onkeydown", down);
        this._SetEvent(document, "onkeyup", up);
    }
   
   
   
    //this._eventOnMouseDown = null;    //function(event)
    //this._eventOnMouseMove = null;    //function(event)
    //this._eventOnMouseUp = null;      //function(event)
    //this._eventOnKeyDown = null;      //function(event)
    //this._eventOnKeyUp = null;        //function(event)
    this._eventOnResized = null;        //function(webgl, w, h),注:webgl的视见区已被更新
    //this._eventOnLoad = null;         //function(webgl, oJSWebGLProgram)
    this._eventOnRender = null;         //function(webgl, oJSWebGLProgram)
   
    this._oJSWebGLProgram = null;
    this._interval = null;
    this._id = CJSWebGL_NewID();
    this._OnResize = function(e)
    {
        this.webgl.viewport(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
        if(this._eventOnResized) this._eventOnResized(this.webgl, this.canvas.clientWidth, this.canvas.clientHeight);
    }
    this._SetEvent = function(obj, e, handler)
    {
        obj[e] = handler;
    }
}
var gJSWebGL_ID = 0;
function CJSWebGL_NewID()
{
    ++gJSWebGL_ID;
    return "CJSWebGL_ID_"+gJSWebGL_ID;
}
function CJSWebGL_OnTimer(id)
{
    var oJSWebGL = window[id];
    if(oJSWebGL) oJSWebGL._eventOnRender(oJSWebGL.webgl, oJSWebGL._oJSWebGLProgram);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值