Added a bunch of WebGL functions related to shader uniforms to gl_functions.js

This commit is contained in:
2025-09-01 18:50:14 -07:00
parent b548b7bb26
commit 42cf6d9e9f
7 changed files with 315 additions and 39 deletions

View File

@@ -96,6 +96,7 @@
"GlId jsGlCreateProgram()", "GlId jsGlCreateProgram()",
"GlId jsGlCreateShader(GlEnum shaderType)", "GlId jsGlCreateShader(GlEnum shaderType)",
"GlId jsGlCreateVertexArray()", "GlId jsGlCreateVertexArray()",
"GlId jsGlGetUniformLocation(GlId programId, int nameLength, const char* namePntr)",
"bool jsGlGetProgramParameterBool(GlId programId, GlEnum parameter)", "bool jsGlGetProgramParameterBool(GlId programId, GlEnum parameter)",
"bool jsGlGetShaderParameterBool(GlId shaderId, GlEnum parameter)", "bool jsGlGetShaderParameterBool(GlId shaderId, GlEnum parameter)",
"inline void* ReallocMem(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize)", "inline void* ReallocMem(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize)",
@@ -116,6 +117,25 @@
"void jsGlEnableVertexAttribArray(GlEnum location)", "void jsGlEnableVertexAttribArray(GlEnum location)",
"void jsGlLinkProgram(GlId programId)", "void jsGlLinkProgram(GlId programId)",
"void jsGlShaderSource(GlId shaderId, int sourceLength, const char* sourcePntr)", "void jsGlShaderSource(GlId shaderId, int sourceLength, const char* sourcePntr)",
"void jsGlUniform1f(int location, r32 value)",
"void jsGlUniform1fv(GlId locationId, int valuesCount, const r32* valuesPntr)",
"void jsGlUniform1i(GlId locationId, int value)",
"void jsGlUniform1iv(GlId locationId, int valuesCount, const int* valuesPntr)",
"void jsGlUniform2f(int location, r32 value0, r32 value1)",
"void jsGlUniform2fv(GlId locationId, int valuesCount, const r32* valuesPntr)",
"void jsGlUniform2i(GlId locationId, int value0, int value1)",
"void jsGlUniform2iv(GlId locationId, int valuesCount, const int* valuesPntr)",
"void jsGlUniform3f(int location, r32 value0, r32 value1, r32 value2)",
"void jsGlUniform3fv(GlId locationId, int valuesCount, const r32* valuesPntr)",
"void jsGlUniform3i(GlId locationId, int value0, int value1, int value2)",
"void jsGlUniform3iv(GlId locationId, int valuesCount, const int* valuesPntr)",
"void jsGlUniform4f(int location, r32 value0, r32 value1, r32 value2, r32 value3)",
"void jsGlUniform4fv(GlId locationId, int valuesCount, const r32* valuesPntr)",
"void jsGlUniform4i(GlId locationId, int value0, int value1, int value2, int value3)",
"void jsGlUniform4iv(GlId locationId, int valuesCount, const int* valuesPntr)",
"void jsGlUniformMatrix2fv(GlId locationId, const r32* valuesPntr)",
"void jsGlUniformMatrix3fv(GlId locationId, const r32* valuesPntr)",
"void jsGlUniformMatrix4fv(GlId locationId, const r32* valuesPntr)",
"void jsGlUseProgram(GlId programId)", "void jsGlUseProgram(GlId programId)",
"void jsGlVertexAttribPointer(GlEnum attribLocation, int componentCount, GlEnum componentType, bool normalized, int stride, int offset)", "void jsGlVertexAttribPointer(GlEnum attribLocation, int componentCount, GlEnum componentType, bool normalized, int stride, int offset)",
"void* AllocMemUnaligned(Arena* arena, u32 numBytes)", "void* AllocMemUnaligned(Arena* arena, u32 numBytes)",

View File

@@ -18,12 +18,5 @@ Description:
void InitializeCWasm(u32 scratchArenasSize) void InitializeCWasm(u32 scratchArenasSize)
{ {
// CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, "Hello\nWorld!");
Write_D("Hello\nWorld!");
PrintLine_I(" Fuzzy %u Bunnies!\n%s", 31415926, "What");
WriteLine_D("");
WriteLine_W("When");
Write_D("\n");
WriteLine_E("Where");
InitGlobalArenas(scratchArenasSize); InitGlobalArenas(scratchArenasSize);
} }

17
cwasm.h
View File

@@ -130,6 +130,23 @@ Description:
#define AssertMsg(condition, message) sizeof(condition) #define AssertMsg(condition, message) sizeof(condition)
#endif #endif
//Actual Value of Pi: 3.1415926535897932384626433832795...
#define Pi64 3.14159265358979311599796346854 //accurate to 15 digits
#define Pi32 3.1415927410125732421875f //accurate to 6 digits
#define QuarterPi64 (Pi64/4.0)
#define ThirdPi64 (Pi64/3.0)
#define HalfPi64 (Pi64/2.0)
#define ThreeHalfsPi64 (Pi64*(3.0/2.0))
#define TwoPi64 (2*Pi64)
#define QuarterPi32 (Pi32/4.0f)
#define ThirdPi32 (Pi32/3.0f)
#define HalfPi32 (Pi32/2.0f)
#define ThreeHalfsPi32 (Pi32*(3.0f/2.0f))
#define TwoPi32 (2*Pi32)
//Actual Value of e: 2.7182818284590452353602874713526...
#define e64 2.71828182845904509079559829843 //accurate to 15 digits
#define e32 2.71828174591064453125f //accurate to 6 digits
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
// | Standard Includes | // | Standard Includes |
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+

View File

@@ -31,5 +31,25 @@ MAYBE_EXTERN_C int jsGlGetProgramParameterInt(GlId programId, GlEnum parameter);
MAYBE_EXTERN_C void jsGlClearColor(r32 rValue, r32 gValue, r32 bValue, r32 aValue); MAYBE_EXTERN_C void jsGlClearColor(r32 rValue, r32 gValue, r32 bValue, r32 aValue);
MAYBE_EXTERN_C void jsGlClear(int bufferBits); MAYBE_EXTERN_C void jsGlClear(int bufferBits);
MAYBE_EXTERN_C void jsGlDrawArrays(GlEnum geometryType, int startIndex, int count); MAYBE_EXTERN_C void jsGlDrawArrays(GlEnum geometryType, int startIndex, int count);
MAYBE_EXTERN_C GlId jsGlGetUniformLocation(GlId programId, int nameLength, const char* namePntr);
MAYBE_EXTERN_C void jsGlUniform1f(GlId locationId, r32 value);
MAYBE_EXTERN_C void jsGlUniform2f(GlId locationId, r32 value0, r32 value1);
MAYBE_EXTERN_C void jsGlUniform3f(GlId locationId, r32 value0, r32 value1, r32 value2);
MAYBE_EXTERN_C void jsGlUniform4f(GlId locationId, r32 value0, r32 value1, r32 value2, r32 value3);
MAYBE_EXTERN_C void jsGlUniform1fv(GlId locationId, int valuesCount, const r32* valuesPntr);
MAYBE_EXTERN_C void jsGlUniform2fv(GlId locationId, int valuesCount, const r32* valuesPntr); //TODO: Change valuesPntr to v2*
MAYBE_EXTERN_C void jsGlUniform3fv(GlId locationId, int valuesCount, const r32* valuesPntr); //TODO: Change valuesPntr to v3*
MAYBE_EXTERN_C void jsGlUniform4fv(GlId locationId, int valuesCount, const r32* valuesPntr); //TODO: Change valuesPntr to v4*
MAYBE_EXTERN_C void jsGlUniform1i(GlId locationId, int value);
MAYBE_EXTERN_C void jsGlUniform2i(GlId locationId, int value0, int value1);
MAYBE_EXTERN_C void jsGlUniform3i(GlId locationId, int value0, int value1, int value2);
MAYBE_EXTERN_C void jsGlUniform4i(GlId locationId, int value0, int value1, int value2, int value3);
MAYBE_EXTERN_C void jsGlUniform1iv(GlId locationId, int valuesCount, const int* valuesPntr);
MAYBE_EXTERN_C void jsGlUniform2iv(GlId locationId, int valuesCount, const int* valuesPntr); //TODO: Change valuesPntr to v2i*
MAYBE_EXTERN_C void jsGlUniform3iv(GlId locationId, int valuesCount, const int* valuesPntr); //TODO: Change valuesPntr to v3i*
MAYBE_EXTERN_C void jsGlUniform4iv(GlId locationId, int valuesCount, const int* valuesPntr); //TODO: Change valuesPntr to v4i*
MAYBE_EXTERN_C void jsGlUniformMatrix2fv(GlId locationId, const r32* valuesPntr); //TODO: Change valuesPntr to mat2*
MAYBE_EXTERN_C void jsGlUniformMatrix3fv(GlId locationId, const r32* valuesPntr); //TODO: Change valuesPntr to mat3*
MAYBE_EXTERN_C void jsGlUniformMatrix4fv(GlId locationId, const r32* valuesPntr); //TODO: Change valuesPntr to mat4*
#endif // _CWASM_WEBGL_JS_IMPORTS_H #endif // _CWASM_WEBGL_JS_IMPORTS_H

View File

@@ -7,12 +7,13 @@ export var glObjects = {
vaos: [ null ], vaos: [ null ],
shaders: [ null ], shaders: [ null ],
programs: [ null ], programs: [ null ],
uniformLocations: [ null ],
}; };
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
// | Helpers | // | Helpers |
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
export function verifyGlBufferId(bufferId, allowZero) function verifyGlBufferId(bufferId, allowZero)
{ {
if (typeof(bufferId) != "number") { return "BufferId is not a number!"; } if (typeof(bufferId) != "number") { return "BufferId is not a number!"; }
if (bufferId == 0) { return allowZero ? null : "BufferId is 0!"; } if (bufferId == 0) { return allowZero ? null : "BufferId is 0!"; }
@@ -21,7 +22,7 @@ export function verifyGlBufferId(bufferId, allowZero)
if (glObjects.buffers[bufferId] == null) { return "BufferId is for a destroyed vertBuffer!"; } if (glObjects.buffers[bufferId] == null) { return "BufferId is for a destroyed vertBuffer!"; }
return null; return null;
} }
export function verifyGlVaoId(vaoId, allowZero) function verifyGlVaoId(vaoId, allowZero)
{ {
if (typeof(vaoId) != "number") { return "VaoId is not a number!"; } if (typeof(vaoId) != "number") { return "VaoId is not a number!"; }
if (vaoId == 0) { return allowZero ? null : "VaoId is 0!"; } if (vaoId == 0) { return allowZero ? null : "VaoId is 0!"; }
@@ -30,7 +31,7 @@ export function verifyGlVaoId(vaoId, allowZero)
if (glObjects.vaos[vaoId] == null) { return "VaoId is for a destroyed array!"; } if (glObjects.vaos[vaoId] == null) { return "VaoId is for a destroyed array!"; }
return null; return null;
} }
export function verifyGlShaderId(shaderId, allowZero) function verifyGlShaderId(shaderId, allowZero)
{ {
if (typeof(shaderId) != "number") { return "ShaderId is not a number!"; } if (typeof(shaderId) != "number") { return "ShaderId is not a number!"; }
if (shaderId == 0) { return allowZero ? null : "ShaderId is 0!"; } if (shaderId == 0) { return allowZero ? null : "ShaderId is 0!"; }
@@ -39,7 +40,7 @@ export function verifyGlShaderId(shaderId, allowZero)
if (glObjects.shaders[shaderId] == null) { return "ShaderId is for a destroyed shader!"; } if (glObjects.shaders[shaderId] == null) { return "ShaderId is for a destroyed shader!"; }
return null; return null;
} }
export function verifyGlProgramId(programId, allowZero) function verifyGlProgramId(programId, allowZero)
{ {
if (typeof(programId) != "number") { return "ProgramId is not a number!"; } if (typeof(programId) != "number") { return "ProgramId is not a number!"; }
if (programId == 0) { return allowZero ? null : "ProgramId is 0!"; } if (programId == 0) { return allowZero ? null : "ProgramId is 0!"; }
@@ -48,7 +49,16 @@ export function verifyGlProgramId(programId, allowZero)
if (glObjects.programs[programId] == null) { return "ProgramId is for a destroyed program!"; } if (glObjects.programs[programId] == null) { return "ProgramId is for a destroyed program!"; }
return null; return null;
} }
export function verifyParameter(verifyResult, functionName, parameterName, parameterValue) function verifyGlUniformLocationId(locationId, allowZero)
{
if (typeof(locationId) != "number") { return "LocationId is not a number!"; }
if (locationId == 0) { return allowZero ? null : "LocationId is 0!"; }
if (glObjects == null || glObjects.uniformLocations == null) { return "Locations array has not been initialized yet!"; }
if (locationId >= glObjects.uniformLocations.length) { return "LocationId is too high!"; }
if (glObjects.uniformLocations[locationId] == null) { return "LocationId is for a destroyed program!"; }
return null;
}
function verifyParameter(verifyResult, functionName, parameterName, parameterValue)
{ {
if (verifyResult == null) { return true; } if (verifyResult == null) { return true; }
console.error("Invalid argument \"" + parameterName + "\" passed to " + functionName + ": " + verifyResult); console.error("Invalid argument \"" + parameterName + "\" passed to " + functionName + ": " + verifyResult);
@@ -208,6 +218,147 @@ export function jsGlDrawArrays(geometryType, startIndex, count)
appGlobals.glContext.drawArrays(geometryType, startIndex, count); appGlobals.glContext.drawArrays(geometryType, startIndex, count);
} }
export function jsGlGetUniformLocation(programId, nameLength, namePntr)
{
if (!verifyParameter(verifyGlProgramId(programId, false), "gl.getUniformLocation", "programId", programId)) { return false; }
let program = glObjects.programs[programId];
let nameStr = wasmPntrAndLengthToJsString(namePntr, nameLength);
let newLocation = appGlobals.glContext.getUniformLocation(program, nameStr);
let newLocationId = glObjects.uniformLocations.length;
glObjects.uniformLocations.push(newLocation);
return newLocationId;
}
export function jsGlUniform1f(locationId, value)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform1f", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform1f(location, value);
}
export function jsGlUniform2f(locationId, value0, value1)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform2f", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform2f(location, value0, value1);
}
export function jsGlUniform3f(locationId, value0, value1, value2)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform3f", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform3f(location, value0, value1, value2);
}
export function jsGlUniform4f(locationId, value0, value1, value2, value3)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform4f", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform4f(location, value0, value1, value2, value3);
}
export function jsGlUniform1fv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform1fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount);
appGlobals.glContext.uniform1fv(location, valuesArray);
}
export function jsGlUniform2fv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform2fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*2);
appGlobals.glContext.uniform2fv(location, valuesArray);
}
export function jsGlUniform3fv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform3fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*3);
appGlobals.glContext.uniform3fv(location, valuesArray);
}
export function jsGlUniform4fv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform4fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*4);
appGlobals.glContext.uniform4fv(location, valuesArray);
}
export function jsGlUniform1i(locationId, value)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform1i", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform1i(location, value);
}
export function jsGlUniform2i(locationId, value0, value1)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform2i", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform2i(location, value0, value1);
}
export function jsGlUniform3i(locationId, value0, value1, value2)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform3i", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform3i(location, value0, value1, value2);
}
export function jsGlUniform4i(locationId, value0, value1, value2, value3)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform4i", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
appGlobals.glContext.uniform4i(location, value0, value1, value2, value3);
}
export function jsGlUniform1iv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform1iv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Int32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount);
appGlobals.glContext.uniform1iv(location, valuesArray);
}
export function jsGlUniform2iv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform2iv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Int32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*2);
appGlobals.glContext.uniform2iv(location, valuesArray);
}
export function jsGlUniform3iv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform3iv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Int32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*3);
appGlobals.glContext.uniform3iv(location, valuesArray);
}
export function jsGlUniform4iv(locationId, valuesCount, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniform4iv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Int32Array(appGlobals.memDataView.buffer, valuesPntr, valuesCount*4);
appGlobals.glContext.uniform4iv(location, valuesArray);
}
export function jsGlUniformMatrix2fv(locationId, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniformMatrix2fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, 2*2);
appGlobals.glContext.uniformMatrix2fv(location, false, valuesArray);
}
export function jsGlUniformMatrix3fv(locationId, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniformMatrix3fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, 3*3);
appGlobals.glContext.uniformMatrix3fv(location, false, valuesArray);
}
export function jsGlUniformMatrix4fv(locationId, valuesPntr)
{
if (!verifyParameter(verifyGlUniformLocationId(locationId, false), "gl.uniformMatrix4fv", "locationId", locationId)) { return false; }
let location = glObjects.uniformLocations[locationId];
let valuesArray = new Float32Array(appGlobals.memDataView.buffer, valuesPntr, 4*4);
appGlobals.glContext.uniformMatrix4fv(location, false, valuesArray);
}
export let jsGlFunctions = { export let jsGlFunctions = {
jsGlCreateBuffer: jsGlCreateBuffer, jsGlCreateBuffer: jsGlCreateBuffer,
jsGlBindBuffer: jsGlBindBuffer, jsGlBindBuffer: jsGlBindBuffer,
@@ -230,6 +381,26 @@ export let jsGlFunctions = {
jsGlClearColor: jsGlClearColor, jsGlClearColor: jsGlClearColor,
jsGlClear: jsGlClear, jsGlClear: jsGlClear,
jsGlDrawArrays: jsGlDrawArrays, jsGlDrawArrays: jsGlDrawArrays,
jsGlGetUniformLocation: jsGlGetUniformLocation,
jsGlUniform1f: jsGlUniform1f,
jsGlUniform2f: jsGlUniform2f,
jsGlUniform3f: jsGlUniform3f,
jsGlUniform4f: jsGlUniform4f,
jsGlUniform1fv: jsGlUniform1fv,
jsGlUniform2fv: jsGlUniform2fv,
jsGlUniform3fv: jsGlUniform3fv,
jsGlUniform4fv: jsGlUniform4fv,
jsGlUniform1i: jsGlUniform1i,
jsGlUniform2i: jsGlUniform2i,
jsGlUniform3i: jsGlUniform3i,
jsGlUniform4i: jsGlUniform4i,
jsGlUniform1iv: jsGlUniform1iv,
jsGlUniform2iv: jsGlUniform2iv,
jsGlUniform3iv: jsGlUniform3iv,
jsGlUniform4iv: jsGlUniform4iv,
jsGlUniformMatrix2fv: jsGlUniformMatrix2fv,
jsGlUniformMatrix3fv: jsGlUniformMatrix3fv,
jsGlUniformMatrix4fv: jsGlUniformMatrix4fv,
}; };
//TODO: string getShaderInfoLog(shaderId) //TODO: string getShaderInfoLog(shaderId)

View File

@@ -21,33 +21,21 @@ function AcquireCanvas(canvasWidth, canvasHeight)
// canvasContainer = document.getElementById("canvas_container"); // canvasContainer = document.getElementById("canvas_container");
// console.assert(canvasContainer != null, "Couldn't find canvas container DOM element!"); // console.assert(canvasContainer != null, "Couldn't find canvas container DOM element!");
appGlobals.canvas = canvas; appGlobals.canvas = canvas;
return canvas;
} }
function CreateGlContext(canvas) function CreateGlContext()
{ {
var canvasContextGl = canvas.getContext("webgl2"); var canvasContextGl = appGlobals.canvas.getContext("webgl2");
if (canvasContextGl === null) { console.error("Unable to initialize WebGL render context. Your browser or machine may not support it :("); return null; } if (canvasContextGl === null) { console.error("Unable to initialize WebGL render context. Your browser or machine may not support it :("); return null; }
// console.dir(canvasContextGl); // console.dir(canvasContextGl);
appGlobals.glContext = canvasContextGl; appGlobals.glContext = canvasContextGl;
return canvasContextGl;
} }
async function LoadWasmModule(wasmFilePath, initialWasmPageCount) async function LoadWasmModule(wasmFilePath, initialWasmPageCount)
{ {
appGlobals.textDecoder = new TextDecoder("utf-8"); appGlobals.textDecoder = new TextDecoder("utf-8");
appGlobals.wasmModule = await loadWasmModule(wasmFilePath, { ...jsStdFunctions, ...jsGlFunctions });
let wasmEnvironment =
{
...jsStdFunctions,
...jsGlFunctions,
};
appGlobals.wasmModule = await loadWasmModule(wasmFilePath, wasmEnvironment);
appGlobals.memDataView = new DataView(new Uint8Array(appGlobals.wasmModule.exports.memory.buffer).buffer); appGlobals.memDataView = new DataView(new Uint8Array(appGlobals.wasmModule.exports.memory.buffer).buffer);
// let heapBaseAddress = appGlobals.wasmModule.exports.__heap_base.value;
// console.log("__heap_base = " + heapBaseAddress);
let memorySize = appGlobals.wasmModule.exports.memory.buffer.byteLength; let memorySize = appGlobals.wasmModule.exports.memory.buffer.byteLength;
let numMemoryPagesAfterLoad = memorySize / WASM_MEMORY_PAGE_SIZE; let numMemoryPagesAfterLoad = memorySize / WASM_MEMORY_PAGE_SIZE;
if ((memorySize % WASM_MEMORY_PAGE_SIZE) != 0) if ((memorySize % WASM_MEMORY_PAGE_SIZE) != 0)
@@ -61,17 +49,17 @@ async function LoadWasmModule(wasmFilePath, initialWasmPageCount)
async function MainLoop() async function MainLoop()
{ {
console.log("Initializing WebGL Canvas..."); console.log("Initializing WebGL Canvas...");
var canvas = AcquireCanvas(600, 400); AcquireCanvas(600, 400);
var glContext = CreateGlContext(canvas); CreateGlContext();
console.log("Loading WASM Module..."); console.log("Loading WASM Module...");
await LoadWasmModule("app.wasm", 4); await LoadWasmModule("app.wasm", 4);
appGlobals.wasmModule.exports.App_Initialize(); appGlobals.wasmModule.exports.App_Initialize();
console.log("Running!"); console.log("Running!");
function renderFrame() function renderFrame(currentTime)
{ {
appGlobals.wasmModule.exports.App_UpdateAndRender(); appGlobals.wasmModule.exports.App_UpdateAndRender(currentTime);
window.requestAnimationFrame(renderFrame); window.requestAnimationFrame(renderFrame);
} }
window.requestAnimationFrame(renderFrame); window.requestAnimationFrame(renderFrame);

View File

@@ -16,8 +16,13 @@ struct
GlId vertexShader; GlId vertexShader;
GlId fragmentShader; GlId fragmentShader;
GlId testShader; GlId testShader;
GlId testUniformLocation;
GlId worldMatrixLocation;
GlId viewMatrixLocation;
GlId projMatrixLocation;
u32 frameIndex; u32 frameIndex;
r64 prevProgramTimeR64;
} app; } app;
static const char* VertexShaderCodeStr; static const char* VertexShaderCodeStr;
@@ -27,12 +32,21 @@ WASM_EXPORT(App_Initialize) void App_Initialize()
{ {
InitializeCWasm(Kilobytes(128)); InitializeCWasm(Kilobytes(128));
#if 0
Write_D("Hello\nWorld!");
PrintLine_I(" Fuzzy %u Bunnies!\n%s", 31415926, "What");
WriteLine_D("");
WriteLine_W("When");
Write_D("\n");
WriteLine_E("Where");
#endif
memset(&app, 0x00, sizeof(app)); memset(&app, 0x00, sizeof(app));
r32 positions[] = { r32 positions[] = {
-0.9, -0.79, // left bottom corner -0.7, -0.7, // left bottom corner
1.0, -1.0, // right bottom corner 0.7, -0.7, // right bottom corner
0.0, 1.0 // center top corner 0.0, 0.7 // center top corner
}; };
app.positionBuffer = jsGlCreateBuffer(); app.positionBuffer = jsGlCreateBuffer();
jsGlBindBuffer(GL_ARRAY_BUFFER, app.positionBuffer); jsGlBindBuffer(GL_ARRAY_BUFFER, app.positionBuffer);
@@ -88,15 +102,61 @@ WASM_EXPORT(App_Initialize) void App_Initialize()
jsGlLinkProgram(app.testShader); jsGlLinkProgram(app.testShader);
// also debug the program status // also debug the program status
if (!jsGlGetProgramParameterBool(app.testShader, GL_LINK_STATUS)) { WriteLine_E("Failed to link shader program!"); } //TODO: jsGlGetProgramInfoLog if (!jsGlGetProgramParameterBool(app.testShader, GL_LINK_STATUS)) { WriteLine_E("Failed to link shader program!"); } //TODO: jsGlGetProgramInfoLog
const char* uniformName = "TestUniform";
app.testUniformLocation = jsGlGetUniformLocation(app.testShader, (int)strlen(uniformName), uniformName);
const char* worldMatrixName = "WorldMatrix";
app.worldMatrixLocation = jsGlGetUniformLocation(app.testShader, (int)strlen(worldMatrixName), worldMatrixName);
const char* viewMatrixName = "ViewMatrix";
app.viewMatrixLocation = jsGlGetUniformLocation(app.testShader, (int)strlen(viewMatrixName), viewMatrixName);
const char* projMatrixName = "ProjMatrix";
app.projMatrixLocation = jsGlGetUniformLocation(app.testShader, (int)strlen(projMatrixName), projMatrixName);
} }
WASM_EXPORT(App_UpdateAndRender) void App_UpdateAndRender() r32 OscillateBy(u64 timeSource, r32 min, r32 max, u64 periodMs, u64 offset)
{ {
r32 time = app.frameIndex * (1000.0f/60.0f); r32 lerpValue = (sinf((((timeSource + offset) % periodMs) / (r32)periodMs) * 2*Pi32) + 1.0f) / 2.0f;
jsGlClearColor(sinf(time * 0.0005f + 1.5f)/2 + 0.5f, sinf(time * 0.0013f + 2.3f)/2 + 0.5f, sinf(time * 0.0007f + 3.7f)/2 + 0.5f, 1.0f); return min + (max - min) * lerpValue;
}
WASM_EXPORT(App_UpdateAndRender) void App_UpdateAndRender(r64 programTimeR64)
{
r64 timeScaleR64 = (programTimeR64 - app.prevProgramTimeR64) / (1000.0 / 60.0);
if (fabs(timeScaleR64 - 1.0) < 0.001) { timeScaleR64 = 1.0; }
if (timeScaleR64 > 4.0) { timeScaleR64 = 4.0; }
if (timeScaleR64 < 0.0) { timeScaleR64 = 0.0; }
r32 timeScale = (r32)timeScaleR64;
r32 programTimef = (r32)programTimeR64;
u64 programTime = (u64)programTimeR64;
u64 elapsedMs = programTime - (u64)app.prevProgramTimeR64;
r32 identityMatrix[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
r32 worldMatrix[] = {
OscillateBy(programTime, 0.9f, 1.1f, 3000, 0), 0.0f, 0.0f, OscillateBy(programTime, -0.1f, 0.1f, 3000, 0),
0.0f, OscillateBy(programTime, 0.9f, 1.1f, 3000, 1500), 0.0f, OscillateBy(programTime, -0.1f, 0.1f, 3000, 750),
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
jsGlClearColor(OscillateBy(programTime, 0.0f, 1.0f, 3700, 1500), OscillateBy(programTime, 0.0f, 1.0f, 5300, 2000), OscillateBy(programTime, 0.0f, 1.0f, 2300, 500), 1.0f);
jsGlClear(GL_COLOR_BUFFER_BIT); jsGlClear(GL_COLOR_BUFFER_BIT);
jsGlBindVertexArray(app.vao); // our vertex array object jsGlBindVertexArray(app.vao); // our vertex array object
jsGlUseProgram(app.testShader); // our shader program jsGlUseProgram(app.testShader); // our shader program
r32 uniformValues[] = {
OscillateBy(programTime, 0.0f, 1.0f, 2000, 0),
OscillateBy(programTime, 0.0f, 1.0f, 2000, 1200),
OscillateBy(programTime, 0.0f, 1.0f, 2000, 700),
};
jsGlUniform1fv(app.testUniformLocation, ArrayCount(uniformValues), &uniformValues[0]);
jsGlUniformMatrix4fv(app.worldMatrixLocation, &worldMatrix[0]);
jsGlUniformMatrix4fv(app.viewMatrixLocation, &identityMatrix[0]);
jsGlUniformMatrix4fv(app.projMatrixLocation, &identityMatrix[0]);
jsGlDrawArrays( jsGlDrawArrays(
GL_TRIANGLES, // drawing mode GL_TRIANGLES, // drawing mode
0, // index of the first vertex to draw 0, // index of the first vertex to draw
@@ -104,6 +164,7 @@ WASM_EXPORT(App_UpdateAndRender) void App_UpdateAndRender()
); );
app.frameIndex++; app.frameIndex++;
app.prevProgramTimeR64 = programTimeR64;
} }
static const char* VertexShaderCodeStr = "#version 300 es\n" static const char* VertexShaderCodeStr = "#version 300 es\n"
@@ -115,6 +176,10 @@ static const char* VertexShaderCodeStr = "#version 300 es\n"
"// data types\n" "// data types\n"
"precision highp float;\n" "precision highp float;\n"
"\n" "\n"
"uniform mat4 WorldMatrix;\n"
"uniform mat4 ViewMatrix;\n"
"uniform mat4 ProjMatrix;\n"
"\n"
"// this is the vertex attribute at index 0\n" "// this is the vertex attribute at index 0\n"
"// which we defined in the vertex array object.\n" "// which we defined in the vertex array object.\n"
"// we can use any name for this in the glsl code\n" "// we can use any name for this in the glsl code\n"
@@ -133,12 +198,14 @@ static const char* VertexShaderCodeStr = "#version 300 es\n"
" \n" " \n"
" // vertex position for the shader program\n" " // vertex position for the shader program\n"
" // always a vec4 value\n" " // always a vec4 value\n"
" gl_Position = vec4(aPos, 0.0, 1.0);\n" " gl_Position = ((vec4(aPos, 0.0, 1.0) * WorldMatrix) * ViewMatrix) * ProjMatrix;\n"
"}\n"; "}\n";
static const char* FragmentShaderCodeStr = "#version 300 es\n" static const char* FragmentShaderCodeStr = "#version 300 es\n"
"precision highp float;\n" "precision highp float;\n"
"\n" "\n"
"uniform float TestUniform[3];\n"
"\n"
"in vec3 vCol; // the data from vertex shader\n" "in vec3 vCol; // the data from vertex shader\n"
"\n" "\n"
"// fragment output value\n" "// fragment output value\n"
@@ -146,5 +213,5 @@ static const char* FragmentShaderCodeStr = "#version 300 es\n"
"out vec4 outCol;\n" "out vec4 outCol;\n"
"\n" "\n"
"void main(){\n" "void main(){\n"
" outCol = vec4(vCol, 1.0);\n" " outCol = vec4(vec3(vCol.r * TestUniform[0], vCol.g * TestUniform[1], vCol.b * TestUniform[2]), 1.0);\n"
"}\n"; "}\n";