scripts/renderer.js
author Eugen Sawin <sawine@me73.com>
Sat, 30 Apr 2011 04:32:22 +0200
changeset 38 ce3efaacb700
parent 36 a828c4cde5b3
permissions -rw-r--r--
Added test texture.
     1 function Context(canvas)
     2 {
     3     this.canvas = canvas;
     4     try 
     5     {
     6 	this.gl = canvas.getContext("experimental-webgl");
     7 	this.viewport = {'width': canvas.width,
     8 			 'height': canvas.height};
     9     } 
    10     catch(e) 
    11     {
    12 	alert(e);
    13     }
    14     if (!this.gl) alert("Failed: WebGL init.");
    15     this.mvMatrix = mat4.create();
    16     this.pMatrix = mat4.create();
    17     this.shader = new Shader(this);  
    18 }
    19 Context.prototype.updateMatrixUniforms = function()
    20 {
    21     var gl = this.gl;
    22     var program = this.shader;
    23     var pMatrix = this.pMatrix;
    24     var mvMatrix = this.mvMatrix;
    25 
    26     gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix);
    27     gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix);
    28     var normalMatrix = mat3.create();
    29     mat4.toInverseMat3(mvMatrix, normalMatrix);
    30     mat3.transpose(normalMatrix);
    31     gl.uniformMatrix3fv(program.nMatrixUniform, false, normalMatrix);
    32 }
    33 Context.prototype.expand = function()
    34 { 
    35     var width = window.innerWidth;
    36     var height = window.innerHeight;
    37     this.canvas.width = width;
    38     this.canvas.height = height;
    39     this.viewport.width = width;
    40     this.viewport.height = height;
    41 }
    42 
    43 function Shader(context)
    44 {
    45     var gl = context.gl;
    46     var fragment = loadShader(gl, "fragment-shader");
    47     var vertex = loadShader(gl, "vertex-shader");
    48     this.program = gl.createProgram();
    49     gl.attachShader(this.program, vertex);
    50     gl.attachShader(this.program, fragment);
    51     gl.linkProgram(this.program);
    52 
    53     if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
    54     {
    55 	alert("Failed: Shader init.");
    56     }
    57 
    58     gl.useProgram(this.program);
    59     this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
    60     gl.enableVertexAttribArray(this.vertexPosition);
    61 
    62     this.vertexNormal = gl.getAttribLocation(this.program, "aVertexNormal");
    63     gl.enableVertexAttribArray(this.vertexNormal);
    64     
    65     this.vertexColour = gl.getAttribLocation(this.program, "aVertexColour");
    66     gl.enableVertexAttribArray(this.vertexColour);    
    67 
    68     this.textureCoord = gl.getAttribLocation(this.program, "aTextureCoord");
    69     gl.enableVertexAttribArray(this.textureCoord);
    70 
    71     this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
    72     this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");    
    73     this.nMatrixUniform = gl.getUniformLocation(this.program, "uNMatrix");
    74     this.samplerUniform = gl.getUniformLocation(this.program, "uSampler");
    75     this.materialShininessUniform = gl.getUniformLocation(this.program, "uMaterialShininess");
    76     this.useLightingUniform = gl.getUniformLocation(this.program, "uUseLighting");
    77     this.useTexture = gl.getUniformLocation(this.program, "uUseTexture");
    78     this.ambientColourUniform = gl.getUniformLocation(this.program, "uAmbientColour");
    79     this.lightingDirectionUniform = gl.getUniformLocation(this.program, "uLightingDirection");
    80     this.directionalColourUniform = gl.getUniformLocation(this.program, "uDirectionalColour");
    81     this.pointLightingLocationUniform = gl.getUniformLocation(this.program, "uPointLightingLocation");
    82     this.pointLightingSpecularColourUniform = gl.getUniformLocation(this.program, "uPointLightingSpecularColour");
    83     this.pointLightingDiffuseColourUniform = gl.getUniformLocation(this.program, "uPointLightingDiffuseColour");
    84     
    85     function loadShader(gl, id)
    86     {
    87 	var script = document.getElementById(id);
    88 	if (!script) return null;
    89 	
    90 	var str = "";
    91 	var child = script.firstChild;
    92 	while (child)
    93 	{
    94 	    if (child.nodeType == 3) str += child.textContent;
    95 	    child = child.nextSibling;
    96 	}
    97 	
    98 	var shader;
    99 	var common = "x-shader/x-";
   100 	if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
   101 	else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
   102 	else return null;
   103 
   104 	gl.shaderSource(shader, str);
   105 	gl.compileShader(shader);
   106 
   107 	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
   108         {
   109 	    alert(gl.getShaderInfoLog(shader));
   110 	    return null;
   111 	}
   112 
   113 	return shader;
   114     }
   115 }
   116 
   117 function Renderer(camera, context)
   118 {
   119     this.camera = camera;
   120     this.context = context;
   121     this.gl = context.gl;
   122     this.matrixStack = [];
   123 }
   124 Renderer.prototype.update = function(scene)
   125 { 
   126     var gl = this.context.gl; 
   127     var shader = this.context.shader;
   128     var viewport = this.context.viewport;
   129     var mvMatrix = this.context.mvMatrix;
   130     var pMatrix = this.context.pMatrix;
   131     var camera = this.camera;
   132 
   133     gl.viewport(0, 0, viewport.width, viewport.height);
   134     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
   135     mat4.perspective(45, viewport.width / viewport.height, 0.1, 1000.0, pMatrix);
   136 
   137     var lighting = true;
   138     gl.uniform1i(shader.useLightingUniform, lighting);
   139     gl.uniform1f(shader.materialShininessUniform, 20.0);
   140    
   141     if (lighting)
   142     {   
   143 	var uni = 0.0;
   144 	gl.uniform3f(shader.ambientColourUniform, uni, uni, uni);
   145 
   146 	var pos = [0, 0, 0];
   147 	gl.uniform3f(shader.pointLightingLocationUniform, pos[0], pos[1], pos[2]);
   148 	uni = 1.0;
   149 	gl.uniform3f(shader.pointLightingSpecularColourUniform, uni, uni, uni);
   150 	uni = .07;
   151 	gl.uniform3f(shader.pointLightingDiffuseColourUniform, uni, uni, uni);
   152 
   153 	// var lightingDir = vec3.create();
   154 	// vec3.add(lightingDir, [0.5, -0.5, 0.0]);
   155 	// vec3.normalize(lightingDir);
   156 	// vec3.scale(lightingDir, -1);     
   157 	// gl.uniform3fv(shader.lightingDirectionUniform, lightingDir);
   158 	
   159 	// uni = 0.9;
   160 	// var directional =  {"r": uni, "g": uni, "b": uni};
   161 	// gl.uniform3f(shader.directionalColourUniform, directional.r, directional.g, directional.b);
   162     }
   163 
   164     mat4.identity(mvMatrix);
   165     mat4.multiply(mvMatrix, camera.matrix); 
   166     
   167     this.draw(scene);
   168     if (this.next) this.next.update(scene);
   169 }
   170 Renderer.prototype.draw = function(node)
   171 {
   172     var gl = this.context.gl;
   173     var shader = this.context.shader;
   174     var mvMatrix = this.context.mvMatrix;
   175     var pMatrix = this.context.pMatrix;
   176    
   177     if (node)
   178     {
   179 	this.pushMatrix(mvMatrix);
   180 	mat4.translate(mvMatrix, node.pos);
   181 	//mat4.rotate(mvMatrix, node.rot);
   182 	//mat4.multiply(mvMatrix, node.matrix);
   183 	var geometry = node.geometry;
   184 	if (geometry)
   185 	{
   186 	    var object = geometry.vbo;
   187 	    gl.bindBuffer(gl.ARRAY_BUFFER, object.positionBuffer);
   188 	    gl.vertexAttribPointer(shader.vertexPosition, object.positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
   189     
   190 	    gl.bindBuffer(gl.ARRAY_BUFFER, object.normalBuffer);
   191 	    gl.vertexAttribPointer(shader.vertexNormal, object.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
   192 
   193 	    gl.bindBuffer(gl.ARRAY_BUFFER, object.textureCoordBuffer);
   194 	    gl.vertexAttribPointer(shader.textureCoord, object.textureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
   195 	    gl.activeTexture(gl.TEXTURE0);
   196 	    if (object.texture && object.useTexture)
   197 	    {
   198 		gl.uniform1i(shader.useTexture, true);
   199 		
   200 		gl.bindTexture(gl.TEXTURE_2D, object.texture.hnd);
   201 		gl.uniform1i(shader.samplerUniform, 0);
   202 	    }
   203 	    else
   204 	    {
   205 		gl.uniform1i(shader.useTexture, false);
   206 		
   207 	    }
   208 	    gl.bindBuffer(gl.ARRAY_BUFFER, object.colourBuffer);
   209 	    gl.vertexAttribPointer(shader.vertexColour, object.colourBuffer.itemSize, gl.FLOAT, false, 0, 0);
   210    
   211 	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.indexBuffer);
   212 	    this.context.updateMatrixUniforms();
   213 	    gl.drawElements(gl.TRIANGLES, object.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
   214 	    //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems);
   215 	}
   216     
   217 	for (var id in node.children)
   218 	{
   219 	    this.mvMatrix = mvMatrix;
   220 	    this.draw(node.children[id]);
   221 	}
   222 	this.context.mvMatrix = this.popMatrix();
   223     }
   224 }
   225 Renderer.prototype.pushMatrix = function(matrix)
   226 {
   227     var copy = mat4.create();
   228     mat4.set(matrix, copy);
   229     this.matrixStack.push(copy);
   230 }
   231 Renderer.prototype.popMatrix = function()    
   232 {
   233     if (this.matrixStack.length > 0) return this.matrixStack.pop();
   234 }