Skip to content

Commit 8c6319f

Browse files
committed
Added partial support for WebGL 2.
1 parent ebc3eef commit 8c6319f

File tree

11 files changed

+2213
-7486
lines changed

11 files changed

+2213
-7486
lines changed

src/Blazor.Extensions.Canvas.JS/package-lock.json

Lines changed: 1977 additions & 7462 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Blazor.Extensions.Canvas.JS/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
"lodash": "^4.17.20"
1212
},
1313
"devDependencies": {
14-
"@types/emscripten": "0.0.31",
15-
"ts-loader": "^4.4.2",
16-
"typescript": "^2.9.2",
17-
"webpack": "^4.16.3",
18-
"webpack-cli": "^3.1.0",
19-
"uuid": "8.3.1"
14+
"@types/emscripten": "^1.39.6",
15+
"ts-loader": "^9.2.7",
16+
"typescript": "^4.6.2",
17+
"webpack": "^5.70.0",
18+
"webpack-cli": "^4.9.2",
19+
"uuid": "8.3.2"
2020
}
2121
}

src/Blazor.Extensions.Canvas.JS/src/CanvasContextManager.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export class ContextManager {
1010
private readonly patterns = new Map<string, any>();
1111

1212
private readonly webGLTypes = [
13-
WebGLBuffer, WebGLShader, WebGLProgram, WebGLFramebuffer, WebGLRenderbuffer, WebGLTexture, WebGLUniformLocation
13+
WebGLBuffer, WebGLShader, WebGLProgram, WebGLFramebuffer, WebGLRenderbuffer, WebGLTexture, WebGLUniformLocation, WebGLVertexArrayObject
1414
];
1515

1616
public constructor(contextName: string) {
@@ -20,6 +20,9 @@ export class ContextManager {
2020
else if (contextName === "webgl" || contextName === "experimental-webgl") {
2121
this.prototypes = WebGLRenderingContext.prototype;
2222
this.webGLContext = true;
23+
} else if (contextName === "webgl2" || contextName === "experimental-webgl2") {
24+
this.prototypes = WebGL2RenderingContext.prototype;
25+
this.webGLContext = true;
2326
} else
2427
throw new Error(`Invalid context name: ${contextName}`);
2528
}
@@ -109,7 +112,7 @@ export class ContextManager {
109112
if (object.hasOwnProperty("webGLType") && object.hasOwnProperty("id")) {
110113
return (this.webGLObject[object["id"]]);
111114
} else if (Array.isArray(object) && !method.endsWith("v")) {
112-
return Int8Array.of(...(object as number[]));
115+
return Int8Array.from(object);
113116
} else if (typeof(object) === "string" && (method === "bufferData" || method === "bufferSubData")) {
114117
let binStr = window.atob(object);
115118
let length = binStr.length;

src/Blazor.Extensions.Canvas.JS/src/InitializeCanvas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ namespace Canvas {
55
// define what this extension adds to the window object inside BlazorExtensions
66
const extensionObject = {
77
Canvas2d: new ContextManager("2d"),
8-
WebGL: new ContextManager("webgl")
8+
WebGL: new ContextManager("webgl"),
9+
WebGL2: new ContextManager("webgl2")
910
};
1011

1112
export function initialize(): void {

src/Blazor.Extensions.Canvas/CanvasContextExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,10 @@ public static async Task<WebGLContext> CreateWebGLAsync(this BECanvasComponent c
3535
{
3636
return await new WebGLContext(canvas, attributes).InitializeAsync().ConfigureAwait(false) as WebGLContext;
3737
}
38+
39+
public static async Task<WebGL2Context> CreateWebGL2Async(this BECanvasComponent canvas, WebGLContextAttributes attributes = null)
40+
{
41+
return await new WebGL2Context(canvas, attributes).InitializeAsync().ConfigureAwait(false) as WebGL2Context;
42+
}
3843
}
3944
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Threading.Tasks;
2+
3+
namespace Blazor.Extensions.Canvas.WebGL
4+
{
5+
public class WebGL2Context : WebGLContext
6+
{
7+
#region Constants
8+
private const string CONTEXT_NAME = "WebGL2";
9+
private const string BIND_BUFFER_BASE = "bindBufferBase";
10+
private const string BIND_VERTEX_ARRAY = "bindVertexArray";
11+
private const string BLIT_FRAMEBUFFER = "blitFramebuffer";
12+
private const string CREATE_VERTEX_ARRAY = "createVertexArray";
13+
private const string DELETE_VERTEX_ARRAY = "deleteVertexArray";
14+
private const string DRAW_ARRAYS_INSTANCED = "drawArraysInstanced";
15+
private const string DRAW_ELEMENTS_INSTANCED = "drawElementsInstanced";
16+
private const string GET_UNIFORM_BLOCK_INDEX = "getUniformBlockIndex";
17+
private const string TEX_STORAGE_2D = "texStorage2D";
18+
private const string UNIFORM_BLOCK_BINDING = "uniformBlockBinding";
19+
private const string VERTEX_ATTRIB_DIVISOR = "vertexAttribDivisor";
20+
private const string VERTEX_ATTRIB_IPOINTER = "vertexAttribIPointer";
21+
#endregion
22+
23+
public WebGL2Context(BECanvasComponent reference, WebGLContextAttributes attributes = null) : base(reference, attributes, CONTEXT_NAME)
24+
{
25+
}
26+
27+
#region Methods
28+
public async Task BindBufferBaseAsync(BufferType target, uint index, WebGLBuffer buffer) => await this.BatchCallAsync(BIND_BUFFER_BASE, isMethodCall: true, target, index, buffer);
29+
public async Task BindVertexArrayAsync(WebGLVertexArrayObject vertexArray) => await this.BatchCallAsync(BIND_VERTEX_ARRAY, isMethodCall: true, vertexArray);
30+
public async Task BlitFramebufferAsync(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, BufferBits mask, BlitFilter filter) => await this.BatchCallAsync(BLIT_FRAMEBUFFER, isMethodCall: true, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
31+
public async Task<WebGLVertexArrayObject> CreateVertexArrayAsync() => await this.CallMethodAsync<WebGLVertexArrayObject>(CREATE_VERTEX_ARRAY);
32+
public async Task DeleteVertexArrayAsync(WebGLVertexArrayObject vertexArray) => await this.BatchCallAsync(DELETE_VERTEX_ARRAY, isMethodCall: true, vertexArray);
33+
public async Task DrawArraysInstancedAsync(Primitive mode, int first, int count, int instanceCount) => await this.BatchCallAsync(DRAW_ARRAYS_INSTANCED, isMethodCall: true, mode, first, count, instanceCount);
34+
public async Task DrawElementsInstancedAsync(Primitive mode, int count, DataType type, long offset, int instanceCount) => await this.BatchCallAsync(DRAW_ELEMENTS_INSTANCED, isMethodCall: true, mode, count, type, offset, instanceCount);
35+
public async Task<uint> GetUniformBlockIndexAsync(WebGLProgram program, string uniformBlockName) => await this.CallMethodAsync<uint>(GET_UNIFORM_BLOCK_INDEX, program, uniformBlockName);
36+
public async Task TexStorage2DAsync(Texture2DType target, int levels, PixelFormat internalformat, int width, int height) => await this.BatchCallAsync(TEX_STORAGE_2D, isMethodCall: true, target, levels, internalformat, width, height);
37+
public async Task UniformBlockBindingAsync(WebGLProgram program, uint uniformBlockIndex, uint uniformBlockBinding) => await this.BatchCallAsync(UNIFORM_BLOCK_BINDING, isMethodCall: true, program, uniformBlockIndex, uniformBlockBinding);
38+
public async Task VertexAttribDivisorAsync(uint index, uint divisor) => await this.BatchCallAsync(VERTEX_ATTRIB_DIVISOR, isMethodCall: true, index, divisor);
39+
public async Task VertexAttribIPointerAsync(uint index, int size, DataType type, int stride, long offset) => await this.BatchCallAsync(VERTEX_ATTRIB_IPOINTER, isMethodCall: true, index, size, type, stride, offset);
40+
#endregion
41+
}
42+
}

src/Blazor.Extensions.Canvas/WebGL/WebGLContext.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public class WebGLContext : RenderingContext
125125
public int DrawingBufferHeight { get; private set; }
126126
#endregion
127127

128-
public WebGLContext(BECanvasComponent reference, WebGLContextAttributes attributes = null) : base(reference, CONTEXT_NAME, attributes)
128+
public WebGLContext(BECanvasComponent reference, WebGLContextAttributes attributes = null, string contextName = CONTEXT_NAME) : base(reference, contextName, attributes)
129129
{
130130
}
131131

@@ -289,12 +289,12 @@ protected override async Task ExtendedInitializeAsync()
289289
public async Task BufferDataAsync(BufferType target, int size, BufferUsageHint usage) => await this.BatchCallAsync(BUFFER_DATA, isMethodCall: true, target, size, usage);
290290

291291
[Obsolete("Use the async version instead, which is already called internally.")]
292-
public void BufferData<T>(BufferType target, T[] data, BufferUsageHint usage) => this.CallMethod<object>(BUFFER_DATA, target, this.ConvertToByteArray(data), usage);
293-
public async Task BufferDataAsync<T>(BufferType target, T[] data, BufferUsageHint usage) => await this.BatchCallAsync(BUFFER_DATA, isMethodCall: true, target, this.ConvertToByteArray(data), usage);
292+
public void BufferData<T>(BufferType target, T[] data, BufferUsageHint usage) where T : unmanaged => this.CallMethod<object>(BUFFER_DATA, target, this.ConvertToByteArray(data), usage);
293+
public async Task BufferDataAsync<T>(BufferType target, T[] data, BufferUsageHint usage) where T : unmanaged => await this.BatchCallAsync(BUFFER_DATA, isMethodCall: true, target, this.ConvertToByteArray(data), usage);
294294

295295
[Obsolete("Use the async version instead, which is already called internally.")]
296-
public void BufferSubData<T>(BufferType target, uint offset, T[] data) => this.CallMethod<object>(BUFFER_SUB_DATA, target, offset, this.ConvertToByteArray(data));
297-
public async Task BufferSubDataAsync<T>(BufferType target, uint offset, T[] data) => await this.BatchCallAsync(BUFFER_SUB_DATA, isMethodCall: true, target, offset, this.ConvertToByteArray(data));
296+
public void BufferSubData<T>(BufferType target, uint offset, T[] data) where T : unmanaged => this.CallMethod<object>(BUFFER_SUB_DATA, target, offset, this.ConvertToByteArray(data));
297+
public async Task BufferSubDataAsync<T>(BufferType target, uint offset, T[] data) where T : unmanaged => await this.BatchCallAsync(BUFFER_SUB_DATA, isMethodCall: true, target, offset, this.ConvertToByteArray(data));
298298

299299
[Obsolete("Use the async version instead, which is already called internally.")]
300300
public WebGLBuffer CreateBuffer() => this.CallMethod<WebGLBuffer>(CREATE_BUFFER);
@@ -410,7 +410,7 @@ public void TexImage2D<T>(Texture2DType target, int level, PixelFormat internalF
410410
=> this.CallMethod<object>(TEX_IMAGE_2D, target, level, internalFormat, width, height, format, type, pixels);
411411
public async Task TexImage2DAsync<T>(Texture2DType target, int level, PixelFormat internalFormat, int width, int height, PixelFormat format, PixelType type, T[] pixels)
412412
where T : struct
413-
=> await this.BatchCallAsync(TEX_IMAGE_2D, isMethodCall: true, target, level, internalFormat, width, height, format, type, pixels);
413+
=> await this.BatchCallAsync(TEX_IMAGE_2D, isMethodCall: true, target, level, internalFormat, width, height, 0, format, type, pixels);
414414

415415
[Obsolete("Use the async version instead, which is already called internally.")]
416416
public void TexSubImage2D<T>(Texture2DType target, int level, int xoffset, int yoffset, int width, int height, PixelFormat format, PixelType type, T[] pixels)
@@ -730,10 +730,18 @@ public async Task VertexAttribAsync(uint index, params float[] value)
730730
public void Flush() => this.CallMethod<object>(FLUSH);
731731
public async Task FlushAsync() => await this.BatchCallAsync(FLUSH, isMethodCall: true);
732732

733-
private byte[] ConvertToByteArray<T>(T[] arr)
733+
private byte[] ConvertToByteArray<T>(T[] arr) where T : unmanaged
734734
{
735735
byte[] byteArr = new byte[arr.Length * Marshal.SizeOf<T>()];
736-
Buffer.BlockCopy(arr, 0, byteArr, 0, byteArr.Length);
736+
var handle = GCHandle.Alloc(arr, GCHandleType.Pinned);
737+
try
738+
{
739+
Marshal.Copy(handle.AddrOfPinnedObject(), byteArr, 0, byteArr.Length);
740+
}
741+
finally
742+
{
743+
handle.Free();
744+
}
737745
return byteArr;
738746
}
739747
private async Task<int> GetDrawingBufferWidthAsync() => await this.GetPropertyAsync<int>(DRAWING_BUFFER_WIDTH);

src/Blazor.Extensions.Canvas/WebGL/WebGLEnums.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ public enum BufferUsageHint
134134
public enum BufferType
135135
{
136136
ARRAY_BUFFER = 0x8892,
137-
ELEMENT_ARRAY_BUFFER = 0x8893
137+
ELEMENT_ARRAY_BUFFER = 0x8893,
138+
UNIFORM_BUFFER = 0x8A11
138139
}
139140

140141
public enum BufferParameter
@@ -209,15 +210,24 @@ public enum HintTarget
209210

210211
public enum PixelFormat
211212
{
213+
DEPTH_COMPONENT = 0x1902,
214+
RED = 0x1903,
212215
ALPHA = 0x1906,
213216
RGB = 0x1907,
214217
RGBA = 0x1908,
215218
LUMINANCE = 0x1909,
216-
LUMINANCE_ALPHA = 0x190A
219+
LUMINANCE_ALPHA = 0x190A,
220+
RGBA8 = 0x8058,
221+
R8 = 0x8229,
222+
RGBA16F = 0x881A,
223+
DEPTH_COMPONENT32F = 0x8CAC,
224+
RGBA16UI = 0x8D76,
225+
R8_SNORM = 0x8F94
217226
}
218227

219228
public enum PixelType
220229
{
230+
BYTE = 0x1400,
221231
UNSIGNED_BYTE = 0x1401,
222232
UNSIGNED_SHORT_4_4_4_4 = 0x8033,
223233
UNSIGNED_SHORT_5_5_5_1 = 0x8034,
@@ -293,7 +303,8 @@ public enum TextureParameter
293303
TEXTURE_MAG_FILTER = 0x2800,
294304
TEXTURE_MIN_FILTER = 0x2801,
295305
TEXTURE_WRAP_S = 0x2802,
296-
TEXTURE_WRAP_T = 0x2803
306+
TEXTURE_WRAP_T = 0x2803,
307+
TEXTURE_MAX_LEVEL = 0x813D
297308
}
298309

299310
public enum TextureParameterValue
@@ -309,6 +320,12 @@ public enum TextureParameterValue
309320
MIRRORED_REPEAT = 0x8370
310321
}
311322

323+
public enum BlitFilter
324+
{
325+
NEAREST = 0x2600,
326+
LINEAR = 0x2601
327+
}
328+
312329
public enum UniformType
313330
{
314331
FLOAT_VEC2 = 0x8B50,
@@ -345,7 +362,9 @@ public enum RenderbufferType
345362

346363
public enum FramebufferType
347364
{
348-
FRAMEBUFFER = 0x8D40
365+
FRAMEBUFFER = 0x8D40,
366+
READ_FRAMEBUFFER = 0x8CA8,
367+
DRAW_FRAMEBUFFER = 0x8CA9
349368
}
350369

351370
public enum RenderbufferParameter
@@ -450,4 +469,4 @@ public enum Texture
450469
TEXTURE30,
451470
TEXTURE31
452471
}
453-
}
472+
}

src/Blazor.Extensions.Canvas/WebGL/WebGLObjects.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,7 @@ public class WebGLShader : WebGLObject
5656

5757
public class WebGLUniformLocation : WebGLObject
5858
{ }
59+
60+
public class WebGLVertexArrayObject : WebGLObject
61+
{ }
5962
}

0 commit comments

Comments
 (0)