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.
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@36
    68
    this.textureCoord = gl.getAttribLocation(this.program, "aTextureCoord");
sawine@36
    69
    gl.enableVertexAttribArray(this.textureCoord);
sawine@36
    70
sawine@24
    71
    this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
sawine@24
    72
    this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");    
sawine@24
    73
    this.nMatrixUniform = gl.getUniformLocation(this.program, "uNMatrix");
sawine@36
    74
    this.samplerUniform = gl.getUniformLocation(this.program, "uSampler");
sawine@33
    75
    this.materialShininessUniform = gl.getUniformLocation(this.program, "uMaterialShininess");
sawine@24
    76
    this.useLightingUniform = gl.getUniformLocation(this.program, "uUseLighting");
sawine@36
    77
    this.useTexture = gl.getUniformLocation(this.program, "uUseTexture");
sawine@24
    78
    this.ambientColourUniform = gl.getUniformLocation(this.program, "uAmbientColour");
sawine@24
    79
    this.lightingDirectionUniform = gl.getUniformLocation(this.program, "uLightingDirection");
sawine@24
    80
    this.directionalColourUniform = gl.getUniformLocation(this.program, "uDirectionalColour");
sawine@30
    81
    this.pointLightingLocationUniform = gl.getUniformLocation(this.program, "uPointLightingLocation");
sawine@33
    82
    this.pointLightingSpecularColourUniform = gl.getUniformLocation(this.program, "uPointLightingSpecularColour");
sawine@33
    83
    this.pointLightingDiffuseColourUniform = gl.getUniformLocation(this.program, "uPointLightingDiffuseColour");
sawine@24
    84
    
sawine@24
    85
    function loadShader(gl, id)
sawine@24
    86
    {
sawine@24
    87
	var script = document.getElementById(id);
sawine@24
    88
	if (!script) return null;
sawine@24
    89
	
sawine@24
    90
	var str = "";
sawine@24
    91
	var child = script.firstChild;
sawine@24
    92
	while (child)
sawine@24
    93
	{
sawine@24
    94
	    if (child.nodeType == 3) str += child.textContent;
sawine@24
    95
	    child = child.nextSibling;
sawine@24
    96
	}
sawine@24
    97
	
sawine@24
    98
	var shader;
sawine@24
    99
	var common = "x-shader/x-";
sawine@24
   100
	if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
sawine@24
   101
	else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
sawine@24
   102
	else return null;
sawine@24
   103
sawine@24
   104
	gl.shaderSource(shader, str);
sawine@24
   105
	gl.compileShader(shader);
sawine@24
   106
sawine@24
   107
	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
sawine@24
   108
        {
sawine@24
   109
	    alert(gl.getShaderInfoLog(shader));
sawine@24
   110
	    return null;
sawine@24
   111
	}
sawine@24
   112
sawine@24
   113
	return shader;
sawine@24
   114
    }
sawine@24
   115
}
sawine@24
   116
sawine@24
   117
function Renderer(camera, context)
sawine@24
   118
{
sawine@24
   119
    this.camera = camera;
sawine@24
   120
    this.context = context;
sawine@24
   121
    this.gl = context.gl;
sawine@24
   122
    this.matrixStack = [];
sawine@24
   123
}
sawine@24
   124
Renderer.prototype.update = function(scene)
sawine@24
   125
{ 
sawine@31
   126
    var gl = this.context.gl; 
sawine@31
   127
    var shader = this.context.shader;
sawine@24
   128
    var viewport = this.context.viewport;
sawine@24
   129
    var mvMatrix = this.context.mvMatrix;
sawine@24
   130
    var pMatrix = this.context.pMatrix;
sawine@24
   131
    var camera = this.camera;
sawine@24
   132
sawine@24
   133
    gl.viewport(0, 0, viewport.width, viewport.height);
sawine@24
   134
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
sawine@34
   135
    mat4.perspective(45, viewport.width / viewport.height, 0.1, 1000.0, pMatrix);
sawine@24
   136
sawine@31
   137
    var lighting = true;
sawine@31
   138
    gl.uniform1i(shader.useLightingUniform, lighting);
sawine@35
   139
    gl.uniform1f(shader.materialShininessUniform, 20.0);
sawine@31
   140
   
sawine@31
   141
    if (lighting)
sawine@31
   142
    {   
sawine@31
   143
	var uni = 0.0;
sawine@31
   144
	gl.uniform3f(shader.ambientColourUniform, uni, uni, uni);
sawine@31
   145
sawine@31
   146
	var pos = [0, 0, 0];
sawine@31
   147
	gl.uniform3f(shader.pointLightingLocationUniform, pos[0], pos[1], pos[2]);
sawine@35
   148
	uni = 1.0;
sawine@33
   149
	gl.uniform3f(shader.pointLightingSpecularColourUniform, uni, uni, uni);
sawine@38
   150
	uni = .07;
sawine@33
   151
	gl.uniform3f(shader.pointLightingDiffuseColourUniform, uni, uni, uni);
sawine@31
   152
sawine@31
   153
	// var lightingDir = vec3.create();
sawine@31
   154
	// vec3.add(lightingDir, [0.5, -0.5, 0.0]);
sawine@31
   155
	// vec3.normalize(lightingDir);
sawine@31
   156
	// vec3.scale(lightingDir, -1);     
sawine@31
   157
	// gl.uniform3fv(shader.lightingDirectionUniform, lightingDir);
sawine@31
   158
	
sawine@31
   159
	// uni = 0.9;
sawine@31
   160
	// var directional =  {"r": uni, "g": uni, "b": uni};
sawine@31
   161
	// gl.uniform3f(shader.directionalColourUniform, directional.r, directional.g, directional.b);
sawine@31
   162
    }
sawine@31
   163
sawine@24
   164
    mat4.identity(mvMatrix);
sawine@27
   165
    mat4.multiply(mvMatrix, camera.matrix); 
sawine@28
   166
    
sawine@28
   167
    this.draw(scene);
sawine@28
   168
    if (this.next) this.next.update(scene);
sawine@28
   169
}
sawine@28
   170
Renderer.prototype.draw = function(node)
sawine@28
   171
{
sawine@28
   172
    var gl = this.context.gl;
sawine@28
   173
    var shader = this.context.shader;
sawine@28
   174
    var mvMatrix = this.context.mvMatrix;
sawine@28
   175
    var pMatrix = this.context.pMatrix;
sawine@28
   176
   
sawine@28
   177
    if (node)
sawine@28
   178
    {
sawine@28
   179
	this.pushMatrix(mvMatrix);
sawine@28
   180
	mat4.translate(mvMatrix, node.pos);
sawine@28
   181
	//mat4.rotate(mvMatrix, node.rot);
sawine@28
   182
	//mat4.multiply(mvMatrix, node.matrix);
sawine@35
   183
	var geometry = node.geometry;
sawine@35
   184
	if (geometry)
sawine@28
   185
	{
sawine@35
   186
	    var object = geometry.vbo;
sawine@28
   187
	    gl.bindBuffer(gl.ARRAY_BUFFER, object.positionBuffer);
sawine@28
   188
	    gl.vertexAttribPointer(shader.vertexPosition, object.positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
sawine@28
   189
    
sawine@28
   190
	    gl.bindBuffer(gl.ARRAY_BUFFER, object.normalBuffer);
sawine@28
   191
	    gl.vertexAttribPointer(shader.vertexNormal, object.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
sawine@24
   192
sawine@36
   193
	    gl.bindBuffer(gl.ARRAY_BUFFER, object.textureCoordBuffer);
sawine@36
   194
	    gl.vertexAttribPointer(shader.textureCoord, object.textureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
sawine@36
   195
	    gl.activeTexture(gl.TEXTURE0);
sawine@36
   196
	    if (object.texture && object.useTexture)
sawine@36
   197
	    {
sawine@36
   198
		gl.uniform1i(shader.useTexture, true);
sawine@36
   199
		
sawine@36
   200
		gl.bindTexture(gl.TEXTURE_2D, object.texture.hnd);
sawine@36
   201
		gl.uniform1i(shader.samplerUniform, 0);
sawine@36
   202
	    }
sawine@36
   203
	    else
sawine@36
   204
	    {
sawine@36
   205
		gl.uniform1i(shader.useTexture, false);
sawine@36
   206
		
sawine@36
   207
	    }
sawine@28
   208
	    gl.bindBuffer(gl.ARRAY_BUFFER, object.colourBuffer);
sawine@28
   209
	    gl.vertexAttribPointer(shader.vertexColour, object.colourBuffer.itemSize, gl.FLOAT, false, 0, 0);
sawine@28
   210
   
sawine@28
   211
	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.indexBuffer);
sawine@28
   212
	    this.context.updateMatrixUniforms();
sawine@28
   213
	    gl.drawElements(gl.TRIANGLES, object.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
sawine@28
   214
	    //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems);
sawine@28
   215
	}
sawine@24
   216
    
sawine@28
   217
	for (var id in node.children)
sawine@28
   218
	{
sawine@28
   219
	    this.mvMatrix = mvMatrix;
sawine@28
   220
	    this.draw(node.children[id]);
sawine@28
   221
	}
sawine@29
   222
	this.context.mvMatrix = this.popMatrix();
sawine@24
   223
    }
sawine@24
   224
}
sawine@24
   225
Renderer.prototype.pushMatrix = function(matrix)
sawine@24
   226
{
sawine@24
   227
    var copy = mat4.create();
sawine@24
   228
    mat4.set(matrix, copy);
sawine@24
   229
    this.matrixStack.push(copy);
sawine@24
   230
}
sawine@24
   231
Renderer.prototype.popMatrix = function()    
sawine@24
   232
{
sawine@24
   233
    if (this.matrixStack.length > 0) return this.matrixStack.pop();
sawine@24
   234
}