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 jsGlCreateShader(GlEnum shaderType)",
"GlId jsGlCreateVertexArray()",
"GlId jsGlGetUniformLocation(GlId programId, int nameLength, const char* namePntr)",
"bool jsGlGetProgramParameterBool(GlId programId, GlEnum parameter)",
"bool jsGlGetShaderParameterBool(GlId shaderId, GlEnum parameter)",
"inline void* ReallocMem(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize)",
@@ -116,6 +117,25 @@
"void jsGlEnableVertexAttribArray(GlEnum location)",
"void jsGlLinkProgram(GlId programId)",
"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 jsGlVertexAttribPointer(GlEnum attribLocation, int componentCount, GlEnum componentType, bool normalized, int stride, int offset)",
"void* AllocMemUnaligned(Arena* arena, u32 numBytes)",

View File

@@ -18,12 +18,5 @@ Description:
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);
}

17
cwasm.h
View File

@@ -130,6 +130,23 @@ Description:
#define AssertMsg(condition, message) sizeof(condition)
#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 |
// +--------------------------------------------------------------+

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 jsGlClear(int bufferBits);
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

View File

@@ -7,12 +7,13 @@ export var glObjects = {
vaos: [ null ],
shaders: [ null ],
programs: [ null ],
uniformLocations: [ null ],
};
// +--------------------------------------------------------------+
// | Helpers |
// +--------------------------------------------------------------+
export function verifyGlBufferId(bufferId, allowZero)
function verifyGlBufferId(bufferId, allowZero)
{
if (typeof(bufferId) != "number") { return "BufferId is not a number!"; }
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!"; }
return null;
}
export function verifyGlVaoId(vaoId, allowZero)
function verifyGlVaoId(vaoId, allowZero)
{
if (typeof(vaoId) != "number") { return "VaoId is not a number!"; }
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!"; }
return null;
}
export function verifyGlShaderId(shaderId, allowZero)
function verifyGlShaderId(shaderId, allowZero)
{
if (typeof(shaderId) != "number") { return "ShaderId is not a number!"; }
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!"; }
return null;
}
export function verifyGlProgramId(programId, allowZero)
function verifyGlProgramId(programId, allowZero)
{
if (typeof(programId) != "number") { return "ProgramId is not a number!"; }
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!"; }
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; }
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);
}
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 = {
jsGlCreateBuffer: jsGlCreateBuffer,
jsGlBindBuffer: jsGlBindBuffer,
@@ -230,6 +381,26 @@ export let jsGlFunctions = {
jsGlClearColor: jsGlClearColor,
jsGlClear: jsGlClear,
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)

View File

@@ -21,33 +21,21 @@ function AcquireCanvas(canvasWidth, canvasHeight)
// canvasContainer = document.getElementById("canvas_container");
// console.assert(canvasContainer != null, "Couldn't find canvas container DOM element!");
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; }
// console.dir(canvasContextGl);
appGlobals.glContext = canvasContextGl;
return canvasContextGl;
}
async function LoadWasmModule(wasmFilePath, initialWasmPageCount)
{
appGlobals.textDecoder = new TextDecoder("utf-8");
let wasmEnvironment =
{
...jsStdFunctions,
...jsGlFunctions,
};
appGlobals.wasmModule = await loadWasmModule(wasmFilePath, wasmEnvironment);
appGlobals.wasmModule = await loadWasmModule(wasmFilePath, { ...jsStdFunctions, ...jsGlFunctions });
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 numMemoryPagesAfterLoad = memorySize / WASM_MEMORY_PAGE_SIZE;
if ((memorySize % WASM_MEMORY_PAGE_SIZE) != 0)
@@ -61,17 +49,17 @@ async function LoadWasmModule(wasmFilePath, initialWasmPageCount)
async function MainLoop()
{
console.log("Initializing WebGL Canvas...");
var canvas = AcquireCanvas(600, 400);
var glContext = CreateGlContext(canvas);
AcquireCanvas(600, 400);
CreateGlContext();
console.log("Loading WASM Module...");
await LoadWasmModule("app.wasm", 4);
appGlobals.wasmModule.exports.App_Initialize();
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);

View File

@@ -16,8 +16,13 @@ struct
GlId vertexShader;
GlId fragmentShader;
GlId testShader;
GlId testUniformLocation;
GlId worldMatrixLocation;
GlId viewMatrixLocation;
GlId projMatrixLocation;
u32 frameIndex;
r64 prevProgramTimeR64;
} app;
static const char* VertexShaderCodeStr;
@@ -27,12 +32,21 @@ WASM_EXPORT(App_Initialize) void App_Initialize()
{
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));
r32 positions[] = {
-0.9, -0.79, // left bottom corner
1.0, -1.0, // right bottom corner
0.0, 1.0 // center top corner
-0.7, -0.7, // left bottom corner
0.7, -0.7, // right bottom corner
0.0, 0.7 // center top corner
};
app.positionBuffer = jsGlCreateBuffer();
jsGlBindBuffer(GL_ARRAY_BUFFER, app.positionBuffer);
@@ -88,15 +102,61 @@ WASM_EXPORT(App_Initialize) void App_Initialize()
jsGlLinkProgram(app.testShader);
// also debug the program status
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);
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);
r32 lerpValue = (sinf((((timeSource + offset) % periodMs) / (r32)periodMs) * 2*Pi32) + 1.0f) / 2.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);
jsGlBindVertexArray(app.vao); // our vertex array object
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(
GL_TRIANGLES, // drawing mode
0, // index of the first vertex to draw
@@ -104,6 +164,7 @@ WASM_EXPORT(App_UpdateAndRender) void App_UpdateAndRender()
);
app.frameIndex++;
app.prevProgramTimeR64 = programTimeR64;
}
static const char* VertexShaderCodeStr = "#version 300 es\n"
@@ -115,6 +176,10 @@ static const char* VertexShaderCodeStr = "#version 300 es\n"
"// data types\n"
"precision highp float;\n"
"\n"
"uniform mat4 WorldMatrix;\n"
"uniform mat4 ViewMatrix;\n"
"uniform mat4 ProjMatrix;\n"
"\n"
"// this is the vertex attribute at index 0\n"
"// which we defined in the vertex array object.\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"
" // vertex position for the shader program\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";
static const char* FragmentShaderCodeStr = "#version 300 es\n"
"precision highp float;\n"
"\n"
"uniform float TestUniform[3];\n"
"\n"
"in vec3 vCol; // the data from vertex shader\n"
"\n"
"// fragment output value\n"
@@ -146,5 +213,5 @@ static const char* FragmentShaderCodeStr = "#version 300 es\n"
"out vec4 outCol;\n"
"\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";