From 0684c274d04470f7d61ca88a19ce79a5177a344b Mon Sep 17 00:00:00 2001 From: nukoseer Date: Sat, 20 Jan 2024 20:58:41 +0300 Subject: [PATCH] add get_uniform_location and set_uniform_2f --- build.bat | 2 +- demo.c | 162 ++++++++++++++++++++++++++++++++++--------------- demo.h | 5 +- demo.js | 54 ++++++++++++++--- memory_utils.h | 45 ++++++++++---- utils.h | 4 +- 6 files changed, 202 insertions(+), 70 deletions(-) diff --git a/build.bat b/build.bat index 9596d68..cf3b6ab 100644 --- a/build.bat +++ b/build.bat @@ -9,7 +9,7 @@ set common_compiler_flags=--target=wasm32 -nostdlib -Wall -Werror -Wno-unused-fu set debug_linker_flags= set release_linker_flags=-Wl,--lto-O3 -set common_linker_flags=-Wl,--no-entry -Wl,--allow-undefined -Wl,--export=render -Wl,--export=init +set common_linker_flags=-Wl,--no-entry -Wl,--allow-undefined -Wl,--export=update -Wl,--export=render -Wl,--export=init set debug=yes diff --git a/demo.c b/demo.c index 80add12..61c6137 100644 --- a/demo.c +++ b/demo.c @@ -101,14 +101,24 @@ static void use_program(GraphicsHandle graphics, ProgramHandle program) platform_use_program(graphics, program); } +static UniformHandle get_uniform_location(GraphicsHandle graphics, ProgramHandle program, const u8* name) +{ + return platform_get_uniform_location(graphics, program, name); +} + +static void set_uniform_2f(GraphicsHandle graphics, UniformHandle uniform, f32 f1, f32 f2) +{ + platform_set_uniform_2f(graphics, uniform, f1, f2); +} + static void draw(GraphicsHandle graphics, PrimitiveType primitive_type, u32 offset, u32 count) { platform_draw_arrays(graphics, primitive_type, offset, count); } -static void log_integer(u32 integer) +static void log_number(f32 number) { - platform_log_integer(integer); + platform_log_number(number); } static DrawBuffer* allocate_draw_buffer(MemoryArena* arena, memory_size size) @@ -117,7 +127,7 @@ static DrawBuffer* allocate_draw_buffer(MemoryArena* arena, memory_size size) draw_buffer->max_size = size; draw_buffer->size = 0; - draw_buffer->base = push_size(arena, draw_buffer->max_size); + draw_buffer->base = PUSH_SIZE(arena, draw_buffer->max_size); // draw_buffer->buffer = create_buffer(graphics); return draw_buffer; @@ -149,18 +159,38 @@ static void draw_rectangle(DrawBuffer* draw_buffer, f32 rectangle_data[] = { - x1, y1, r, g, b, - x2, y1, r, g, b, - x1, y2, r, g, b, - x1, y2, r, g, b, - x2, y1, r, g, b, - x2, y2, r, g, b, + x1, y1, 0.0f, 0.0f, r, g, b, + x2, y1, 1.0f, 0.0f, r, g, b, + x1, y2, 0.0f, 1.0f, r, g, b, + x1, y2, 0.0f, 1.0f, r, g, b, + x2, y1, 1.0f, 0.0f, r, g, b, + x2, y2, 1.0f, 1.0f, r, g, b, }; push_draw_data(draw_buffer, &rectangle_data, sizeof(rectangle_data)); } -void update(void) +typedef struct Rectangle { + f32 x, y; + f32 width, height; +} Rectangle; + +static Rectangle rectangle[2]; + +void update(f32 delta_time) +{ + // DrawBuffer* draw_buffer = state->draw_buffer; + + for (u32 i = 0; i < ARRAY_COUNT(rectangle); ++i) + { + Rectangle* rect = rectangle + i; + + if (rect->x >= (f32)state->width) + { + rect->x = 0.0f; + } + rect->x += 0.80f; + } } void render(void) @@ -168,9 +198,11 @@ void render(void) GraphicsState* graphics = &state->graphics; DrawBuffer* draw_buffer = state->draw_buffer; - clear_color(graphics->handle, 0.7f, 0.584f, 0.7, 1.0f); - draw_rectangle(draw_buffer, -0.25f, -0.25f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f); - draw_rectangle(draw_buffer, 0.0f, 0.0f, 0.01f, 0.01f, 1.0f, 1.0f, 1.0f); + clear_color(graphics->handle, 0.0f, 0.0f, 0.0f, 1.0f); + draw_rectangle(draw_buffer, rectangle[0].x, rectangle[0].y, rectangle[0].width, rectangle[0].height, 1.0f, 0.0f, 0.0f); + draw_rectangle(draw_buffer, rectangle[1].x, rectangle[1].y, rectangle[1].width, rectangle[1].height, 1.0f, 0.0f, 0.0f); + // draw_rectangle(draw_buffer, -0.25f, -0.25f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f); + // draw_rectangle(draw_buffer, 0.0f, 0.0f, 0.01f, 0.01f, 1.0f, 1.0f, 1.0f); bind_buffer(graphics->handle, graphics->vertex_buffer_handle, ARRAY_BUFFER_TYPE); set_buffer_data(graphics->handle, graphics->vertex_buffer_handle, draw_buffer->base, draw_buffer->size, ARRAY_BUFFER_TYPE); @@ -182,30 +214,31 @@ void render(void) reset_draw_buffer(draw_buffer); } -void init(u32 width, u32 height) +void graphics_init(void) { - MemoryArena* arena = get_memory_arena(&__heap_base, &__heap_base - &__data_end); - - state = PUSH_STRUCT(arena, State); - state->arena = arena; - state->width = width; - state->height = height; - - state->draw_buffer = allocate_draw_buffer(arena, KILOBYTES(2)); + state->draw_buffer = allocate_draw_buffer(state->arena, KILOBYTES(2)); const u8* vertex_shader_source = (const u8*) - "#version 300 es \n" - " \n" - "layout (location = 0) in vec2 a_position; \n" - "layout (location = 1) in vec3 a_color; \n" - " \n" - "out vec4 color; \n" - " \n" - "void main() \n" - "{ \n" - " gl_Position = vec4(a_position, 0.0, 1.0); \n" - " color = vec4(a_color, 1.0); \n" - "} \n"; + "#version 300 es \n" + " \n" + "layout (location = 0) in vec2 a_position; \n" + "layout (location = 1) in vec2 a_uv; \n" + "layout (location = 2) in vec3 a_color; \n" + " \n" + "uniform vec2 u_resolution; \n" + " \n" + "out vec4 color; \n" + "out vec2 uv; \n" + " \n" + "void main() \n" + "{ \n" + " vec2 zero_to_one = a_position / u_resolution; \n" + " vec2 clip_space = (zero_to_one * 2.0) - 1.0; \n" + " \n" + " gl_Position = vec4(clip_space, 0.0, 1.0); \n" + " color = vec4(a_color, 1.0); \n" + " uv = a_uv; \n" + "} \n"; const u8* pixel_shader_source = (const u8*) "#version 300 es \n" @@ -213,16 +246,24 @@ void init(u32 width, u32 height) "precision highp float; \n" " \n" "in vec4 color; \n" + "in vec2 uv; \n" " \n" "out vec4 out_color; \n" " \n" "void main() \n" "{ \n" - // " vec4 new_color = color; \n" - // " new_color.w = 0.5; \n" - " out_color = color; \n" + " vec2 n_uv = uv * 2.0 - 1.0; \n" + " vec2 border_size = vec2(1.5); \n" + " vec2 rectangle_size = vec2(1.0) - border_size; \n" + " \n" + " float distance_field = length(max(abs(n_uv) - rectangle_size, 0.0) / border_size); \n" + " float alpha = 1.0 - distance_field; \n" + " \n" + " out_color = vec4(vec3(color), distance_field); \n" + // " out_color = color; \n" "} \n"; + state->graphics.handle = create_graphics(); state->graphics.vertex_shader_handle = create_shader(state->graphics.handle, VERTEX_SHADER_TYPE, vertex_shader_source); state->graphics.pixel_shader_handle = create_shader(state->graphics.handle, PIXEL_SHADER_TYPE, pixel_shader_source); @@ -233,6 +274,7 @@ void init(u32 width, u32 height) typedef struct Vertex { f32 position[2]; + f32 uv[2]; f32 color[3]; } Vertex; @@ -250,23 +292,47 @@ void init(u32 width, u32 height) // { { -0.75f, -0.50f }, { 0.0f, 0.0f, 1.0f } }, // }; - const char* input_layout_names[] = { "a_position", "a_color" }; - u32 input_layout_offsets[] = { OFFSETOF(Vertex, position), OFFSETOF(Vertex, color) }; - u32 input_layout_formats[] = { COUNTOF(Vertex, position), COUNTOF(Vertex, color) }; + const char* input_layout_names[] = { "a_position", "a_uv", "a_color" }; + u32 input_layout_offsets[] = { OFFSETOF(Vertex, position), OFFSETOF(Vertex, uv), OFFSETOF(Vertex, color) }; + u32 input_layout_formats[] = { COUNTOF(Vertex, position), COUNTOF(Vertex, uv), COUNTOF(Vertex, color) }; state->graphics.input_layout.handle = create_input_layout(state->graphics.handle, state->graphics.program_handle, input_layout_names, input_layout_offsets, input_layout_formats, sizeof(Vertex), ARRAY_COUNT(input_layout_names)); state->graphics.input_layout.stride = sizeof(Vertex); + use_program(state->graphics.handle, state->graphics.program_handle); + UniformHandle uniform_handle = get_uniform_location(state->graphics.handle, state->graphics.program_handle, (u8*)"u_resolution"); + set_uniform_2f(state->graphics.handle, uniform_handle, state->width, state->height); + set_viewport(state->graphics.handle, state->width, state->height); - log_integer(width); - log_integer(height); - log_integer(state->graphics.handle); - log_integer(state->graphics.vertex_shader_handle); - log_integer(state->graphics.pixel_shader_handle); - log_integer(state->graphics.program_handle); - log_integer(state->graphics.vertex_buffer_handle); - log_integer(state->graphics.input_layout.handle); + log_number(state->graphics.handle); + log_number(state->graphics.vertex_shader_handle); + log_number(state->graphics.pixel_shader_handle); + log_number(state->graphics.program_handle); + log_number(state->graphics.vertex_buffer_handle); + log_number(state->graphics.input_layout.handle); + log_number(uniform_handle); +} + +void init(u32 width, u32 height) +{ + MemoryArena* arena = get_memory_arena(&__heap_base, &__heap_base - &__data_end); + + state = PUSH_STRUCT(arena, State); + state->arena = arena; + state->width = width; + state->height = height; + + graphics_init(); + + rectangle[0].x = 0.0f; + rectangle[0].y = 10.0f; + rectangle[0].width = 40.0f; + rectangle[0].height = 40.0f; + rectangle[1].x = 110.0f; + rectangle[1].y = 10.0f; + rectangle[1].width = 40.0f; + rectangle[1].height = 40.0f; } diff --git a/demo.h b/demo.h index 1cb4737..9c4aaec 100644 --- a/demo.h +++ b/demo.h @@ -5,6 +5,7 @@ typedef uptr ShaderHandle; typedef uptr ProgramHandle; typedef uptr BufferHandle; typedef uptr InputLayoutHandle; +typedef uptr UniformHandle; // NOTE: WebGL 1.0 and 2.0 Specs // https://registry.khronos.org/webgl/specs/1.0/ @@ -26,7 +27,7 @@ typedef enum PrimitiveType TRIANGLE_PRIMITIVE_TYPE=0x0004, } PrimitiveType; -void platform_log_integer(u32 integer); +void platform_log_number(f32 number); GraphicsHandle platform_create_graphics(void); ShaderHandle platform_create_shader(GraphicsHandle graphics, ShaderType type, const u8* source); @@ -41,6 +42,8 @@ void platform_use_input_layout(GraphicsHandle graphics, InputLayoutHandle input_ void platform_set_viewport(GraphicsHandle graphics, u32 width, u32 height); void platform_clear_color(GraphicsHandle graphics, f32 r, f32 g, f32 b, f32 a); void platform_use_program(GraphicsHandle graphics, ProgramHandle program); +UniformHandle platform_get_uniform_location(GraphicsHandle graphics, ProgramHandle program, const u8* name); +void platform_set_uniform_2f(GraphicsHandle graphics, UniformHandle uniform, f32 f1, f32 f2); void platform_draw_arrays(GraphicsHandle graphics, PrimitiveType primitive_type, u32 offset, u32 count); void render(void); diff --git a/demo.js b/demo.js index 1308a4e..16d3eaa 100644 --- a/demo.js +++ b/demo.js @@ -158,6 +158,21 @@ function clear_color(gl, r, g, b, a) gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); } +function use_program(gl, program) +{ + gl.useProgram(program); +} + +function get_uniform_location(gl, program, name) +{ + return gl.getUniformLocation(program, name); +} + +function set_uniform_2f(gl, uniform, f1, f2) +{ + return gl.uniform2f(uniform, f1, f2); +} + function platform_create_shader(gl_reference, type, source) { const shader_source = convert_to_string(memory_buffer, source); @@ -263,17 +278,31 @@ function platform_clear_color(gl_reference, r, g, b, a) clear_color(gl_object, r, g, b, a); } -function use_program(gl, program) +function platform_use_program(gl_reference, program_reference) { - gl.useProgram(program); + const gl_object = get_object_from_reference(gl_reference); + const program_object = get_object_from_reference(program_reference); + + use_program(gl_object, program_object); } -function platform_use_program(gl_reference, program_reference) +function platform_get_uniform_location(gl_reference, program_reference, name) { const gl_object = get_object_from_reference(gl_reference); const program_object = get_object_from_reference(program_reference); + const uniform_name = convert_to_string(memory_buffer, name); + const uniform = get_uniform_location(gl_object, program_object, uniform_name); + const uniform_reference = create_new_reference(uniform); + + return uniform_reference; +} - use_program(gl_object, program_object); +function platform_set_uniform_2f(gl_reference, uniform_reference, f1, f2) +{ + const gl_object = get_object_from_reference(gl_reference); + const uniform_object = get_object_from_reference(uniform_reference); + + set_uniform_2f(gl_object, uniform_object, f1, f2); } function draw_arrays(gl, primitive_type, offset, count) @@ -349,9 +378,15 @@ function platform_create_graphics() return gl_reference; } -function platform_log_integer(integer) +function platform_log_number(number) { - console.log(integer); + console.log(number); +} + +function platform_throw_error(text) +{ + const string = convert_to_string(memory_buffer, text); + throw new Error(string); } let previous_timestamp = null; @@ -361,6 +396,7 @@ function loop(timestamp) if (previous_timestamp != null) { let delta_time = (timestamp - previous_timestamp) / 1000; + wasm.instance.exports.update(delta_time); wasm.instance.exports.render(); } @@ -373,7 +409,8 @@ WebAssembly.instantiateStreaming( { env: { - platform_log_integer, + platform_log_number, + platform_throw_error, platform_create_graphics, platform_create_shader, platform_create_program, @@ -386,6 +423,8 @@ WebAssembly.instantiateStreaming( platform_set_viewport, platform_clear_color, platform_use_program, + platform_get_uniform_location, + platform_set_uniform_2f, platform_draw_arrays, } } @@ -400,4 +439,3 @@ WebAssembly.instantiateStreaming( // main(); } ); - diff --git a/memory_utils.h b/memory_utils.h index 871a508..a8ea1e5 100644 --- a/memory_utils.h +++ b/memory_utils.h @@ -1,9 +1,16 @@ #ifndef H_MEMORY_UTILS_H -#define PUSH_ARRAY(memory_arena, count, type) (push_size(memory_arena, ((count) * sizeof(type)))) -#define PUSH_STRUCT(memory_arena, type) ((type*)(push_size(memory_arena, sizeof(type)))) -#define PUSH_ARRAY_ZERO(memory_arena, count, type) (push_size_zero(memory_arena, ((count) * sizeof(type)))) -#define PUSH_STRUCT_ZERO(memory_arena, type) ((type*)(push_size_zero(memory_arena, sizeof(type)))) +#define DEFAULT_ALIGNMENT 4 + +#define PUSH_SIZE(memory_arena, size) (push_size(memory_arena, size, DEFAULT_ALIGNMENT)) +#define PUSH_ARRAY(memory_arena, count, type) (push_size(memory_arena, ((count) * sizeof(type)), DEFAULT_ALIGNMENT)) +#define PUSH_ARRAY_N(memory_arena, count, type, alignment) (push_size(memory_arena, ((count) * sizeof(type)), alignment)) +#define PUSH_STRUCT(memory_arena, type) ((type*)(push_size(memory_arena, sizeof(type), DEFAULT_ALIGNMENT))) +#define PUSH_STRUCT_N(memory_arena, type, alignment) ((type*)(push_size(memory_arena, sizeof(type), alignment))) +#define PUSH_ARRAY_ZERO(memory_arena, count, type) (push_size_zero(memory_arena, ((count) * sizeof(type)), DEFAULT_ALIGNMENT)) +#define PUSH_ARRAY_ZERO_N(memory_arena, count, type, alignment) (push_size_zero(memory_arena, ((count) * sizeof(type)), alignment)) +#define PUSH_STRUCT_ZERO(memory_arena, type) ((type*)(push_size_zero(memory_arena, sizeof(type), DEFAULT_ALIGNMENT))) +#define PUSH_STRUCT_ZERO_N(memory_arena, type, alignment) ((type*)(push_size_zero(memory_arena, sizeof(type)), alignment)) #define STRUCT_ZERO(memory, type) (memory_zero(memory, sizeof(type))) typedef struct MemoryArena @@ -50,14 +57,30 @@ static inline void end_temporary_memory(TemporaryMemory temporary_memory) temporary_memory.arena->used = temporary_memory.initial_size; } +static inline memory_size get_alignment_offset(MemoryArena* arena, memory_size alignment) +{ + memory_size alignment_offset = 0; + + memory_size result_pointer = (memory_size)arena->memory + arena->used; + memory_size alignment_mask = alignment - 1; + + if (result_pointer & alignment_mask) + { + alignment_offset = alignment - (result_pointer & alignment_mask); + } + + return alignment_offset; +} + // TODO: Probably, we should also handle alignment in these functions. -static inline void* push_size(MemoryArena* memory_arena, memory_size size) +static inline void* push_size(MemoryArena* memory_arena, memory_size size, memory_size alignment) { void* result = 0; + memory_size alignment_offset = get_alignment_offset(memory_arena, alignment); + size += alignment_offset; ASSERT(memory_arena->used + size <= memory_arena->size); - result = (u8*)memory_arena->memory + memory_arena->used; - + result = ((u8*)memory_arena->memory + memory_arena->used + alignment_offset); memory_arena->used += size; return result; @@ -93,18 +116,18 @@ static inline memory_size memory_copy(void* destination, void* source, memory_si return size - copy_size; } -static inline void* push_size_zero(MemoryArena* memory_arena, memory_size size) +static inline void* push_size_zero(MemoryArena* memory_arena, memory_size size, memory_size alignment) { - void* result = push_size(memory_arena, size); + void* result = push_size(memory_arena, size, alignment); memory_zero(result, size); return result; } -static inline MemoryArena* get_sub_arena(MemoryArena* memory_arena, memory_size size) +static inline MemoryArena* get_sub_arena(MemoryArena* memory_arena, memory_size size, memory_size alignment) { - MemoryArena* sub_arena = push_size(memory_arena, size); + MemoryArena* sub_arena = push_size(memory_arena, size, alignment); sub_arena->memory = sub_arena + sizeof(MemoryArena); sub_arena->used = 0; diff --git a/utils.h b/utils.h index 9fa3c00..aeb8378 100644 --- a/utils.h +++ b/utils.h @@ -26,7 +26,9 @@ typedef double f64; #define TRUE (1) #define FALSE (0) -#define ASSERT(x) do { if (!(x)) { *(volatile int*)0; } } while (0) +void platform_throw_error(const u8* text); + +#define ASSERT(x) do { if (!(x)) { platform_throw_error((u8*)#x); (volatile int*)0; } } while (0) #define ARRAY_COUNT(x) (sizeof(x) / sizeof(*(x))) #define OFFSETOF(type, member) ((memory_size)&(((type*)0)->member))