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