From dab31fbdf4d95f1abe27af78afc198a4921b8597 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sat, 23 Mar 2013 18:16:16 -0700 Subject: [PATCH] Fix a logic error in the WebGL samples Update the WebGL vertex structs sample to use interleaved vertex data. Fix Marshal.SizeOf(object). --- Examples/WebGL/Page.cs | 6 +-- Examples/WebGL_Vertex_Structs/Page.cs | 64 ++++++++++++++++++--------- Libraries/JSIL.Unsafe.js | 4 +- Meta/PackedArray.cs | 2 +- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/Examples/WebGL/Page.cs b/Examples/WebGL/Page.cs index c7615e56e..dfb3205f0 100644 --- a/Examples/WebGL/Page.cs +++ b/Examples/WebGL/Page.cs @@ -76,12 +76,12 @@ public static bool InitGL () { } if (Builtins.IsTruthy(gl)) { - Builtins.Global["alert"]("Could not initialize WebGL"); - return false; - } else { GL = gl; Console.WriteLine("Initialized WebGL"); return true; + } else { + Builtins.Global["alert"]("Could not initialize WebGL"); + return false; } } diff --git a/Examples/WebGL_Vertex_Structs/Page.cs b/Examples/WebGL_Vertex_Structs/Page.cs index 753753225..29e351f3f 100644 --- a/Examples/WebGL_Vertex_Structs/Page.cs +++ b/Examples/WebGL_Vertex_Structs/Page.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Text; using JSIL; using JSIL.Meta; @@ -18,7 +19,7 @@ public class UniformCollection { } public class BufferCollection { - public object CubeVertexPositions, CubeVertexNormals, CubeTextureCoords; + public object CubeVertices; public object CubeIndices; } @@ -78,12 +79,12 @@ public static bool InitGL () { } if (Builtins.IsTruthy(gl)) { - Builtins.Global["alert"]("Could not initialize WebGL"); - return false; - } else { GL = gl; Console.WriteLine("Initialized WebGL"); return true; + } else { + Builtins.Global["alert"]("Could not initialize WebGL"); + return false; } } @@ -164,14 +165,8 @@ public static void InitShaders () { } public static void InitBuffers () { - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertexPositions = GL.createBuffer()); - GL.bufferData(GL.ARRAY_BUFFER, CubeData.Positions.GetBackingTypedArray(), GL.STATIC_DRAW); - - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertexNormals = GL.createBuffer()); - GL.bufferData(GL.ARRAY_BUFFER, CubeData.Normals.GetBackingTypedArray(), GL.STATIC_DRAW); - - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeTextureCoords = GL.createBuffer()); - GL.bufferData(GL.ARRAY_BUFFER, CubeData.TexCoords.GetBackingTypedArray(), GL.STATIC_DRAW); + GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertices = GL.createBuffer()); + GL.bufferData(GL.ARRAY_BUFFER, CubeData.Vertices.GetArrayBuffer(), GL.STATIC_DRAW); GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, Buffers.CubeIndices = GL.createBuffer()); GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, CubeData.Indices, GL.STATIC_DRAW); @@ -255,14 +250,23 @@ public static void DrawScene () { GLMatrix4.rotate(Matrices.ModelView, DegreesToRadians(RotationX), new [] { 1f, 0, 0 }); GLMatrix4.rotate(Matrices.ModelView, DegreesToRadians(RotationY), new [] { 0, 1f, 0 }); - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertexPositions); - GL.vertexAttribPointer(Attributes.VertexPosition, 3, GL.FLOAT, false, 0, 0); + var vertexExemplar = default(CubeVertex); + var sizeofFloat = Marshal.SizeOf(typeof(float)); + var sizeofVertex = Marshal.SizeOf(vertexExemplar); + var sizeofPosition = Marshal.SizeOf(vertexExemplar.Position); + var sizeofNormal = Marshal.SizeOf(vertexExemplar.Normal); + var sizeofTexCoord = Marshal.SizeOf(vertexExemplar.TexCoord); + var offsetOfPosition = Marshal.OffsetOf(typeof(CubeVertex), "Position").ToInt32(); + var offsetOfNormal = Marshal.OffsetOf(typeof(CubeVertex), "Normal").ToInt32(); + var offsetOfTexCoord = Marshal.OffsetOf(typeof(CubeVertex), "TexCoord").ToInt32(); - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertexNormals); - GL.vertexAttribPointer(Attributes.VertexNormal, 3, GL.FLOAT, false, 0, 0); + // Contrary to what you would expect from reading the documentation, and from a stride of 0 being densely-packed elements, + // glVertexAttribPointer's 'stride' parameter is the *complete* size of a vertex, not the size excluding the attribute you are describing. - GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeTextureCoords); - GL.vertexAttribPointer(Attributes.TextureCoord, 2, GL.FLOAT, false, 0, 0); + GL.bindBuffer(GL.ARRAY_BUFFER, Buffers.CubeVertices); + GL.vertexAttribPointer(Attributes.VertexPosition, sizeofPosition / sizeofFloat, GL.FLOAT, false, sizeofVertex, offsetOfPosition); + GL.vertexAttribPointer(Attributes.VertexNormal, sizeofNormal / sizeofFloat, GL.FLOAT, false, sizeofVertex, offsetOfNormal); + GL.vertexAttribPointer(Attributes.TextureCoord, sizeofTexCoord / sizeofFloat, GL.FLOAT, false, sizeofVertex, offsetOfTexCoord); GL.activeTexture(GL.TEXTURE0); GL.bindTexture(GL.TEXTURE_2D, CrateTexture); @@ -349,8 +353,22 @@ public Vector3f (float x, float y, float z) { } } + public struct CubeVertex { + public readonly Vector3f Position; + public readonly Vector3f Normal; + public readonly Vector2f TexCoord; + + public CubeVertex (Vector3f position, Vector3f normal, Vector2f texCoord) { + Position = position; + Normal = normal; + TexCoord = texCoord; + } + } + public static class CubeData { [JSPackedArray] + public static readonly CubeVertex[] Vertices; + public static readonly Vector3f[] Positions = new [] { // Front face new Vector3f(-1, -1, 1), @@ -389,7 +407,6 @@ public static class CubeData { new Vector3f(-1, 1, -1), }; - [JSPackedArray] public static readonly Vector3f[] Normals = new [] { // Front face new Vector3f(0, 0, 1), @@ -428,7 +445,6 @@ public static class CubeData { new Vector3f(-1, 0, 0) }; - [JSPackedArray] public static readonly Vector2f[] TexCoords = new [] { // Front face new Vector2f(0, 0), @@ -475,5 +491,13 @@ public static class CubeData { 16, 17, 18, 16, 18, 19, // Right face 20, 21, 22, 20, 22, 23 // Left face }; + + static CubeData () { + Vertices = new CubeVertex[Positions.Length]; + + for (var i = 0; i < Vertices.Length; i++) { + Vertices[i] = new CubeVertex(Positions[i], Normals[i], TexCoords[i]); + } + } } } diff --git a/Libraries/JSIL.Unsafe.js b/Libraries/JSIL.Unsafe.js index a69c619ba..53c22a918 100644 --- a/Libraries/JSIL.Unsafe.js +++ b/Libraries/JSIL.Unsafe.js @@ -91,7 +91,7 @@ JSIL.ImplementExternals("System.Runtime.InteropServices.Marshal", function ($) { (new JSIL.MethodSignature($.Int32, [$.Object], [])), function SizeOf (structure) { var type = JSIL.GetType(structure); - return JSIL.GetNativeSizeOf(structure); + return JSIL.GetNativeSizeOf(type); } ) @@ -690,7 +690,7 @@ JSIL.PackedArray.New = function PackedArray_New (elementType, sizeOrInitializer) if (initializerIsArray) { for (var i = 0; i < size; i++) { var element = sizeOrInitializer[i]; - result.Set(i, element); + result.set_Item(i, element); } } diff --git a/Meta/PackedArray.cs b/Meta/PackedArray.cs index 1fe3c2533..6194220fd 100644 --- a/Meta/PackedArray.cs +++ b/Meta/PackedArray.cs @@ -49,7 +49,7 @@ public static class PackedArrayExtensionMethods { [JSReplacement("JSIL.GetBackingTypedArray($array)")] [JSAllowPackedArrayArguments] [JSIsPure] - public static byte[] GetBackingTypedArray (this T[] array) + public static dynamic GetBackingTypedArray (this T[] array) where T : struct { throw new NotImplementedException("Not supported when running as C#");