textures, window fixes

This commit is contained in:
PS 2022-03-29 18:09:50 +02:00
parent 7925279d59
commit 6775ea26d3
25 changed files with 899 additions and 384 deletions

View File

@ -1,2 +1,3 @@
SCRIPT_REL_DIR=$(dirname "${BASH_SOURCE[0]}")
$SCRIPT_REL_DIR/build_.sh debug win32 intel
$SCRIPT_REL_DIR/build_.sh debug win32 intel
$SCRIPT_REL_DIR/build_.sh debug wasm intel

View File

@ -126,6 +126,7 @@ add_flag CompilerFlags_win32 "-wd4505" #
add_flag CompilerFlags_win32 "-wd4100" #
add_flag CompilerFlags_win32 "-wd4189" #
add_flag CompilerFlags_win32 "-wd4702" #
add_flag CompilerFlags_win32 "-wd4996" # _CRT_SECURE_NO_WARNINGS
CompilerFlags_osx=""
@ -143,6 +144,7 @@ CompilerFlags_DEBUG_win32=""
add_flag CompilerFlags_DEBUG_win32 "-Od" #
add_flag CompilerFlags_DEBUG_win32 "-Zi" #
add_flag CompilerFlags_DEBUG_win32 "-DDEBUG" #
add_flag CompilerFlags_DEBUG_win32 "-DPRINT_ASSERTS"
CompilerFlags_DEBUG="-O0"
add_flag CompilerFlags_DEBUG "-g" #

Binary file not shown.

View File

@ -34,6 +34,35 @@ function wasm_get_proc(inst, proc_ptr)
function fract (v) { return v % 1; }
function u32_to_byte_array_32 (v)
{
let result = [0, 0, 0, 0];
result[0] = (v & 0xff);
result[1] = (((v - result[0]) >> 8 ) & 0xff);
result[2] = (((v - result[1]) >> 16) & 0xff);
result[3] = (((v - result[2]) >> 24) & 0xff);
return result;
}
function byte_array_32_to_u32 (arr)
{
// NOTE(PS): the '>>>' operators in this function deal with the fact
// that bit shift operators convert numbers to s32's. The >>> just
// converts them back to u32s
let r0 = ((arr[0] & 0xff) << 0 );
let r1 = ((arr[1] & 0xff) << 8 );
let r2 = ((arr[2] & 0xff) << 16);
let r3 = (((arr[3] & 0xff) << 24) >>> 0);
let result = (r0 | r1 | r2 | r3) >>> 0;
return result;
}
function put_u32 (ptr, value)
{
let src = u32_to_byte_array_32(value);
wasm_write_bytes(lumenarium_wasm_instance, src, ptr, 4);
}
var lumenarium_wasm_imports = {
memset: (dst, size, value) => {
@ -122,12 +151,46 @@ var lumenarium_wasm_imports = {
let string = wasm_read_string(lumenarium_wasm_instance, str_base, len);
console.log(string);
},
wasm_get_canvas_dim: (w_ptr, h_ptr) => {
const canvas = document.querySelector("#gl_canvas");
let w_view = wasm_mem_get_u8_arr(lumenarium_wasm_instance, w_ptr, 4);
let w = canvas.width;
let wb = u32_to_byte_array_32(w);
for (let i = 0; i < 4; i++) w_view[i] = wb[i];
let h_view = wasm_mem_get_u8_arr(lumenarium_wasm_instance, h_ptr, 4);
let h = canvas.height;
let hb = u32_to_byte_array_32(h);
for (let i = 0; i < 4; i++) h_view[i] = hb[i];
},
};
///////////////////////////////////////
// Web GL Imports
let gl = null;
let gl_error = false;
function glErrorReport(outer_args) {
const err = gl.getError();
if (err == gl.NO_ERROR) return;
gl_error = true;
let msg = "";
switch (err) {
case gl.NO_ERROR: { msg = "NO_ERROR"; } break;
case gl.INVALID_ENUM: { msg = "INVALID_ENUM"; } break;
case gl.INVALID_VALUE: { msg = "INVALID_VALUE"; } break;
case gl.INVALID_OPERATION: { msg = "INVALID_OPERATION"; } break;
case gl.INVALID_FRAMEBUFFER_OPERATION: { msg = "INVALID_FRAMEBUFFER_OPERATION"; } break;
case gl.OUT_OF_MEMORY: { msg = "OUT_OF_MEMORY"; } break;
case gl.CONTEXT_LOST_WEBGL: { msg = "CONTEXT_LOST_WEBGL"; } break;
default: { msg = "Uknown error"; } break;
}
console.error(`WebGL Error: ${msg} ${err}`, outer_args);
}
// NOTE(PS): it seems like its not enough to set
// the values of imports to gl.function
@ -135,16 +198,37 @@ let gl = null;
// instead we need to wrap them for some reason.
// Not sure why
function glClearColor (r, g, b, a) { return gl.clearColor(r,g,b,a); }
function glEnable(v) { return gl.enable(v); }
function glDisable(v) { return gl.disable(v); }
function glBlendFunc(a,b) { return gl.blendFunc(a,b); }
function glEnable(v) {
const r = gl.enable(v);
glErrorReport(arguments);
return r;
}
function glDisable(v) {
const r = gl.disable(v);
glErrorReport(arguments);
return r;
}
function glBlendFunc(a,b) {
const r = gl.blendFunc(a,b);
glErrorReport(arguments);
return r;
}
function glViewport(xmin, ymin, xmax, ymax) { return gl.viewport(xmin,ymin,xmax,ymax); }
function glDepthFunc(v) { return gl.depthFunc(v); }
function glClear(mask) { return gl.clear(mask); }
function glDepthFunc(v) {
const r = gl.depthFunc(v);
glErrorReport(arguments);
return r;
}
function glClear(mask) {
const r = gl.clear(mask);
glErrorReport(arguments);
return r;
}
let glBuffers = [];
let glShaders = [];
let glPrograms = [];
let glTextures = [];
function gl_get_managed_resource(arr, id) {
if (id == 0) return null;
return arr[id - 1];
@ -152,55 +236,76 @@ function gl_get_managed_resource(arr, id) {
function gl_get_buffer(id) { return gl_get_managed_resource(glBuffers, id); }
function gl_get_shader(id) { return gl_get_managed_resource(glShaders, id); }
function gl_get_program(id) { return gl_get_managed_resource(glPrograms, id); }
function gl_get_texture(id) { return gl_get_managed_resource(glTextures, id); }
function glCreateBuffer() {
let buffer = gl.createBuffer();
glErrorReport(arguments);
let new_len = glBuffers.push(buffer);
return new_len;
}
function glBindBuffer(buffer_kind, buffer_id)
{
return gl.bindBuffer(buffer_kind, gl_get_buffer(buffer_id));
const r = gl.bindBuffer(buffer_kind, gl_get_buffer(buffer_id));
glErrorReport(arguments);
return r;
}
function glBufferData(target, size, ptr, usage)
{
let data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, ptr, size);
return gl.bufferData(target, data, usage);
const r = gl.bufferData(target, data, usage);
glErrorReport(arguments);
return r;
}
function glCreateShader(kind)
{
let shader = gl.createShader(kind);
glErrorReport(arguments);
let new_len = glShaders.push(shader);
return new_len;
}
function glShaderSource(shader_id, shader_code, shader_code_len)
{
let str = wasm_read_string(lumenarium_wasm_instance, shader_code, shader_code_len);
console.error("For some reason, str isn't getting the correct data out of here", str);
return gl.shaderSource(gl_get_shader(shader_id), str);
const r = gl.shaderSource(gl_get_shader(shader_id), str);
glErrorReport(arguments);
return r;
}
function glCompileShader(shader_id)
{
let s = gl_get_shader(shader_id);
let r = gl.compileShader(s);
glErrorReport(arguments);
let m = gl.getShaderInfoLog(s);
glErrorReport(arguments);
if (m.length > 0)
{
console.error("glCompileShader: \n\n" + m);
}
}
function glCreateProgram()
{
let prog = gl.createProgram();
glErrorReport(arguments);
let new_len = glPrograms.push(prog);
return new_len;
}
function glAttachShader(program, shader)
{
let s = gl_get_shader(shader);
let p = gl_get_program(program);
return gl.attachShader(p, s);
const r = gl.attachShader(p, s);
glErrorReport(arguments);
return r;
}
function glLinkProgram(program)
{
let p = gl_get_program(program);
@ -210,43 +315,94 @@ function glLinkProgram(program)
console.error("Failed to compile WebGL program. \n\n"+info);
}
}
function glUseProgram(program)
{
let p = gl_get_program(program);
return gl.useProgram(p);
const r = gl.useProgram(p);
glErrorReport(arguments);
return r;
}
function glGetAttribLocation(program, name, name_len)
{
let str = wasm_read_string(lumenarium_wasm_instance, name, name_len);
return gl.getAttribLocation(gl_get_program(program), str);
const r = gl.getAttribLocation(gl_get_program(program), str);
glErrorReport(arguments);
return r;
}
function glVertexAttribPointer(attr, size, type, normalized, stride, pointer)
{
return gl.vertexAttribPointer(attr, size, type, normalized, stride, pointer);
const r = gl.vertexAttribPointer(attr, size, type, normalized, stride, pointer);
glErrorReport(arguments);
return r;
}
function glEnableVertexAttribArray(index)
{
return gl.enableVertexAttribArray(index);
const r = gl.enableVertexAttribArray(index);
glErrorReport(arguments);
return r;
}
function glDrawElements(type, index_count, ele_type, indices)
{
return gl.drawElements(type, index_count, ele_type, indices);
const r = gl.drawElements(type, index_count, ele_type, indices);
glErrorReport(arguments);
return r;
}
function glGenTextures(count, ids_ptr, ids_size)
{
for (let i = 0; i < count; i++)
{
const tex = gl.createTexture();
glErrorReport(arguments);
let new_len = glTextures.push(tex);
put_u32(ids_ptr + (i * 4), new_len);
}
}
function glBindTexture(slot, id)
{
let tex = gl_get_texture(id);
const r = gl.bindTexture(slot, tex);
glErrorReport(arguments);
return r;
}
function glTexParameteri(slot, param, value)
{
const r = gl.texParameteri(slot, param, value);
glErrorReport(arguments);
return r;
}
function glTexImage2D(target, level, internalformat, width, height, border, format, type, data_ptr, data_size)
{
const data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, data_ptr, data_size);
const r = gl.texImage2D(target, level, internalformat, width, height, border, format, type, data);
glErrorReport(arguments);
return r;
}
function glTexSubImage2D(target, level, offsetx, offsety, width, height, format, type, data_ptr, data_size)
{
const data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, data_ptr, data_size);
const r = gl.texSubImage2D(target, level, offsetx, offsety, width, height, format, type, data);
glErrorReport(arguments);
return r;
}
function webgl_add_imports (canvas_selector, imports) {
const canvas = document.querySelector(canvas_selector);
if (!canvas) return console.error("no canvas");
gl = canvas.getContext("webgl");
gl = canvas.getContext("webgl2");
if (gl === null) return console.error("no webgl ctx");
console.log(
gl.FLOAT.toString(16), "\n",
gl.UNSIGNED_INT.toString(16), "\n"
);
imports.glHadError = () => { return gl_error; };
imports.glClearColor = glClearColor;
imports.glEnable = glEnable;
imports.glDisable = glDisable;
@ -269,6 +425,11 @@ function webgl_add_imports (canvas_selector, imports) {
imports.glVertexAttribPointer = glVertexAttribPointer;
imports.glEnableVertexAttribArray = glEnableVertexAttribArray;
imports.glDrawElements = glDrawElements;
imports.glGenTextures = glGenTextures;
imports.glBindTexture = glBindTexture;
imports.glTexParameteri = glTexParameteri;
imports.glTexImage2D = glTexImage2D;
imports.glTexSubImage2D = glTexSubImage2D;
imports.glBindTexture = glBindTexture;
return imports;
}

View File

@ -0,0 +1 @@
OpenGL Version: 3.3.0 - Build 27.20.100.9778

View File

@ -8,147 +8,147 @@
internal void
Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse, context Context)
{
DEBUG_TRACK_FUNCTION;
DEBUG_TRACK_FUNCTION;
b32 MouseInputHandled = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State);
gs_string TextInputString = PushString(State->Transient, 32);
panel* ActivePanel = PanelSystem_GetPanelContainingPoint(&State->PanelSystem, Mouse.Pos);
if (ActivePanel)
{
panel_definition ActiveDef = State->PanelSystem.PanelDefs[ActivePanel->TypeIndex];
b32 MouseInputHandled = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State);
gs_string TextInputString = PushString(State->Transient, 32);
panel* ActivePanel = PanelSystem_GetPanelContainingPoint(&State->PanelSystem, Mouse.Pos);
if (ActivePanel)
input_command_registry ActiveCommands = {};
if (State->Modes.ActiveModesCount > 0)
{
panel_definition ActiveDef = State->PanelSystem.PanelDefs[ActivePanel->TypeIndex];
input_command_registry ActiveCommands = {};
if (State->Modes.ActiveModesCount > 0)
{
ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands;
}
else if (ActiveDef.InputCommands)
{
ActiveCommands.Commands = ActiveDef.InputCommands;
ActiveCommands.Size = sizeof(*ActiveDef.InputCommands) / sizeof(ActiveDef.InputCommands[0]);
ActiveCommands.Used = ActiveCommands.Size;
}
// Fill up the command queue
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{
input_entry Event = InputQueue.Entries[EventIdx];
bool IsMouseEvent = (Event.Key == KeyCode_MouseLeftButton ||
Event.Key == KeyCode_MouseMiddleButton ||
Event.Key == KeyCode_MouseRightButton);
if (IsMouseEvent && MouseInputHandled)
{
continue;
}
// NOTE(Peter): These are in the order Down, Up, Held because we want to privalege
// Down and Up over Held. In other words, we don't want to call a Held command on the
// frame when the button was released, even if the command is registered to both events
if (KeyTransitionedDown(Event))
{
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue))
{
char KeyASCII = KeyCodeToChar(Event.Key);
if (KeyASCII)
{
OutChar(&TextInputString, KeyASCII);
}
}
}
else if (KeyTransitionedUp(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue);
}
else if (KeyHeldDown(Event))
{
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue))
{
char KeyASCII = KeyCodeToChar(Event.Key);
if (KeyASCII)
{
OutChar(&TextInputString, KeyASCII);
}
}
}
}
ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands;
}
else if (ActiveDef.InputCommands)
{
ActiveCommands.Commands = ActiveDef.InputCommands;
ActiveCommands.Size = sizeof(*ActiveDef.InputCommands) / sizeof(ActiveDef.InputCommands[0]);
ActiveCommands.Used = ActiveCommands.Size;
}
// Execute all commands in CommandQueue
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
// Fill up the command queue
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
if (Entry->Command.Proc)
input_entry Event = InputQueue.Entries[EventIdx];
bool IsMouseEvent = (Event.Key == KeyCode_MouseLeftButton ||
Event.Key == KeyCode_MouseMiddleButton ||
Event.Key == KeyCode_MouseRightButton);
if (IsMouseEvent && MouseInputHandled)
{
continue;
}
// NOTE(Peter): These are in the order Down, Up, Held because we want to privalege
// Down and Up over Held. In other words, we don't want to call a Held command on the
// frame when the button was released, even if the command is registered to both events
if (KeyTransitionedDown(Event))
{
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue))
{
Entry->Command.Proc(State, Entry->Event, Mouse, Context, ActivePanel);
char KeyASCII = KeyCodeToChar(Event.Key);
if (KeyASCII)
{
OutChar(&TextInputString, KeyASCII);
}
}
else
}
else if (KeyTransitionedUp(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue);
}
else if (KeyHeldDown(Event))
{
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue))
{
EndCurrentOperationMode(State);
char KeyASCII = KeyCodeToChar(Event.Key);
if (KeyASCII)
{
OutChar(&TextInputString, KeyASCII);
}
}
}
}
State->Interface.TempInputString = TextInputString.ConstString;
ClearCommandQueue(&State->CommandQueue);
}
// Execute all commands in CommandQueue
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
{
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
if (Entry->Command.Proc)
{
Entry->Command.Proc(State, Entry->Event, Mouse, Context, ActivePanel);
}
else
{
EndCurrentOperationMode(State);
}
}
State->Interface.TempInputString = TextInputString.ConstString;
ClearCommandQueue(&State->CommandQueue);
}
internal void
Editor_Update(app_state* State, context* Context, input_queue InputQueue)
{
Context->Mouse.CursorType = CursorType_Arrow;
State->WindowBounds = Context->WindowBounds;
State->Interface.Mouse = Context->Mouse;
State->Interface.HotWidgetFramesSinceUpdate += 1;
if (State->Interface.HotWidgetFramesSinceUpdate > 1)
{
State->Interface.HotWidget = {};
}
Assert(State->Interface.PerFrameMemory &&
(u64)State->Interface.PerFrameMemory != 0x5);
PanelSystem_UpdateLayout(&State->PanelSystem, State->WindowBounds);
Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context);
Context->Mouse.CursorType = CursorType_Arrow;
State->WindowBounds = Context->WindowBounds;
State->Interface.Mouse = Context->Mouse;
State->Interface.HotWidgetFramesSinceUpdate += 1;
if (State->Interface.HotWidgetFramesSinceUpdate > 1)
{
State->Interface.HotWidget = {};
}
Assert(State->Interface.PerFrameMemory &&
(u64)State->Interface.PerFrameMemory != 0x5);
PanelSystem_UpdateLayout(&State->PanelSystem, State->WindowBounds);
Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context);
}
internal void
Editor_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer)
{
State->Interface.WindowBounds = Context->WindowBounds;
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
PushRenderClearScreen(RenderBuffer);
State->Interface.WindowBounds = Context->WindowBounds;
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
PushRenderClearScreen(RenderBuffer);
ui_InterfaceReset(&State->Interface);
State->Interface.RenderBuffer = RenderBuffer;
ui_PushLayout(&State->Interface, Context->WindowBounds, LayoutDirection_TopDown, MakeString("Editor Layout"));
{
DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context);
ui_InterfaceReset(&State->Interface);
State->Interface.RenderBuffer = RenderBuffer;
ui_PushLayout(&State->Interface, Context->WindowBounds, LayoutDirection_TopDown, MakeString("Editor Layout"));
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
{
DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context);
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
{
operation_mode OperationMode = State->Modes.ActiveModes[m];
if (OperationMode.Render != 0)
{
OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context);
}
}
operation_mode OperationMode = State->Modes.ActiveModes[m];
if (OperationMode.Render != 0)
{
OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context);
}
}
ui_PopLayout(&State->Interface, MakeString("Editor Layout"));
// Draw the Interface
if (State->Interface.DrawOrderRoot != 0)
{
ui_widget* Widget = State->Interface.DrawOrderRoot;
Editor_DrawWidgetList(State, Context, RenderBuffer, Widget, Context->WindowBounds);
}
Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext);
}
ui_PopLayout(&State->Interface, MakeString("Editor Layout"));
// Draw the Interface
if (State->Interface.DrawOrderRoot != 0)
{
ui_widget* Widget = State->Interface.DrawOrderRoot;
Editor_DrawWidgetList(State, Context, RenderBuffer, Widget, Context->WindowBounds);
}
Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext);
}

View File

@ -1,8 +1,101 @@
static r32 z_ = 0;
static r32 r_ = 0.3f;
static r32 quad_verts[] = {
-r_, -r_, z_, 1.0f, 0, 0,
r_, -r_, z_, 1.0f, 1, 0,
r_, r_, z_, 1.0f, 1, 1,
-r_, r_, z_, 1.0f, 0, 1,
};
static u32 quad_indices[] = {
0, 1, 2,
0, 2, 3,
};
static String shader_code_vert_win32 = lit_str(
"#version 330 core\n"
"layout (location = 0) in vec4 coordinates;\n"
"layout (location = 1) in vec2 uv;\n"
"out vec2 tex_coord;\n"
"void main(void) {\n"
" gl_Position = coordinates;\n"
" tex_coord = uv;\n"
"}"
);
static String shader_code_vert_wasm = lit_str(
"precision highp float;\n"
"attribute vec4 coordinates;\n"
"attribute vec2 uv;\n"
"varying vec2 tex_coord;\n"
"void main(void) {\n"
" gl_Position = coordinates;\n"
" tex_coord = uv;\n"
"}");
static String shader_code_frag_win32 = lit_str(
"#version 330 core\n"
"in vec2 tex_coord;\n"
"out vec4 FragColor;\n"
"uniform sampler2D texture;\n"
"void main(void) {\n"
"// FragColor = vec4(1,tex_coord.x,tex_coord.y,1);\n"
" FragColor = texture(texture, tex_coord);\n"
"}"
);
static String shader_code_frag_wasm = lit_str(
"precision highp float;\n"
"varying vec2 tex_coord;\n"
"uniform sampler2D texture;\n"
"void main(void) {\n"
" gl_FragColor = texture2D(texture, tex_coord);\n"
" // vec4(1, tex_coord.x, tex_coord.y, 1);\n"
"}");
static u32 pix[] = {
0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000,
0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000,
};
void make_quad(Platform_Geometry_Buffer* geo, Platform_Shader* shd, Platform_Texture* tex)
{
// TODO(PS): TEMP
#if defined(PLATFORM_win32)
String shader_code_vert = shader_code_vert_win32;
String shader_code_frag = shader_code_frag_win32;
#elif defined(PLATFORM_wasm)
String shader_code_vert = shader_code_vert_wasm;
String shader_code_frag = shader_code_frag_wasm;
#endif
*geo = platform_geometry_buffer_create(
quad_verts, 24, quad_indices, 6
);
String attribs[] = {
lit_str("coordinates"),
lit_str("uv"),
};
*shd = platform_shader_create(
shader_code_vert, shader_code_frag, attribs, 2
);
platform_vertex_attrib_pointer(*geo, *shd, 4, shd->attrs[0], 6, 0);
platform_vertex_attrib_pointer(*geo, *shd, 2, shd->attrs[1], 6, 4);
*tex = platform_texture_create((u8*)pix, 4, 4, 4);
}
internal void
ed_init(App_State* state)
{
Editor* editor = allocator_alloc_struct(permanent, Editor);
state->editor = editor;
make_quad(&editor->renderer.geo, &editor->renderer.shd, &editor->renderer.tex);
}
internal void
@ -14,6 +107,13 @@ ed_frame_prepare(App_State* state)
internal void
ed_frame(App_State* state)
{
for (u32 i = 0; i < 16; i++)
{
if (i % 2 == 1) continue;
pix[i] += 1;
}
platform_texture_update(state->editor->renderer.tex, (u8*)pix, 4, 4, 4);
edr_render(state);
}

View File

@ -0,0 +1,12 @@
/* date = March 27th 2022 0:50 pm */
#ifndef LUMENARIUM_EDITOR_H
#define LUMENARIUM_EDITOR_H
struct Editor
{
v2 window_dim;
Editor_Renderer renderer;
};
#endif //LUMENARIUM_EDITOR_H

View File

@ -1,82 +1,4 @@
internal void
edr_init(App_State* state)
{
v4 quad_verts[] = {
-0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f,
00.5f, -0.5f, 0.0f, 1.0f,
00.5f, 0.5f, 0.0f, 1.0f,
};
u32 quad_indices[] = {
3, 2, 1,
3, 1, 0,
};
char* shader_code_vert =
"#version 140\n"
"attribute vec4 coordinates;\n"
"void main(void) {\n"
" gl_Position = coordinates;\n"
"}";
char* shader_code_frag =
"#version 140\n"
"void main(void) {\n"
" gl_FragColor = vec4(1, 0, 1, 1);\n"
"}";
#if 0
/* ======= Geometry =======*/
glCreateBuffers(1, &buffer_vertex);
glBindBuffer(GL_ARRAY_BUFFER, buffer_vertex);
glBufferData(GL_ARRAY_BUFFER, quad_verts, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glCreateBuffer(1, &buffer_index);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_index);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, quad_indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
/* ======= Shaders =======*/
shader_vert = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader_vertex, shader_code_vert);
glCompileShader(shader_vert);
shader_frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(shader_frag, shader_code_frag);
glCompileShader(shader_frag);
shader_prog = glCreateProgram();
glAttachShader(shader_prog, shader_vert);
glAttachShader(shader_prog, shader_frag);
glLinkProgram(shader_prog);
glUseProgram(shader_prog);
/* ======= Associating shaders to buffer objects =======*/
glBindBuffer(GL_ARRAY_BUFFER, buffer_vertex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_index);
coord = glGetAttribLocation(shader_prog, "coordinates");
glVertexAttribPointer(coord, 4, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(coord);
#endif
}
internal void
edr_render_quad()
{
#if 0
glBindBuffer(GL_ARRAY_BUFFER, buffer_vertex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_index);
glEnableVertexAttribArray(coord);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
#endif
}
internal void
edr_render(App_State* state)
@ -84,11 +6,12 @@ edr_render(App_State* state)
Platform_Graphics_Frame_Desc desc = {};
desc.clear_color = { 0.1f, 0.1f, 0.1f, 1 };
desc.viewport_min = { 0, 0 };
desc.viewport_max = { 1600, 900 };
desc.viewport_max = state->editor->window_dim;
platform_frame_begin(desc);
platform_frame_clear();
#if 0
edr_render_quad();
#endif
platform_geometry_bind(state->editor->renderer.geo);
platform_texture_bind(state->editor->renderer.tex);
platform_shader_bind(state->editor->renderer.shd);
platform_geometry_draw(state->editor->renderer.geo);
}

View File

@ -5,7 +5,9 @@
struct Editor_Renderer
{
Platform_Shader shd;
Platform_Geometry_Buffer geo;
Platform_Texture tex;
};
#endif //LUMENARIUM_EDITOR_RENDERER_H

View File

@ -0,0 +1,36 @@
/* date = March 28th 2022 10:52 pm */
#ifndef LUMENARIUM_UI_H
#define LUMENARIUM_UI_H
struct Font_Glyph
{
u32 code_point;
v2 uv_min;
v2 uv_max;
};
struct Font_Glyph_Table
{
Font_Glyph* values;
u32 cap;
u32 len;
};
struct Font_Bitmap
{
u8* pixels;
u32 width;
u32 height;
u32 stride;
Platform_Texture texture;
};
struct Font
{
Font_Glyph_Table glyphs;
Font_Bitmap bitmap;
};
#endif //LUMENARIUM_UI_H

View File

@ -1,73 +1,6 @@
#include "lumenarium_first.h"
#include "user_space/user_space_incenter.cpp"
Platform_Geometry_Buffer quad0;
Platform_Shader shader0;
static r32 z_ = 0;
static r32 r_ = 0.3f;
static r32 quad_verts[] = {
-r_, -r_, z_, 1.0f,
r_, -r_, z_, 1.0f,
r_, r_, z_, 1.0f,
-r_, r_, z_, 1.0f,
};
static u32 quad_indices[] = {
0, 1, 2,
0, 2, 3,
};
static String shader_code_vert_win32 = lit_str(
"#version 330 core\n"
"layout (location = 0) in vec4 coordinates;\n"
"void main(void) {\n"
" gl_Position = coordinates;\n"
"}"
);
static String shader_code_vert_wasm = lit_str(
"attribute vec4 coordinates;\n"
"void main(void) {\n"
" gl_Position = coordinates;\n"
"}");
static String shader_code_frag_win32 = lit_str(
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main(void) {\n"
" FragColor = vec4(1,0,1,1);\n"
"}"
);
static String shader_code_frag_wasm = lit_str(
"void main(void) {\n"
" gl_FragColor = vec4(1, 0, 1, 1);\n"
"}");
void make_quad()
{
// TODO(PS): TEMP
#if defined(PLATFORM_win32)
String shader_code_vert = shader_code_vert_win32;
String shader_code_frag = shader_code_frag_win32;
#elif defined(PLATFORM_wasm)
String shader_code_vert = shader_code_vert_wasm;
String shader_code_frag = shader_code_frag_wasm;
#endif
quad0 = platform_geometry_buffer_create(
quad_verts, 16, quad_indices, 6
);
String attribs[] = { lit_str("coordinates") };
shader0 = platform_shader_create(
shader_code_vert, shader_code_frag, attribs, 1
);
platform_vertex_attrib_pointer(quad0, shader0, 0);
}
internal App_State*
lumenarium_init()
{
@ -76,7 +9,6 @@ lumenarium_init()
permanent = bump_allocator_create_reserve(MB(4));
scratch = bump_allocator_create_reserve(KB(64));
run_tests();
App_Init_Desc desc = incenter_get_init_desc();
@ -84,19 +16,16 @@ lumenarium_init()
state = allocator_alloc_struct(permanent, App_State);
add_flag(state->flags, AppState_IsRunning);
add_flag(state->flags, AppState_RunEditor);
state->input_state = input_state_create();
en_init(state, desc);
if (!has_flag(state->flags, AppState_NoEditor))
if (has_flag(state->flags, AppState_RunEditor))
{
ed_init(state);
}
incenter_init(state);
make_quad();
return state;
}
@ -108,7 +37,7 @@ lumenarium_frame_prepare(App_State* state)
input_state_swap_frames(&state->input_state);
en_frame_prepare(state);
if (!has_flag(state->flags, AppState_NoEditor))
if (has_flag(state->flags, AppState_RunEditor))
{
ed_frame_prepare(state);
}
@ -119,23 +48,9 @@ internal void
lumenarium_frame(App_State* state)
{
en_frame(state);
if (!has_flag(state->flags, AppState_NoEditor))
if (has_flag(state->flags, AppState_RunEditor))
{
//ed_frame(state);
Platform_Graphics_Frame_Desc desc = {};
desc.clear_color = { 0.1f, 0.1f, 0.1f, 1 };
desc.viewport_min = { 0, 0 };
desc.viewport_max = { 1600, 900 };
platform_frame_begin(desc);
platform_frame_clear();
platform_geometry_bind(quad0);
platform_shader_bind(shader0);
platform_geometry_draw(quad0);
ed_frame(state);
}
incenter_frame(state);
}
@ -176,7 +91,7 @@ lumenarium_cleanup(App_State* state)
{
incenter_cleanup(state);
en_cleanup(state);
if (!has_flag(state->flags, AppState_NoEditor))
if (has_flag(state->flags, AppState_RunEditor))
{
ed_cleanup(state);
}

View File

@ -15,6 +15,7 @@ typedef struct App_State App_State;
// Editor
#include "editor/lumenarium_editor_renderer.h"
#include "editor/lumenarium_editor.h"
//////////////////////////////////////////////
// Lumenarium Runtime Environment
@ -36,7 +37,7 @@ enum
{
AppState_None = 0,
AppState_IsRunning = 1,
AppState_NoEditor = 2,
AppState_RunEditor = 2,
};
struct App_Init_Desc
@ -50,6 +51,8 @@ struct App_State
Input_State input_state;
Assembly_Array assemblies;
Editor* editor;
};
#include "engine/lumenarium_engine_assembly.cpp"

View File

@ -7,7 +7,8 @@ c_str_len(char* s)
return result;
}
#define str_varg(str) (int)(str).len, (char*)(str).str
#define str_varg(s) (int)(s).len, (char*)(s).str
#define str_expand(s) (char*)(s).str, (u64)(s).len
#define lit_str(s) String{ (u8*)(s), (u64)sizeof(s)-1, (u64)sizeof(s)-1 }
internal String

View File

@ -3,27 +3,47 @@
#ifndef LUMENARIUM_ASSERT_H
#define LUMENARIUM_ASSERT_H
#if defined(PRINT_ASSERTS)
# include <stdio.h>
# define err_write(s,...) err_write_(s,__VA_ARGS__)
static FILE* file_err;
void err_write_(char* fmt, ...) {
if (!file_err) return;
va_list args;
va_start(args, fmt);
vfprintf(file_err, fmt, args);
va_end(args);
}
void open_err_file() { file_err = fopen("./err.txt", "wb"); }
void close_err_file() { fclose(file_err); }
#else
# define err_write(s,...)
void open_err_file() {}
void close_err_file() {}
#endif
#if !defined(PLATFORM_wasm)
// this assert works by simply trying to write to an invalid address
// (in this case, 0x0), which will crash in most debuggers
# define assert_always (*((volatile s32*)0) = 0xFFFF)
#else
WASM_EXTERN void wasm_assert_always(char* file, u32 file_len, u32 line);
WASM_EXTERN void wasm_assert_always(char* file, unsigned int file_len, unsigned int line);
# define assert_always wasm_assert_always(__FILE__, sizeof(__FILE__), __LINE__)
#endif // defined(PLATFORM_WASM)
#ifdef USE_ASSERTS
# define assert(c) if (!(c)) { assert_always; }
# define assert(c) if (!(c)) { err_write("Assert Hit: %s:%d\n", __FILE__, (u32)__LINE__); close_err_file(); assert_always; }
// useful for catching cases that you aren't sure you'll hit, but
// want to be alerted when they happen
# define invalid_code_path assert_always
# define invalid_code_path assert(0);
// useful for switch statements on enums that might grow. You'll
// break in the debugger the first time the default case is hit
// with a new enum value
# define invalid_default_case default: { assert_always; } break;
# define invalid_default_case default: { assert(0); } break;
#else
# define assert(c)

View File

@ -309,6 +309,13 @@ struct Platform_Geometry_Buffer
u32 indices_len;
};
struct Platform_Texture
{
u32 id;
u32 w, h, s;
};
struct Platform_Graphics_Frame_Desc
{
v4 clear_color;
@ -319,18 +326,23 @@ struct Platform_Graphics_Frame_Desc
void platform_frame_begin(Platform_Graphics_Frame_Desc desc);
void platform_frame_clear();
// Geometry
Platform_Geometry_Buffer platform_geometry_buffer_create(r32* vertices, u32 vertices_len, u32* indices, u32 indices_len);
Platform_Shader platform_shader_create(
String code_vert, String code_frag, String* attribs, u32 attribs_len
);
void platform_vertex_attrib_pointer(
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 attrib_index
);
// Shaders
void platform_geometry_bind(Platform_Geometry_Buffer geo);
void platform_shader_bind(Platform_Shader shader);
void platform_geometry_draw(Platform_Geometry_Buffer geo);
void platform_vertex_attrib_pointer(
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 attr_index
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 count, u32 attr_index, u32 stride, u32 offset
);
// Textures
Platform_Texture platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride);
void platform_texture_bind(Platform_Texture tex);
void platform_texture_update(Platform_Texture tex, u8* new_pixels, u32 width, u32 height, u32 stride);
#endif //LUMENARIUM_PLATFORM_H

View File

@ -13,9 +13,13 @@
#include "lumenarium_assert.h"
#include "glcorearb.h"
#include "glext.h"
#include "wglext.h"
// NOTE(PS): only need the opengl extension headers
// when running on a platform that is using opengl 3.3+
#if !defined(PLATFORM_wasm)
# include "glcorearb.h"
# include "glext.h"
# include "wglext.h"
#endif
#if 0
#define HMM_SINF sin

View File

@ -25,6 +25,8 @@ WASM_EXTERN void print(const char* text, int len);
typedef void wasm_animation_frame_cb(u32 time_elapsed);
WASM_EXTERN void wasm_request_animation_frame(wasm_animation_frame_cb* cb);
WASM_EXTERN void wasm_get_canvas_dim(u32* w_ptr, u32* h_ptr);
EXTERN_C_BEGIN;
int
@ -46,14 +48,25 @@ update(u32 time_elapsed)
lumenarium_frame(wasm_app_state);
// TODO(PS): check for app running flags
wasm_request_animation_frame(update);
if (!glHadError())
{
wasm_request_animation_frame(update);
}
}
WASM_EXPORT int
main(void)
{
wasm_app_state = lumenarium_init();
//wasm_request_animation_frame(update);
if (has_flag(wasm_app_state->flags, AppState_RunEditor))
{
u32 w, h;
wasm_get_canvas_dim(&w, &h);
wasm_app_state->editor->window_dim = v2{
(r32)w, (r32)h
};
}
wasm_request_animation_frame(update);
return 0;
#if 0

View File

@ -34,6 +34,35 @@ function wasm_get_proc(inst, proc_ptr)
function fract (v) { return v % 1; }
function u32_to_byte_array_32 (v)
{
let result = [0, 0, 0, 0];
result[0] = (v & 0xff);
result[1] = (((v - result[0]) >> 8 ) & 0xff);
result[2] = (((v - result[1]) >> 16) & 0xff);
result[3] = (((v - result[2]) >> 24) & 0xff);
return result;
}
function byte_array_32_to_u32 (arr)
{
// NOTE(PS): the '>>>' operators in this function deal with the fact
// that bit shift operators convert numbers to s32's. The >>> just
// converts them back to u32s
let r0 = ((arr[0] & 0xff) << 0 );
let r1 = ((arr[1] & 0xff) << 8 );
let r2 = ((arr[2] & 0xff) << 16);
let r3 = (((arr[3] & 0xff) << 24) >>> 0);
let result = (r0 | r1 | r2 | r3) >>> 0;
return result;
}
function put_u32 (ptr, value)
{
let src = u32_to_byte_array_32(value);
wasm_write_bytes(lumenarium_wasm_instance, src, ptr, 4);
}
var lumenarium_wasm_imports = {
memset: (dst, size, value) => {
@ -122,12 +151,46 @@ var lumenarium_wasm_imports = {
let string = wasm_read_string(lumenarium_wasm_instance, str_base, len);
console.log(string);
},
wasm_get_canvas_dim: (w_ptr, h_ptr) => {
const canvas = document.querySelector("#gl_canvas");
let w_view = wasm_mem_get_u8_arr(lumenarium_wasm_instance, w_ptr, 4);
let w = canvas.width;
let wb = u32_to_byte_array_32(w);
for (let i = 0; i < 4; i++) w_view[i] = wb[i];
let h_view = wasm_mem_get_u8_arr(lumenarium_wasm_instance, h_ptr, 4);
let h = canvas.height;
let hb = u32_to_byte_array_32(h);
for (let i = 0; i < 4; i++) h_view[i] = hb[i];
},
};
///////////////////////////////////////
// Web GL Imports
let gl = null;
let gl_error = false;
function glErrorReport(outer_args) {
const err = gl.getError();
if (err == gl.NO_ERROR) return;
gl_error = true;
let msg = "";
switch (err) {
case gl.NO_ERROR: { msg = "NO_ERROR"; } break;
case gl.INVALID_ENUM: { msg = "INVALID_ENUM"; } break;
case gl.INVALID_VALUE: { msg = "INVALID_VALUE"; } break;
case gl.INVALID_OPERATION: { msg = "INVALID_OPERATION"; } break;
case gl.INVALID_FRAMEBUFFER_OPERATION: { msg = "INVALID_FRAMEBUFFER_OPERATION"; } break;
case gl.OUT_OF_MEMORY: { msg = "OUT_OF_MEMORY"; } break;
case gl.CONTEXT_LOST_WEBGL: { msg = "CONTEXT_LOST_WEBGL"; } break;
default: { msg = "Uknown error"; } break;
}
console.error(`WebGL Error: ${msg} ${err}`, outer_args);
}
// NOTE(PS): it seems like its not enough to set
// the values of imports to gl.function
@ -135,16 +198,37 @@ let gl = null;
// instead we need to wrap them for some reason.
// Not sure why
function glClearColor (r, g, b, a) { return gl.clearColor(r,g,b,a); }
function glEnable(v) { return gl.enable(v); }
function glDisable(v) { return gl.disable(v); }
function glBlendFunc(a,b) { return gl.blendFunc(a,b); }
function glEnable(v) {
const r = gl.enable(v);
glErrorReport(arguments);
return r;
}
function glDisable(v) {
const r = gl.disable(v);
glErrorReport(arguments);
return r;
}
function glBlendFunc(a,b) {
const r = gl.blendFunc(a,b);
glErrorReport(arguments);
return r;
}
function glViewport(xmin, ymin, xmax, ymax) { return gl.viewport(xmin,ymin,xmax,ymax); }
function glDepthFunc(v) { return gl.depthFunc(v); }
function glClear(mask) { return gl.clear(mask); }
function glDepthFunc(v) {
const r = gl.depthFunc(v);
glErrorReport(arguments);
return r;
}
function glClear(mask) {
const r = gl.clear(mask);
glErrorReport(arguments);
return r;
}
let glBuffers = [];
let glShaders = [];
let glPrograms = [];
let glTextures = [];
function gl_get_managed_resource(arr, id) {
if (id == 0) return null;
return arr[id - 1];
@ -152,55 +236,76 @@ function gl_get_managed_resource(arr, id) {
function gl_get_buffer(id) { return gl_get_managed_resource(glBuffers, id); }
function gl_get_shader(id) { return gl_get_managed_resource(glShaders, id); }
function gl_get_program(id) { return gl_get_managed_resource(glPrograms, id); }
function gl_get_texture(id) { return gl_get_managed_resource(glTextures, id); }
function glCreateBuffer() {
let buffer = gl.createBuffer();
glErrorReport(arguments);
let new_len = glBuffers.push(buffer);
return new_len;
}
function glBindBuffer(buffer_kind, buffer_id)
{
return gl.bindBuffer(buffer_kind, gl_get_buffer(buffer_id));
const r = gl.bindBuffer(buffer_kind, gl_get_buffer(buffer_id));
glErrorReport(arguments);
return r;
}
function glBufferData(target, size, ptr, usage)
{
let data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, ptr, size);
return gl.bufferData(target, data, usage);
const r = gl.bufferData(target, data, usage);
glErrorReport(arguments);
return r;
}
function glCreateShader(kind)
{
let shader = gl.createShader(kind);
glErrorReport(arguments);
let new_len = glShaders.push(shader);
return new_len;
}
function glShaderSource(shader_id, shader_code, shader_code_len)
{
let str = wasm_read_string(lumenarium_wasm_instance, shader_code, shader_code_len);
console.error("For some reason, str isn't getting the correct data out of here", str);
return gl.shaderSource(gl_get_shader(shader_id), str);
const r = gl.shaderSource(gl_get_shader(shader_id), str);
glErrorReport(arguments);
return r;
}
function glCompileShader(shader_id)
{
let s = gl_get_shader(shader_id);
let r = gl.compileShader(s);
glErrorReport(arguments);
let m = gl.getShaderInfoLog(s);
glErrorReport(arguments);
if (m.length > 0)
{
console.error("glCompileShader: \n\n" + m);
}
}
function glCreateProgram()
{
let prog = gl.createProgram();
glErrorReport(arguments);
let new_len = glPrograms.push(prog);
return new_len;
}
function glAttachShader(program, shader)
{
let s = gl_get_shader(shader);
let p = gl_get_program(program);
return gl.attachShader(p, s);
const r = gl.attachShader(p, s);
glErrorReport(arguments);
return r;
}
function glLinkProgram(program)
{
let p = gl_get_program(program);
@ -210,43 +315,94 @@ function glLinkProgram(program)
console.error("Failed to compile WebGL program. \n\n"+info);
}
}
function glUseProgram(program)
{
let p = gl_get_program(program);
return gl.useProgram(p);
const r = gl.useProgram(p);
glErrorReport(arguments);
return r;
}
function glGetAttribLocation(program, name, name_len)
{
let str = wasm_read_string(lumenarium_wasm_instance, name, name_len);
return gl.getAttribLocation(gl_get_program(program), str);
const r = gl.getAttribLocation(gl_get_program(program), str);
glErrorReport(arguments);
return r;
}
function glVertexAttribPointer(attr, size, type, normalized, stride, pointer)
{
return gl.vertexAttribPointer(attr, size, type, normalized, stride, pointer);
const r = gl.vertexAttribPointer(attr, size, type, normalized, stride, pointer);
glErrorReport(arguments);
return r;
}
function glEnableVertexAttribArray(index)
{
return gl.enableVertexAttribArray(index);
const r = gl.enableVertexAttribArray(index);
glErrorReport(arguments);
return r;
}
function glDrawElements(type, index_count, ele_type, indices)
{
return gl.drawElements(type, index_count, ele_type, indices);
const r = gl.drawElements(type, index_count, ele_type, indices);
glErrorReport(arguments);
return r;
}
function glGenTextures(count, ids_ptr, ids_size)
{
for (let i = 0; i < count; i++)
{
const tex = gl.createTexture();
glErrorReport(arguments);
let new_len = glTextures.push(tex);
put_u32(ids_ptr + (i * 4), new_len);
}
}
function glBindTexture(slot, id)
{
let tex = gl_get_texture(id);
const r = gl.bindTexture(slot, tex);
glErrorReport(arguments);
return r;
}
function glTexParameteri(slot, param, value)
{
const r = gl.texParameteri(slot, param, value);
glErrorReport(arguments);
return r;
}
function glTexImage2D(target, level, internalformat, width, height, border, format, type, data_ptr, data_size)
{
const data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, data_ptr, data_size);
const r = gl.texImage2D(target, level, internalformat, width, height, border, format, type, data);
glErrorReport(arguments);
return r;
}
function glTexSubImage2D(target, level, offsetx, offsety, width, height, format, type, data_ptr, data_size)
{
const data = wasm_mem_get_u8_arr(lumenarium_wasm_instance, data_ptr, data_size);
const r = gl.texSubImage2D(target, level, offsetx, offsety, width, height, format, type, data);
glErrorReport(arguments);
return r;
}
function webgl_add_imports (canvas_selector, imports) {
const canvas = document.querySelector(canvas_selector);
if (!canvas) return console.error("no canvas");
gl = canvas.getContext("webgl");
gl = canvas.getContext("webgl2");
if (gl === null) return console.error("no webgl ctx");
console.log(
gl.FLOAT.toString(16), "\n",
gl.UNSIGNED_INT.toString(16), "\n"
);
imports.glHadError = () => { return gl_error; };
imports.glClearColor = glClearColor;
imports.glEnable = glEnable;
imports.glDisable = glDisable;
@ -269,6 +425,11 @@ function webgl_add_imports (canvas_selector, imports) {
imports.glVertexAttribPointer = glVertexAttribPointer;
imports.glEnableVertexAttribArray = glEnableVertexAttribArray;
imports.glDrawElements = glDrawElements;
imports.glGenTextures = glGenTextures;
imports.glBindTexture = glBindTexture;
imports.glTexParameteri = glTexParameteri;
imports.glTexImage2D = glTexImage2D;
imports.glTexSubImage2D = glTexSubImage2D;
imports.glBindTexture = glBindTexture;
return imports;
}

View File

@ -6,6 +6,7 @@
// TODO(PS): you guessed the data types and names of ALL of this
// fix it!
typedef int GLint;
typedef unsigned int GLuint;
typedef float GLfloat;
typedef unsigned int GLenum;
@ -35,9 +36,19 @@ typedef unsigned int GLsizei;
#define GL_FRAGMENT_SHADER 0x8b30
#define GL_VERTEX_SHADER 0x8b31
#define GL_TRIANGLES 0x0004
#define GL_UNSIGNED_INT 0x1406
#define GL_FLOAT 0x1405
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_REPEAT 0x2901
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_LINEAR 0x2601
#define GL_RGB 0x1907
#define GL_RGBA 0x1908
#define GL_UNSIGNED_BYTE 0x1401
WASM_EXTERN bool glHadError();
WASM_EXTERN void glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
WASM_EXTERN void glEnable(GLuint i);
WASM_EXTERN void glDisable(GLuint i);
@ -60,6 +71,12 @@ WASM_EXTERN GLuint glGetAttribLocation(GLuint program, const char* name, GLuint
WASM_EXTERN void glVertexAttribPointer(GLuint attr, GLuint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
WASM_EXTERN void glEnableVertexAttribArray(GLuint index);
WASM_EXTERN void glDrawElements(GLenum type, GLuint count, GLenum ele_type, void* indices);
WASM_EXTERN void glGenTextures(GLuint count, GLuint* ids, u32 ids_size);
WASM_EXTERN void glBindTexture(GLenum slot, GLuint id);
WASM_EXTERN void glTexParameteri(GLenum slot, GLenum param, GLenum value);
WASM_EXTERN void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * data, u32 data_size);
WASM_EXTERN void glBindTexture(GLenum target, GLuint id);
WASM_EXTERN void glTexSubImage2D(GLenum target, GLint level, GLuint offsetx, GLuint offsety, GLuint w, GLuint h, GLenum format, GLenum type, void* ptr, u32 ptr_size);
Platform_Geometry_Buffer
platform_geometry_buffer_create(
@ -97,13 +114,11 @@ platform_shader_create(
Platform_Shader result = {};
GLuint shader_vert = glCreateShader(GL_VERTEX_SHADER);
GLuint vert_len = (GLuint)code_vert.len;
glShaderSource(shader_vert, (char*)&code_vert.str, vert_len);
glShaderSource(shader_vert, str_expand(code_vert));
glCompileShader(shader_vert);
GLuint shader_frag = glCreateShader(GL_FRAGMENT_SHADER);
GLuint frag_len = (GLuint)code_frag.len;
glShaderSource(shader_frag, (char*)&code_frag.str, frag_len);
glShaderSource(shader_frag, str_expand(code_frag));
glCompileShader(shader_frag);
result.id = (GLuint)glCreateProgram();
@ -138,7 +153,7 @@ void
platform_shader_bind(Platform_Shader shader)
{
glUseProgram(shader.id);
for (GLuint i = 0; i < PLATFORM_SHADER_MAX_ATTRS && shader.attrs[i] != PLATFORM_SHADER_MAX_ATTRS; i++)
for (GLuint i = 0; i < PLATFORM_SHADER_MAX_ATTRS && shader.attrs[i] != PLATFORM_SHADER_ATTR_LAST; i++)
{
glEnableVertexAttribArray(shader.attrs[i]);
}
@ -152,11 +167,70 @@ platform_geometry_draw(
}
void platform_vertex_attrib_pointer(
Platform_Geometry_Buffer geo, Platform_Shader shader, GLuint attr_index
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 count, u32 attr_index, u32 stride, u32 offset
){
platform_shader_bind(shader);
//platform_shader_bind(shader);
platform_geometry_bind(geo);
glVertexAttribPointer(shader.attrs[attr_index], 4, GL_FLOAT, false, 0, 0);
glVertexAttribPointer(shader.attrs[attr_index], count, GL_FLOAT, false, stride * sizeof(float), (void*)(offset * sizeof(float)));
}
Platform_Texture
platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride)
{
Platform_Texture result = {};
glGenTextures(1, &result.id, sizeof(u32));
glBindTexture(GL_TEXTURE_2D, result.id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixels,
(width * height) * sizeof(u32)
);
result.w = width;
result.h = height;
result.s = stride;
return result;
}
void
platform_texture_update(Platform_Texture tex, u8* new_pixels, u32 width, u32 height, u32 stride)
{
// NOTE(PS): this function simply replaces the entire image
// we can write a more granular version if we need it
assert(tex.w == width && tex.h == height && tex.s == stride);
platform_texture_bind(tex);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
0, 0, // offset
width, height,
GL_RGBA,
GL_UNSIGNED_BYTE,
new_pixels,
width * height * sizeof(u32)
);
}
void
platform_texture_bind(Platform_Texture tex)
{
glBindTexture(GL_TEXTURE_2D, tex.id);
}
void

View File

@ -180,6 +180,8 @@ WinMain(
PSTR lpCmdLine,
INT nCmdShow)
{
open_err_file();
// Window Setup
win32_window_create(
&win32_main_window,
@ -189,6 +191,7 @@ WinMain(
900,
win32_window_event_handler
);
win32_window_update_dim(&win32_main_window);
win32_time_init();
win32_files_init();
@ -230,6 +233,15 @@ WinMain(
// using invalid resources
if (!running || !has_flag(state->flags, AppState_IsRunning)) continue;
// Update window size
if (has_flag(state->flags, AppState_RunEditor))
{
state->editor->window_dim = v2{
(r32)win32_main_window.info.width,
(r32)win32_main_window.info.height
};
}
lumenarium_frame(state);
SwapBuffers(win32_main_window.dc);
@ -261,6 +273,8 @@ WinMain(
// windows cleanup
UnregisterClass(win32_main_window.window_class.lpszClassName, hInstance);
close_err_file();
return 0;
}

View File

@ -1,12 +1,16 @@
#define win32_gl_no_error() win32_gl_no_error_()
void win32_gl_no_error_() {
#define win32_gl_no_error() win32_gl_no_error_(__FILE__, __LINE__)
void win32_gl_no_error_(char* file, u32 line) {
u32 error = glGetError();
char* str = 0;
if (error) {
str = win32_gl_error_to_string(error);
}
assert(error == 0);
if (error != 0)
{
err_write("OpenGL error: %s:%d\n\t%s :: %d\n", file, line, str, error);
invalid_code_path;
}
}
Platform_Geometry_Buffer
@ -64,7 +68,7 @@ platform_shader_create(
{ // errors
GLint shader_vert_compiled;
gl.glGetShaderiv(shader_vert, GL_COMPILE_STATUS, &shader_vert_compiled);
if (shader_vert_compiled != GL_TRUE)
if (!shader_vert_compiled)
{
GLsizei log_length = 0;
GLchar message[1024];
@ -79,7 +83,7 @@ platform_shader_create(
{ // errors
GLint shader_frag_compiled;
gl.glGetShaderiv(shader_frag, GL_COMPILE_STATUS, &shader_frag_compiled);
if (shader_frag_compiled != GL_TRUE)
if (!shader_frag_compiled)
{
GLsizei log_length = 0;
GLchar message[1024];
@ -122,7 +126,7 @@ platform_shader_create(
void
platform_geometry_bind(Platform_Geometry_Buffer geo)
{
gl.glBindVertexArray(geo.buffer_id_vertices);
gl.glBindVertexArray(geo.buffer_id_vao);
win32_gl_no_error();
gl.glBindBuffer(GL_ARRAY_BUFFER, geo.buffer_id_vertices);
@ -155,15 +159,76 @@ platform_geometry_draw(
}
void platform_vertex_attrib_pointer(
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 attr_index
Platform_Geometry_Buffer geo, Platform_Shader shader, GLuint count, GLuint attr_index, GLuint stride, GLuint offset
){
platform_geometry_bind(geo);
gl.glVertexAttribPointer(shader.attrs[attr_index], 4, GL_FLOAT, false, 0, 0);
gl.glVertexAttribPointer(shader.attrs[attr_index], count, GL_FLOAT, false, stride * sizeof(float), (void*)(offset * sizeof(float)));
win32_gl_no_error();
gl.glEnableVertexAttribArray(shader.attrs[attr_index]);
win32_gl_no_error();
}
Platform_Texture
platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride)
{
Platform_Texture result = {};
glGenTextures(1, &result.id);
win32_gl_no_error();
glBindTexture(GL_TEXTURE_2D, result.id);
win32_gl_no_error();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
win32_gl_no_error();
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixels
);
win32_gl_no_error();
result.w = width;
result.h = height;
result.s = stride;
return result;
}
void
platform_texture_update(Platform_Texture tex, u8* new_pixels, u32 width, u32 height, u32 stride)
{
// NOTE(PS): this function simply replaces the entire image
// we can write a more granular version if we need it
assert(tex.w == width && tex.h == height && tex.s == stride);
platform_texture_bind(tex);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
0, 0, // offset
width, height,
GL_RGBA,
GL_UNSIGNED_BYTE,
new_pixels
);
}
void
platform_texture_bind(Platform_Texture tex)
{
glBindTexture(GL_TEXTURE_2D, tex.id);
win32_gl_no_error();
}
void
platform_frame_begin(Platform_Graphics_Frame_Desc desc)
@ -180,10 +245,10 @@ platform_frame_begin(Platform_Graphics_Frame_Desc desc)
glDisable(GL_CULL_FACE);
//glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
win32_gl_no_error();
}
void

View File

@ -96,7 +96,6 @@ win32_window_create(
hinstance,
0
);
return true;
}
return false;
@ -333,12 +332,8 @@ win32_window_opengl_ctx_create_ext(HDC dc, Win32_Window_OpenGL_Info* info)
invalid_code_path;
}
#if 0
//char* version_string = (char*)glGetString(GL_VERSION);
OutputDebugStringA("OpenGL Version: ");
OutputDebugStringA(version_string);
OutputDebugStringA("\n");
#endif
char* version_string = (char*)glGetString(GL_VERSION);
err_write("OpenGL Version: %s\n", version_string);
}
internal void