Kaynağa Gözat

demo: updated webgl

mattias 6 yıl önce
ebeveyn
işleme
20be28d765

+ 320 - 320
demo/webgl/GLUtils.pas

@@ -1,463 +1,463 @@
 unit GLUtils;
 unit GLUtils;
 interface
 interface
 uses
 uses
-	MemoryBuffer, Mat4, GLTypes,
-	BrowserConsole, WebGL, JS,
-	Types, SysUtils;
+    MemoryBuffer, Mat4, GLTypes,
+    BrowserConsole, WebGL, JS,
+    Types, SysUtils;
 
 
 type
 type
-	TShader = class
-		public
-			constructor Create (context: TJSWebGLRenderingContext; vertexShaderSource, fragmentShaderSource: string);
-			procedure Compile;
-			procedure Link;
-			procedure Use;
+    TShader = class
+        public
+            constructor Create (context: TJSWebGLRenderingContext; vertexShaderSource, fragmentShaderSource: string);
+            procedure Compile;
+            procedure Link;
+            procedure Use;
 
 
-			function GetAttribLocation (name: string): GLint;
-			procedure BindAttribLocation (index: GLuint; name: string);
+            function GetAttribLocation (name: string): GLint;
+            procedure BindAttribLocation (index: GLuint; name: string);
 
 
-			procedure SetUniformMat4 (name: string; value: TMat4);
-			procedure SetUniformVec3 (name: string; value: TVec3);
-			procedure SetUniformFloat (name: string; value: GLfloat);
+            procedure SetUniformMat4 (name: string; value: TMat4);
+            procedure SetUniformVec3 (name: string; value: TVec3);
+            procedure SetUniformFloat (name: string; value: GLfloat);
 
 
-		private
-			gl: TJSWebGLRenderingContext;
-			vertexShader: TJSWebGLShader;
-			fragmentShader: TJSWebGLShader;
-			programID: TJSWebGLProgram;
+        private
+            gl: TJSWebGLRenderingContext;
+            vertexShader: TJSWebGLShader;
+            fragmentShader: TJSWebGLShader;
+            programID: TJSWebGLProgram;
 
 
-			function GetUniformLocation (name: string): TJSWebGLUniformLocation;
-			function CreateShader (theType: GLenum; source: string): TJSWebGLShader;
-	end;
+            function GetUniformLocation (name: string): TJSWebGLUniformLocation;
+            function CreateShader (theType: GLenum; source: string): TJSWebGLShader;
+    end;
 
 
 
 
 type
 type
-	TModelData = record
-		verticies: TJSFloat32Array;		// GLfloat
+    TModelData = record
+        verticies: TJSFloat32Array;     // GLfloat
 
 
-		// NOTE: it's not clear if WebGL supports GLuint
-		// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawElements
+        // NOTE: it's not clear if WebGL supports GLuint
+        // https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawElements
 
 
-		indicies: TJSUint16Array;			// GLushort
-		floatsPerVertex: integer;
-	end;
+        indicies: TJSUint16Array;           // GLushort
+        floatsPerVertex: integer;
+    end;
 
 
 const
 const
-	kModelVertexFloats = 3 + 2 + 3;
+    kModelVertexFloats = 3 + 2 + 3;
 type
 type
-	TModelVertex = record
-		pos: TVec3;
-		texCoord: TVec2;
-		normal: TVec3;
-	end;
+    TModelVertex = record
+        pos: TVec3;
+        texCoord: TVec2;
+        normal: TVec3;
+    end;
 
 
 procedure ModelVertexAddToBuffer(vertex: TModelVertex; buffer: TMemoryBuffer);
 procedure ModelVertexAddToBuffer(vertex: TModelVertex; buffer: TMemoryBuffer);
-procedure ModelVertexAddToArray (vertex: TModelVertex; list: TJSArray); 
+procedure ModelVertexAddToArray (vertex: TModelVertex; list: TJSArray);
 
 
 type
 type
-	TModel = class
-		public
-			constructor Create(context: TJSWebGLRenderingContext; modelData: TModelData); overload;
-			procedure Draw;
-		private
-			gl: TJSWebGLRenderingContext;
-			data: TModelData;
-			vertexBuffer: TJSWebGLBuffer;
-			indexBuffer: TJSWebGLBuffer;
-			//elementCount: integer;
-
-			procedure EnableAttributes;
-			procedure Load;
-	end;
+    TModel = class
+        public
+            constructor Create(context: TJSWebGLRenderingContext; modelData: TModelData); overload;
+            procedure Draw;
+        private
+            gl: TJSWebGLRenderingContext;
+            data: TModelData;
+            vertexBuffer: TJSWebGLBuffer;
+            indexBuffer: TJSWebGLBuffer;
+            //elementCount: integer;
+
+            procedure EnableAttributes;
+            procedure Load;
+    end;
 
 
 function LoadOBJFile (text: TJSString): TModelData;
 function LoadOBJFile (text: TJSString): TModelData;
 
 
-function GLSizeof(glType: NativeInt): integer; 
-procedure GLFatal (gl: TJSWebGLRenderingContext; messageString: string = 'Fatal OpenGL error'); 
+function GLSizeof(glType: NativeInt): integer;
+procedure GLFatal (gl: TJSWebGLRenderingContext; messageString: string = 'Fatal OpenGL error');
 
 
 implementation
 implementation
 
 
 {=============================================}
 {=============================================}
-{@! ___Utilities___ } 
+{@! ___Utilities___ }
 {=============================================}
 {=============================================}
 
 
 procedure Fatal (messageString: string); overload;
 procedure Fatal (messageString: string); overload;
 begin
 begin
-	writeln('*** FATAL: ', messageString);
-	raise Exception.Create('FATAL');
+    writeln('*** FATAL: ', messageString);
+    raise Exception.Create('FATAL');
 end;
 end;
 
 
 // TODO: toll free bridge to FPC strings
 // TODO: toll free bridge to FPC strings
 {procedure Fatal (messageString: TJSString); overload;
 {procedure Fatal (messageString: TJSString); overload;
 begin
 begin
-	writeln('*** FATAL: ', messageString);
-	raise Exception.Create('FATAL');
+    writeln('*** FATAL: ', messageString);
+    raise Exception.Create('FATAL');
 end;}
 end;}
 
 
-procedure GLFatal (gl: TJSWebGLRenderingContext; messageString: string = 'Fatal OpenGL error'); 
+procedure GLFatal (gl: TJSWebGLRenderingContext; messageString: string = 'Fatal OpenGL error');
 var
 var
-	error: integer;
+    error: integer;
 begin
 begin
-	error := gl.getError();
-	if error <> TJSWebGLRenderingContext.NO_ERROR then
-		begin
-			// TODO: case doesn't work?
-			case error of
-				TJSWebGLRenderingContext.INVALID_VALUE:
-					messageString := messageString+' (GL_INVALID_VALUE)';
-				TJSWebGLRenderingContext.INVALID_OPERATION:
-					messageString := messageString+' (GL_INVALID_OPERATION)';
-				TJSWebGLRenderingContext.INVALID_ENUM:
-					messageString := messageString+' (GL_INVALID_ENUM)';
-				otherwise
-					messageString := messageString+' '+IntToStr(error);
-			end;
-			Fatal(messageString);
-		end;
+    error := gl.getError();
+    if error <> TJSWebGLRenderingContext.NO_ERROR then
+        begin
+            // TODO: case doesn't work?
+            case error of
+                TJSWebGLRenderingContext.INVALID_VALUE:
+                    messageString := messageString+' (GL_INVALID_VALUE)';
+                TJSWebGLRenderingContext.INVALID_OPERATION:
+                    messageString := messageString+' (GL_INVALID_OPERATION)';
+                TJSWebGLRenderingContext.INVALID_ENUM:
+                    messageString := messageString+' (GL_INVALID_ENUM)';
+                otherwise
+                    messageString := messageString+' '+IntToStr(error);
+            end;
+            Fatal(messageString);
+        end;
 end;
 end;
 
 
-function GLSizeof(glType: NativeInt): integer; 
+function GLSizeof(glType: NativeInt): integer;
 begin
 begin
-	case glType of
-		TJSWebGLRenderingContext.UNSIGNED_BYTE, TJSWebGLRenderingContext.BYTE:
-			result := 1;
-		TJSWebGLRenderingContext.SHORT, TJSWebGLRenderingContext.UNSIGNED_SHORT:
-			result := 2;
-		TJSWebGLRenderingContext.INT, TJSWebGLRenderingContext.UNSIGNED_INT:
-			result := 4;
-		TJSWebGLRenderingContext.FLOAT:
-			result := 4;
-		otherwise
-			Fatal('GLSizeof type is invalid.');
-	end;
+    case glType of
+        TJSWebGLRenderingContext.UNSIGNED_BYTE, TJSWebGLRenderingContext.BYTE:
+            result := 1;
+        TJSWebGLRenderingContext.SHORT, TJSWebGLRenderingContext.UNSIGNED_SHORT:
+            result := 2;
+        TJSWebGLRenderingContext.INT, TJSWebGLRenderingContext.UNSIGNED_INT:
+            result := 4;
+        TJSWebGLRenderingContext.FLOAT:
+            result := 4;
+        otherwise
+            Fatal('GLSizeof type is invalid.');
+    end;
 end;
 end;
 
 
 {=============================================}
 {=============================================}
-{@! ___Model___ } 
+{@! ___Model___ }
 {=============================================}
 {=============================================}
 
 
 procedure ModelVertexAddToBuffer(vertex: TModelVertex; buffer: TMemoryBuffer);
 procedure ModelVertexAddToBuffer(vertex: TModelVertex; buffer: TMemoryBuffer);
 begin
 begin
-	buffer.AddFloats(kModelVertexFloats, [
-		vertex.pos.x, vertex.pos.y, vertex.pos.z,
-		vertex.texCoord.x, vertex.texCoord.y,
-		vertex.normal.x, vertex.normal.y, vertex.normal.z
-		]);
+    buffer.AddFloats(kModelVertexFloats, [
+        vertex.pos.x, vertex.pos.y, vertex.pos.z,
+        vertex.texCoord.x, vertex.texCoord.y,
+        vertex.normal.x, vertex.normal.y, vertex.normal.z
+        ]);
 end;
 end;
 
 
-procedure ModelVertexAddToArray (vertex: TModelVertex; list: TJSArray); 
+procedure ModelVertexAddToArray (vertex: TModelVertex; list: TJSArray);
 begin
 begin
-	list.push(vertex.pos.x);
-	list.push(vertex.pos.y);
-	list.push(vertex.pos.z);
-	list.push(vertex.texCoord.x);
-	list.push(vertex.texCoord.y);
-	list.push(vertex.normal.x);
-	list.push(vertex.normal.y);
-	list.push(vertex.normal.z);
+    list.push(vertex.pos.x);
+    list.push(vertex.pos.y);
+    list.push(vertex.pos.z);
+    list.push(vertex.texCoord.x);
+    list.push(vertex.texCoord.y);
+    list.push(vertex.normal.x);
+    list.push(vertex.normal.y);
+    list.push(vertex.normal.z);
 end;
 end;
 
 
 constructor TModel.Create(context: TJSWebGLRenderingContext; modelData: TModelData);
 constructor TModel.Create(context: TJSWebGLRenderingContext; modelData: TModelData);
 begin
 begin
-	gl := context;
-	data := modelData;
-	Load;
+    gl := context;
+    data := modelData;
+    Load;
 end;
 end;
 
 
 procedure TModel.Draw;
 procedure TModel.Draw;
 begin
 begin
-	gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
-	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
 
 
-	EnableAttributes;
-	gl.drawElements(gl.TRIANGLES, data.indicies.length, gl.UNSIGNED_SHORT, 0);
+    EnableAttributes;
+    gl.drawElements(gl.TRIANGLES, data.indicies.length, gl.UNSIGNED_SHORT, 0);
 
 
-	gl.bindBuffer(gl.ARRAY_BUFFER, nil);
-	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, nil);
+    gl.bindBuffer(gl.ARRAY_BUFFER, nil);
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, nil);
 end;
 end;
 
 
 procedure TModel.EnableAttributes;
 procedure TModel.EnableAttributes;
 var
 var
-	offset: integer;
-	stride: integer;
+    offset: integer;
+    stride: integer;
 begin
 begin
 
 
-	// NOTE: we don't have VAO's yet so we need to enable vertex attributes for shader
-	// before every draw call (unless the array buffer hasn't changed between calls)
-	offset := 0;  
-	stride := data.floatsPerVertex * GLSizeof(TJSWebGLRenderingContext.FLOAT);
-
-	// position
-	gl.enableVertexAttribArray(0);
-	gl.vertexAttribPointer(0, 3, gl.FLOAT, false, stride, offset);
-	offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 3;
-
-	// texture
-	gl.enableVertexAttribArray(1);
-	gl.vertexAttribPointer(1, 2, gl.FLOAT, false, stride, offset);
-	offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 2;
-
-	// normal
-	gl.enableVertexAttribArray(2);
-	gl.vertexAttribPointer(2, 3, gl.FLOAT, false, stride, offset);
-	offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 3;
+    // NOTE: we don't have VAO's yet so we need to enable vertex attributes for shader
+    // before every draw call (unless the array buffer hasn't changed between calls)
+    offset := 0;
+    stride := data.floatsPerVertex * GLSizeof(TJSWebGLRenderingContext.FLOAT);
+
+    // position
+    gl.enableVertexAttribArray(0);
+    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, stride, offset);
+    offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 3;
+
+    // texture
+    gl.enableVertexAttribArray(1);
+    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, stride, offset);
+    offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 2;
+
+    // normal
+    gl.enableVertexAttribArray(2);
+    gl.vertexAttribPointer(2, 3, gl.FLOAT, false, stride, offset);
+    offset += GLSizeof(TJSWebGLRenderingContext.FLOAT) * 3;
 end;
 end;
 
 
 procedure TModel.Load;
 procedure TModel.Load;
 begin
 begin
-	indexBuffer := gl.createBuffer;
-	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
-	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data.indicies, gl.STATIC_DRAW);	
-	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, nil);
+    indexBuffer := gl.createBuffer;
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data.indicies, gl.STATIC_DRAW);
+    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, nil);
 
 
-	vertexBuffer := gl.createBuffer;
-	gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+    vertexBuffer := gl.createBuffer;
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
   gl.bufferData(gl.ARRAY_BUFFER, data.verticies, gl.STATIC_DRAW);
   gl.bufferData(gl.ARRAY_BUFFER, data.verticies, gl.STATIC_DRAW);
-	gl.bindBuffer(gl.ARRAY_BUFFER, nil);
+    gl.bindBuffer(gl.ARRAY_BUFFER, nil);
 end;
 end;
 
 
 type
 type
-	TOBJVertex = record
-		position: TVec3;
-		textureIndex: integer;
-		normalIndex: integer;
-	end;
+    TOBJVertex = record
+        position: TVec3;
+        textureIndex: integer;
+        normalIndex: integer;
+    end;
 
 
 function ProcessFace (verticies: TJSArray; indices: TJSArray; face: TStringDynArray): TOBJVertex;
 function ProcessFace (verticies: TJSArray; indices: TJSArray; face: TStringDynArray): TOBJVertex;
 var
 var
-	index: integer;
-	vertex: TOBJVertex;
+  index: integer;
+  vertex: TOBJVertex;
 begin
 begin
-	index := StrToInt(face[0]) - 1;
+  index := StrToInt(face[0]) - 1;
 
 
-	vertex := TOBJVertex(verticies[index]);
+  vertex := TOBJVertex(verticies[index]);
 
 
-	// NOTE: see TOBJData
-	// index can't exceed GLushort
-	if index > 65536 then
-		Fatal('overflowed indices array');
+  // NOTE: see TOBJData
+  // index can't exceed GLushort
+  if index > 65536 then
+      Fatal('overflowed indices array');
 
 
-	if face[1] <> '' then
-		vertex.textureIndex := StrToInt(face[1]) - 1
-	else
-		vertex.textureIndex := -1;
+  if face[1] <> '' then
+      vertex.textureIndex := StrToInt(face[1]) - 1
+  else
+      vertex.textureIndex := -1;
 
 
-	if face[2] <> '' then
-		vertex.normalIndex := StrToInt(face[2]) - 1
-	else
-		vertex.normalIndex := -1;
+  if face[2] <> '' then
+      vertex.normalIndex := StrToInt(face[2]) - 1
+  else
+      vertex.normalIndex := -1;
 
 
-	indices.push(index);
-	
-	verticies[index] := vertex;
+  indices.push(index);
 
 
-	result := vertex;
+  verticies[index] := vertex;
+
+  result := vertex;
 end;
 end;
 
 
 function LoadOBJFile (text: TJSString): TModelData;
 function LoadOBJFile (text: TJSString): TModelData;
 const
 const
-	kLineEnding = #10;
-	kSpace = ' '; // what code is space?
+    kLineEnding = #10;
+    kSpace = ' '; // what code is space?
 var
 var
-	lines: TStringDynArray;
-	parts: TStringDynArray;
-	indices: TJSArray;
-	positions: TJSArray;
-	normals: TJSArray;
-	textures: TJSArray;
-	verticies: TJSArray;
-	mesh: TJSFloat32Array;
-
-	i: integer;
-	line: TJSString;
-	vertex: TOBJVertex;
-	vertexIndex: integer;
-	data: TModelData;
-
-	pos: TVec3;
-	texCoord: TVec2;
-	normal: TVec3;
+    lines: TStringDynArray;
+    parts: TStringDynArray;
+    indices: TJSArray;
+    positions: TJSArray;
+    normals: TJSArray;
+    textures: TJSArray;
+    verticies: TJSArray;
+    mesh: TJSFloat32Array;
+
+    i: integer;
+    line: TJSString;
+    vertex: TOBJVertex;
+    vertexIndex: integer;
+    data: TModelData;
+
+    pos: TVec3;
+    texCoord: TVec2;
+    normal: TVec3;
 begin
 begin
-	positions := TJSArray.new;
-	normals := TJSArray.new;
-	textures := TJSArray.new;
-	indices := TJSArray.new;
-	verticies := TJSArray.new;
-
-	lines := text.split(kLineEnding);
-
-	for i := 0 to high(lines) do
-		begin
-			line := TJSString(lines[i]);
-			parts := line.split(kSpace);
-
-			if line.startsWith('v ') then
-				begin
-					pos := V3(StrToFloat(parts[1]), StrToFloat(parts[2]), StrToFloat(parts[3]));
-					positions.push(pos);
-					
-					// add new vertex
-					vertex.position := pos;
-					vertex.textureIndex := -1;
-					vertex.normalIndex := -1;
-					verticies.push(pos);
-				end
-			else if line.startsWith('vn ') then
-				begin
-					normals.push(V3(StrToFloat(parts[1]), StrToFloat(parts[2]), StrToFloat(parts[3])));
-				end
-			else if line.startsWith('vt ') then
-				begin
-					textures.push(V2(StrToFloat(parts[1]), 1 - StrToFloat(parts[2])));
-				end
-			else if line.startsWith('f ') then
-				begin
-					ProcessFace(verticies, indices, TJSString(parts[1]).split('/'));
-					ProcessFace(verticies, indices, TJSString(parts[2]).split('/'));
-					ProcessFace(verticies, indices, TJSString(parts[3]).split('/'));
-				end;
-		end;
-	
-	// vec3 (position) + vec2 (texCoord) + vec3 (normal)
-	data.floatsPerVertex := kModelVertexFloats;
-
-	mesh := TJSFloat32Array.New(data.floatsPerVertex * verticies.length);
-
-	for i := 0 to verticies.length - 1 do
-		begin
-			vertex := TOBJVertex(verticies[i]);
-
-			vertexIndex := i * data.floatsPerVertex;
-
-			// position
-			pos := TVec3(positions[i]);
-			mesh[vertexIndex + 0] := pos.x;
-			mesh[vertexIndex + 1] := pos.y;
-			mesh[vertexIndex + 2] := pos.z;
-
-			// texture
-			if vertex.textureIndex <> -1 then
-				begin
-					texCoord := TVec2(textures[vertex.textureIndex]);
-					mesh[vertexIndex + 3] := texCoord.x;
-					mesh[vertexIndex + 4] := texCoord.y;
-				end
-			else
-				begin
-					mesh[vertexIndex + 3] := 0;
-					mesh[vertexIndex + 4] := 0;
-				end;
-			
-			// normal
-			if vertex.normalIndex <> -1 then
-				begin
-					normal := TVec3(normals[vertex.normalIndex]);
-					mesh[vertexIndex + 5] := normal.x;
-					mesh[vertexIndex + 6] := normal.y;
-					mesh[vertexIndex + 7] := normal.z;
-				end;
-		end;
-
-	//writeln('floats: ', mesh.length);
-	//writeln('positions:', positions.length);
-	//writeln('indices:', indices.length);
-
-	data.verticies := mesh;
-	data.indicies := TJSUint16Array.New(TJSObject(indices));
-
-	result := data;
+    positions := TJSArray.new;
+    normals := TJSArray.new;
+    textures := TJSArray.new;
+    indices := TJSArray.new;
+    verticies := TJSArray.new;
+
+    lines := text.split(kLineEnding);
+
+    for i := 0 to high(lines) do
+        begin
+            line := TJSString(lines[i]);
+            parts := line.split(kSpace);
+
+            if line.startsWith('v ') then
+                begin
+                    pos := V3(StrToFloat(parts[1]), StrToFloat(parts[2]), StrToFloat(parts[3]));
+                    positions.push(pos);
+
+                    // add new vertex
+                    vertex.position := pos;
+                    vertex.textureIndex := -1;
+                    vertex.normalIndex := -1;
+                    verticies.push(vertex);
+                end
+            else if line.startsWith('vn ') then
+                begin
+                    normals.push(V3(StrToFloat(parts[1]), StrToFloat(parts[2]), StrToFloat(parts[3])));
+                end
+            else if line.startsWith('vt ') then
+                begin
+                    textures.push(V2(StrToFloat(parts[1]), 1 - StrToFloat(parts[2])));
+                end
+            else if line.startsWith('f ') then
+                begin
+                    ProcessFace(verticies, indices, TJSString(parts[1]).split('/'));
+                    ProcessFace(verticies, indices, TJSString(parts[2]).split('/'));
+                    ProcessFace(verticies, indices, TJSString(parts[3]).split('/'));
+                end;
+        end;
+
+    // vec3 (position) + vec2 (texCoord) + vec3 (normal)
+    data.floatsPerVertex := kModelVertexFloats;
+
+    mesh := TJSFloat32Array.New(data.floatsPerVertex * verticies.length);
+
+    for i := 0 to verticies.length - 1 do
+        begin
+            vertex := TOBJVertex(verticies[i]);
+
+            vertexIndex := i * data.floatsPerVertex;
+
+            // position
+            pos := TVec3(positions[i]);
+            mesh[vertexIndex + 0] := pos.x;
+            mesh[vertexIndex + 1] := pos.y;
+            mesh[vertexIndex + 2] := pos.z;
+
+            // texture
+            if vertex.textureIndex <> -1 then
+                begin
+                    texCoord := TVec2(textures[vertex.textureIndex]);
+                    mesh[vertexIndex + 3] := texCoord.x;
+                    mesh[vertexIndex + 4] := texCoord.y;
+                end
+            else
+                begin
+                    mesh[vertexIndex + 3] := 0;
+                    mesh[vertexIndex + 4] := 0;
+                end;
+
+            // normal
+            if vertex.normalIndex <> -1 then
+                begin
+                    normal := TVec3(normals[vertex.normalIndex]);
+                    mesh[vertexIndex + 5] := normal.x;
+                    mesh[vertexIndex + 6] := normal.y;
+                    mesh[vertexIndex + 7] := normal.z;
+                end;
+        end;
+
+    //writeln('floats: ', mesh.length);
+    //writeln('positions:', positions.length);
+    //writeln('indices:', indices.length);
+
+    data.verticies := mesh;
+    data.indicies := TJSUint16Array.New(TJSObject(indices));
+
+    result := data;
 end;
 end;
 
 
 {=============================================}
 {=============================================}
-{@! ___Shader___ } 
+{@! ___Shader___ }
 {=============================================}
 {=============================================}
 function TShader.GetUniformLocation (name: string): TJSWebGLUniformLocation;
 function TShader.GetUniformLocation (name: string): TJSWebGLUniformLocation;
 begin
 begin
-	// TODO: cache these. how do we use dictionarys from JS in Pascal?
-	result := gl.getUniformLocation(programID, name);
-	GLFatal(gl, 'gl.getUniformLocation');
+    // TODO: cache these. how do we use dictionarys from JS in Pascal?
+    result := gl.getUniformLocation(programID, name);
+    GLFatal(gl, 'gl.getUniformLocation');
 end;
 end;
 
 
 procedure TShader.SetUniformFloat (name: string; value: GLfloat);
 procedure TShader.SetUniformFloat (name: string; value: GLfloat);
 begin
 begin
-	gl.uniform1f(GetUniformLocation(name), value);
-	GLFatal(gl, 'gl.uniform1f');
+    gl.uniform1f(GetUniformLocation(name), value);
+    GLFatal(gl, 'gl.uniform1f');
 end;
 end;
 
 
 procedure TShader.SetUniformVec3 (name: string; value: TVec3);
 procedure TShader.SetUniformVec3 (name: string; value: TVec3);
 begin
 begin
-	//gl.uniform3fv(GetUniformLocation(name), ToFloats(value));
-	gl.uniform3f(GetUniformLocation(name), value.x, value.y, value.z);
-	GLFatal(gl, 'gl.uniform3fv');
+    //gl.uniform3fv(GetUniformLocation(name), ToFloats(value));
+    gl.uniform3f(GetUniformLocation(name), value.x, value.y, value.z);
+    GLFatal(gl, 'gl.uniform3fv');
 end;
 end;
 
 
 procedure TShader.SetUniformMat4 (name: string; value: TMat4);
 procedure TShader.SetUniformMat4 (name: string; value: TMat4);
 var
 var
-	list: TJSFloat32List;
+    list: TJSFloat32List;
 begin
 begin
-	// TODO: fix mat4 to use flat arrays
-	list := TJSFloat32List(value.CopyList);
-	gl.uniformMatrix4fv(GetUniformLocation(name), false, list);
-	GLFatal(gl, 'gl.uniformMatrix4fv');
+    // TODO: fix mat4 to use flat arrays
+    list := TJSFloat32List(value.CopyList);
+    gl.uniformMatrix4fv(GetUniformLocation(name), false, list);
+    GLFatal(gl, 'gl.uniformMatrix4fv');
 end;
 end;
 
 
 function TShader.GetAttribLocation (name: string): GLint;
 function TShader.GetAttribLocation (name: string): GLint;
 begin
 begin
-	result := gl.getAttribLocation(programID, name);
+    result := gl.getAttribLocation(programID, name);
 end;
 end;
 
 
 procedure TShader.BindAttribLocation (index: GLuint; name: string);
 procedure TShader.BindAttribLocation (index: GLuint; name: string);
 begin
 begin
-	gl.bindAttribLocation(programID, index, name);
-	//GLFatal('glBindAttribLocation '+IntToStr(index)+':'+name);
+    gl.bindAttribLocation(programID, index, name);
+    //GLFatal('glBindAttribLocation '+IntToStr(index)+':'+name);
 end;
 end;
 
 
 constructor TShader.Create (context: TJSWebGLRenderingContext; vertexShaderSource, fragmentShaderSource: string);
 constructor TShader.Create (context: TJSWebGLRenderingContext; vertexShaderSource, fragmentShaderSource: string);
 begin
 begin
-	gl := context;
-	vertexShader := CreateShader(gl.VERTEX_SHADER, vertexShaderSource);
-	fragmentShader := CreateShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
+    gl := context;
+    vertexShader := CreateShader(gl.VERTEX_SHADER, vertexShaderSource);
+    fragmentShader := CreateShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
 end;
 end;
 
 
-function TShader.CreateShader(theType: GLenum; source: string): TJSWebGLShader; 
+function TShader.CreateShader(theType: GLenum; source: string): TJSWebGLShader;
 begin
 begin
-	Result := gl.createShader(theType);
-	if Result = nil then
-		Fatal('create shader failed');
-	gl.shaderSource(Result, source);
-	gl.compileShader(Result);
-	if gl.getShaderParameter(Result, gl.COMPILE_STATUS) then
-		begin
-			//writeln('loaded shader ', theType);
-			exit;
-		end
-	else
-		begin
-			Fatal(gl.getShaderInfoLog(Result));
-			//gl.deleteShader(shader);
-		end;
+    Result := gl.createShader(theType);
+    if Result = nil then
+        Fatal('create shader failed');
+    gl.shaderSource(Result, source);
+    gl.compileShader(Result);
+    if gl.getShaderParameter(Result, gl.COMPILE_STATUS) then
+        begin
+            //writeln('loaded shader ', theType);
+            exit;
+        end
+    else
+        begin
+            Fatal(gl.getShaderInfoLog(Result));
+            //gl.deleteShader(shader);
+        end;
 end;
 end;
 
 
-procedure TShader.Compile; 
+procedure TShader.Compile;
 begin
 begin
-	programID := gl.createProgram;
-	gl.attachShader(programID, vertexShader);
-	gl.attachShader(programID, fragmentShader);
+    programID := gl.createProgram;
+    gl.attachShader(programID, vertexShader);
+    gl.attachShader(programID, fragmentShader);
 end;
 end;
 
 
-procedure TShader.Link; 
+procedure TShader.Link;
 begin
 begin
   gl.linkProgram(programID);
   gl.linkProgram(programID);
   if not gl.getProgramParameter(programID, gl.LINK_STATUS) then
   if not gl.getProgramParameter(programID, gl.LINK_STATUS) then
-  	begin
-  		Fatal(gl.getProgramInfoLog(programID));
-  		//gl.deleteProgram(programID);
-  	end;
+    begin
+        Fatal(gl.getProgramInfoLog(programID));
+        //gl.deleteProgram(programID);
+    end;
 end;
 end;
 
 
-procedure TShader.Use; 
+procedure TShader.Use;
 begin
 begin
-	gl.useProgram(programID);
+    gl.useProgram(programID);
 end;
 end;
 
 
 end.
 end.

+ 2 - 2
demo/webgl/Noise.pas

@@ -1,7 +1,7 @@
 unit Noise;
 unit Noise;
 interface
 interface
 uses
 uses
-	SysUtils, Math;
+	Math;
 
 
 const
 const
 	kNoisekPerumationMax = 256;
 	kNoisekPerumationMax = 256;
@@ -241,4 +241,4 @@ begin
 		p[i] := seed[i mod kNoisekPerumationMax];
 		p[i] := seed[i mod kNoisekPerumationMax];
 end;
 end;
 
 
-end.
+end.

+ 5 - 10
demo/webgl/Pas2JS_WebGL.lpi

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
-  <ProjectOptions>
-    <Version Value="11"/>
+  <ProjectOptions BuildModesCount="1">
+    <Version Value="12"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <Runnable Value="False"/>
         <Runnable Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="project1"/>
       <Title Value="project1"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
@@ -18,7 +18,7 @@
     <CustomData Count="1">
     <CustomData Count="1">
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
     </CustomData>
     </CustomData>
-    <BuildModes Count="1">
+    <BuildModes>
       <Item1 Name="Default" Default="True"/>
       <Item1 Name="Default" Default="True"/>
     </BuildModes>
     </BuildModes>
     <PublishOptions>
     <PublishOptions>
@@ -28,11 +28,6 @@
       <FormatVersion Value="2"/>
       <FormatVersion Value="2"/>
       <Modes Count="0"/>
       <Modes Count="0"/>
     </RunParams>
     </RunParams>
-    <RequiredPackages Count="1">
-      <Item1>
-        <PackageName Value="pas2js_rtl"/>
-      </Item1>
-    </RequiredPackages>
     <Units Count="1">
     <Units Count="1">
       <Unit0>
       <Unit0>
         <Filename Value="Pas2JS_WebGL.pas"/>
         <Filename Value="Pas2JS_WebGL.pas"/>
@@ -66,7 +61,7 @@
     </Linking>
     </Linking>
     <Other>
     <Other>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
-      <CompilerPath Value="$MakeExe(IDE,pas2js)"/>
+      <CompilerPath Value="$(pas2js)"/>
     </Other>
     </Other>
   </CompilerOptions>
   </CompilerOptions>
   <Debugging>
   <Debugging>

+ 5 - 10
demo/webgl/Pas2JS_WebGL_Minimal.lpi

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
-  <ProjectOptions>
-    <Version Value="11"/>
+  <ProjectOptions BuildModesCount="1">
+    <Version Value="12"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <Runnable Value="False"/>
         <Runnable Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="project1"/>
       <Title Value="project1"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
@@ -18,7 +18,7 @@
     <CustomData Count="1">
     <CustomData Count="1">
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
     </CustomData>
     </CustomData>
-    <BuildModes Count="1">
+    <BuildModes>
       <Item1 Name="Default" Default="True"/>
       <Item1 Name="Default" Default="True"/>
     </BuildModes>
     </BuildModes>
     <PublishOptions>
     <PublishOptions>
@@ -28,11 +28,6 @@
       <FormatVersion Value="2"/>
       <FormatVersion Value="2"/>
       <Modes Count="0"/>
       <Modes Count="0"/>
     </RunParams>
     </RunParams>
-    <RequiredPackages Count="1">
-      <Item1>
-        <PackageName Value="pas2js_rtl"/>
-      </Item1>
-    </RequiredPackages>
     <Units Count="1">
     <Units Count="1">
       <Unit0>
       <Unit0>
         <Filename Value="Pas2JS_WebGL_Minimal.pas"/>
         <Filename Value="Pas2JS_WebGL_Minimal.pas"/>
@@ -66,7 +61,7 @@
     </Linking>
     </Linking>
     <Other>
     <Other>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
-      <CompilerPath Value="$MakeExe(IDE,pas2js)"/>
+      <CompilerPath Value="$(pas2js)"/>
     </Other>
     </Other>
   </CompilerOptions>
   </CompilerOptions>
   <Debugging>
   <Debugging>

+ 6 - 12
demo/webgl/Pas2JS_WebGL_OBJ.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="11"/>
+    <Version Value="12"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
@@ -10,7 +10,6 @@
         <Runnable Value="False"/>
         <Runnable Value="False"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="project1"/>
       <Title Value="project1"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
@@ -18,8 +17,8 @@
     <CustomData Count="1">
     <CustomData Count="1">
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
     </CustomData>
     </CustomData>
-    <BuildModes Count="1">
-      <Item1 Name="Default" Default="True"/>
+    <BuildModes>
+      <Item Name="Default" Default="True"/>
     </BuildModes>
     </BuildModes>
     <PublishOptions>
     <PublishOptions>
       <Version Value="2"/>
       <Version Value="2"/>
@@ -28,16 +27,11 @@
       <FormatVersion Value="2"/>
       <FormatVersion Value="2"/>
       <Modes Count="0"/>
       <Modes Count="0"/>
     </RunParams>
     </RunParams>
-    <RequiredPackages Count="1">
-      <Item1>
-        <PackageName Value="pas2js_rtl"/>
-      </Item1>
-    </RequiredPackages>
-    <Units Count="1">
-      <Unit0>
+    <Units>
+      <Unit>
         <Filename Value="Pas2JS_WebGL_OBJ.pas"/>
         <Filename Value="Pas2JS_WebGL_OBJ.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
-      </Unit0>
+      </Unit>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

+ 2 - 2
demo/webgl/Pas2JS_WebGL_OBJ.pas

@@ -4,8 +4,8 @@ uses
 	BrowserConsole, Web, WebGL, JS, Math;
 	BrowserConsole, Web, WebGL, JS, Math;
 
 
 var
 var
-	gl: TJSWebGLRenderingContext;
-	shader: TShader;
+  gl: TJSWebGLRenderingContext;
+  shader: TShader;
   projTransform: TMat4;
   projTransform: TMat4;
   viewTransform: TMat4;
   viewTransform: TMat4;
   modelTransform: TMat4;
   modelTransform: TMat4;

+ 5 - 10
demo/webgl/Pas2JS_WebGL_Terrain.lpi

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
-  <ProjectOptions>
-    <Version Value="11"/>
+  <ProjectOptions BuildModesCount="1">
+    <Version Value="12"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <Runnable Value="False"/>
         <Runnable Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="project1"/>
       <Title Value="project1"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
@@ -18,7 +18,7 @@
     <CustomData Count="1">
     <CustomData Count="1">
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
       <Item0 Name="PasJSWebBrowserProject" Value="1"/>
     </CustomData>
     </CustomData>
-    <BuildModes Count="1">
+    <BuildModes>
       <Item1 Name="Default" Default="True"/>
       <Item1 Name="Default" Default="True"/>
     </BuildModes>
     </BuildModes>
     <PublishOptions>
     <PublishOptions>
@@ -28,11 +28,6 @@
       <FormatVersion Value="2"/>
       <FormatVersion Value="2"/>
       <Modes Count="0"/>
       <Modes Count="0"/>
     </RunParams>
     </RunParams>
-    <RequiredPackages Count="1">
-      <Item1>
-        <PackageName Value="pas2js_rtl"/>
-      </Item1>
-    </RequiredPackages>
     <Units Count="1">
     <Units Count="1">
       <Unit0>
       <Unit0>
         <Filename Value="Pas2JS_WebGL_Terrain.pas"/>
         <Filename Value="Pas2JS_WebGL_Terrain.pas"/>
@@ -66,7 +61,7 @@
     </Linking>
     </Linking>
     <Other>
     <Other>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
       <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
-      <CompilerPath Value="$MakeExe(IDE,pas2js)"/>
+      <CompilerPath Value="$(pas2js)"/>
     </Other>
     </Other>
   </CompilerOptions>
   </CompilerOptions>
   <Debugging>
   <Debugging>

+ 1 - 1
demo/webgl/Pas2JS_WebGL_Terrain.pas

@@ -11,7 +11,7 @@ var
   viewTransform: TMat4;
   viewTransform: TMat4;
   modelTransform: TMat4;
   modelTransform: TMat4;
 
 
- var
+var
   debugConsole: TJSElement;
   debugConsole: TJSElement;
   canvasAnimationHandler: integer = 0;
   canvasAnimationHandler: integer = 0;