diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d16a064 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.blend filter=lfs diff=lfs merge=lfs -text +*.pn filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 0e83ffc..6a60308 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ # Visual studio stuff .vs/ +# Exported art, reproduced from blend file +assets/exported_3d/ +art/exported/ +*.blend1 + # Exported web builds are zipped into zip files in the root of the repo *.zip diff --git a/art/art.blend b/art/art.blend new file mode 100644 index 0000000..5730634 --- /dev/null +++ b/art/art.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31d12b0ddc3eb2909994163a30548a90b61628ffb502d0e84330ee68acbdad79 +size 916880 diff --git a/art/gigatexture.png b/art/gigatexture.png new file mode 100644 index 0000000..3ff5970 --- /dev/null +++ b/art/gigatexture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0739c7806650470aebc7ad64040109a290432db5442015e48aa739506e658b95 +size 310122 diff --git a/assets/Button.png b/assets/Button.png index 300d841..d7b1936 100644 Binary files a/assets/Button.png and b/assets/Button.png differ diff --git a/assets/ThumbstickBase.png b/assets/ThumbstickBase.png index 869ab15..6a66aef 100644 Binary files a/assets/ThumbstickBase.png and b/assets/ThumbstickBase.png differ diff --git a/assets/ThumbstickNub.png b/assets/ThumbstickNub.png index 1ebe053..5e418f2 100644 Binary files a/assets/ThumbstickNub.png and b/assets/ThumbstickNub.png differ diff --git a/assets/_Attack.png b/assets/_Attack.png index f77195b..fdb02a2 100644 Binary files a/assets/_Attack.png and b/assets/_Attack.png differ diff --git a/assets/_Idle.png b/assets/_Idle.png index daf3db4..9cebdb9 100644 Binary files a/assets/_Idle.png and b/assets/_Idle.png differ diff --git a/assets/_Roll.png b/assets/_Roll.png index e85dcff..56c7004 100644 Binary files a/assets/_Roll.png and b/assets/_Roll.png differ diff --git a/assets/_Run.png b/assets/_Run.png index 181cf33..b9ab551 100644 Binary files a/assets/_Run.png and b/assets/_Run.png differ diff --git a/assets/arrow.png b/assets/arrow.png index c8c7d8e..a380cc3 100644 Binary files a/assets/arrow.png and b/assets/arrow.png differ diff --git a/assets/arrow_shooter.png b/assets/arrow_shooter.png index ac1b642..0b2ed13 100644 Binary files a/assets/arrow_shooter.png and b/assets/arrow_shooter.png differ diff --git a/assets/backpack.png b/assets/backpack.png index 2dcb0fb..dcf8fe2 100644 Binary files a/assets/backpack.png and b/assets/backpack.png differ diff --git a/assets/boots.png b/assets/boots.png index bea61de..64052da 100644 Binary files a/assets/boots.png and b/assets/boots.png differ diff --git a/assets/bullet.png b/assets/bullet.png index ca9038b..09a54cb 100644 Binary files a/assets/bullet.png and b/assets/bullet.png differ diff --git a/assets/chalice_of_gold.png b/assets/chalice_of_gold.png index 16cd869..f16e72b 100644 Binary files a/assets/chalice_of_gold.png and b/assets/chalice_of_gold.png differ diff --git a/assets/door.png b/assets/door.png index 4945884..b2f4a5d 100644 Binary files a/assets/door.png and b/assets/door.png differ diff --git a/assets/drop_shadow.png b/assets/drop_shadow.png index 3d443a5..549da3d 100644 Binary files a/assets/drop_shadow.png and b/assets/drop_shadow.png differ diff --git a/assets/e_icon.png b/assets/e_icon.png index 756600b..067c40d 100644 Binary files a/assets/e_icon.png and b/assets/e_icon.png differ diff --git a/assets/gold_coin.png b/assets/gold_coin.png index d17ef2f..8687de4 100644 Binary files a/assets/gold_coin.png and b/assets/gold_coin.png differ diff --git a/assets/hovering_circle.png b/assets/hovering_circle.png index 641029a..7808ad8 100644 Binary files a/assets/hovering_circle.png and b/assets/hovering_circle.png differ diff --git a/assets/hurt_vignette.png b/assets/hurt_vignette.png index 7feb85c..828dffa 100644 Binary files a/assets/hurt_vignette.png and b/assets/hurt_vignette.png differ diff --git a/assets/idol.png b/assets/idol.png index 0902d47..9a0933c 100644 Binary files a/assets/idol.png and b/assets/idol.png differ diff --git a/assets/idol_machine_has_idol.png b/assets/idol_machine_has_idol.png index 66d21ff..b684f32 100644 Binary files a/assets/idol_machine_has_idol.png and b/assets/idol_machine_has_idol.png differ diff --git a/assets/idol_machine_no_idol.png b/assets/idol_machine_no_idol.png index 0373eab..0e5e544 100644 Binary files a/assets/idol_machine_no_idol.png and b/assets/idol_machine_no_idol.png differ diff --git a/assets/mystery_tile.png b/assets/mystery_tile.png index 837e465..478bb1a 100644 Binary files a/assets/mystery_tile.png and b/assets/mystery_tile.png differ diff --git a/assets/pile_of_rocks.png b/assets/pile_of_rocks.png index 149e074..257956d 100644 Binary files a/assets/pile_of_rocks.png and b/assets/pile_of_rocks.png differ diff --git a/assets/scroll.png b/assets/scroll.png index 25fb211..4d4f095 100644 Binary files a/assets/scroll.png and b/assets/scroll.png differ diff --git a/assets/shift_icon.png b/assets/shift_icon.png index f1d9a02..fac0ce9 100644 Binary files a/assets/shift_icon.png and b/assets/shift_icon.png differ diff --git a/assets/small_old_man.png b/assets/small_old_man.png index e81fb69..29b618f 100644 Binary files a/assets/small_old_man.png and b/assets/small_old_man.png differ diff --git a/assets/space_icon.png b/assets/space_icon.png index 92dceaf..6ebfe00 100644 Binary files a/assets/space_icon.png and b/assets/space_icon.png differ diff --git a/assets/swipe.png b/assets/swipe.png index 7034218..8900292 100644 Binary files a/assets/swipe.png and b/assets/swipe.png differ diff --git a/assets/sword_of_nazareth.png b/assets/sword_of_nazareth.png index 374c5c2..271d604 100644 Binary files a/assets/sword_of_nazareth.png and b/assets/sword_of_nazareth.png differ diff --git a/assets/thinking.png b/assets/thinking.png index 6e9c2ea..21e617a 100644 Binary files a/assets/thinking.png and b/assets/thinking.png differ diff --git a/assets/tripod.png b/assets/tripod.png index b05a412..88794e0 100644 Binary files a/assets/tripod.png and b/assets/tripod.png differ diff --git a/assets/white square.png b/assets/white square.png index d58e9f7..4e201d9 100644 Binary files a/assets/white square.png and b/assets/white square.png differ diff --git a/level design document.png b/level design document.png index d791d05..40b55d5 100644 Binary files a/level design document.png and b/level design document.png differ diff --git a/main.c b/main.c index 357bd29..ea8e3de 100644 --- a/main.c +++ b/main.c @@ -6,7 +6,7 @@ #if defined(WIN32) || defined(_WIN32) #define DESKTOP #define WINDOWS -#define SOKOL_D3D11 +#define SOKOL_GLCORE33 #endif #if defined(__EMSCRIPTEN__) @@ -149,7 +149,6 @@ MD_String8 nullterm(MD_Arena *copy_onto, MD_String8 to_nullterm) } - double clamp(double d, double min, double max) { const double t = d < min ? min : d; @@ -873,11 +872,140 @@ sg_image load_image(const char *path) return to_return; } +SER_MAKE_FOR_TYPE(uint64_t); +SER_MAKE_FOR_TYPE(bool); +SER_MAKE_FOR_TYPE(double); +SER_MAKE_FOR_TYPE(float); +SER_MAKE_FOR_TYPE(MD_u64); +SER_MAKE_FOR_TYPE(ItemKind); +SER_MAKE_FOR_TYPE(PropKind); +SER_MAKE_FOR_TYPE(NpcKind); +SER_MAKE_FOR_TYPE(CharacterState); +SER_MAKE_FOR_TYPE(Memory); +SER_MAKE_FOR_TYPE(Vec2); +SER_MAKE_FOR_TYPE(Vec3); +SER_MAKE_FOR_TYPE(AnimKind); +SER_MAKE_FOR_TYPE(EntityRef); +SER_MAKE_FOR_TYPE(NPCPlayerStanding); + +typedef struct +{ + Vec3 *vertices; + MD_u64 num_vertices; + + sg_buffer loaded_buffer; +} Mesh; + +// mesh_name is for debugging +// arena must last as long as the Mesh lasts. Internal data points to `arena`, such as +// the name of the mesh's buffer in sokol +Mesh load_mesh(MD_Arena *arena, MD_String8 binary_file, MD_String8 mesh_name) +{ + MD_ArenaTemp scratch = MD_GetScratch(&arena, 1); + SerState ser = { + .data = binary_file.str, + .max = binary_file.size, + .arena = arena, + .error_arena = scratch.arena, + .serializing = false, + }; + Mesh out = {0}; + ser_MD_u64(&ser, &out.num_vertices); + Log("Mesh %.*s has %llu vertices\n", MD_S8VArg(mesh_name), out.num_vertices); + + out.vertices = MD_ArenaPush(arena, sizeof(Vec3) * out.num_vertices); + for(MD_u64 i = 0; i < out.num_vertices; i++) + { + ser_Vec3(&ser, &out.vertices[i]); + } + + assert(!ser.cur_error.failed); + MD_ReleaseScratch(scratch); + + out.loaded_buffer = sg_make_buffer(&(sg_buffer_desc) + { + .usage = SG_USAGE_IMMUTABLE, + .data = (sg_range){.ptr = out.vertices, .size = out.num_vertices * sizeof(Vec3)}, + .label = (const char*)nullterm(arena, MD_S8Fmt(arena, "%.*s-vertices", MD_S8VArg(mesh_name))).str, + }); + + + return out; +} + #include "assets.gen.c" #include "quad-sapp.glsl.h" +#include "threedee.glsl.h" AABB level_aabb = { .upper_left = { 0.0f, 0.0f }, .lower_right = { TILE_SIZE * LEVEL_TILES, -(TILE_SIZE * LEVEL_TILES) } }; GameState gs = { 0 }; +bool flycam = false; +Vec3 flycam_pos = {0}; +float flycam_horizontal_rotation = 0.0; +float flycam_vertical_rotation = 0.0; + +Vec4 IsPoint(Vec3 point) +{ + return V4(point.x, point.y, point.z, 1.0f); +} + +typedef struct +{ + Vec3 right; // X+ + Vec3 forward; // Z- + Vec3 up; +} Basis; + +void print_matrix(Mat4 m) +{ + for(int r = 0; r < 4; r++) + { + for(int c = 0; c < 4; c++) + { + printf("%f ", m.Elements[c][r]); + } + printf("\n"); + //printf("%f %f %f %f\n", m.Columns[i].x, m.Columns[i].y, m.Columns[i].z, m.Columns[i].w); + } + + printf("\n"); + + for(int r = 0; r < 4; r++) + { + + printf("%f %f %f %f\n", m.Columns[0].Elements[r], m.Columns[1].Elements[r], m.Columns[2].Elements[r], m.Columns[3].Elements[r]); + } +} + +Basis flycam_basis() +{ + // This basis function is wrong. Do not use it. Something about the order of rotations for + // each basis vector is screwey + Basis to_return = { + .forward = V3(0,0,-1), + .right = V3(1,0,0), + .up = V3(0,1,0), + }; + Mat4 rotate_horizontal = Rotate_RH(flycam_horizontal_rotation, V3(0,1,0)); + Mat4 rotate_vertical = Rotate_RH(flycam_vertical_rotation, V3(1,0,0)); + + to_return.forward = MulM4V4(rotate_horizontal, MulM4V4(rotate_vertical, IsPoint(to_return.forward))).xyz; + to_return.right = MulM4V4(rotate_horizontal, MulM4V4(rotate_vertical, IsPoint(to_return.right))).xyz; + to_return.up = MulM4V4(rotate_horizontal, MulM4V4(rotate_vertical, IsPoint(to_return.up))).xyz; + + return to_return; +} + +Mat4 flycam_matrix() +{ + Basis basis = flycam_basis(); + Mat4 to_return = {0}; + to_return.Columns[0] = IsPoint(basis.right); + to_return.Columns[1] = IsPoint(basis.up); + to_return.Columns[2] = IsPoint(basis.forward); + to_return.Columns[3] = IsPoint(flycam_pos); + return to_return; +} # define MD_S8LitConst(s) {(MD_u8 *)(s), sizeof(s)-1} @@ -1779,19 +1907,6 @@ enum VMax, } Version; -SER_MAKE_FOR_TYPE(uint64_t); -SER_MAKE_FOR_TYPE(bool); -SER_MAKE_FOR_TYPE(double); -SER_MAKE_FOR_TYPE(float); -SER_MAKE_FOR_TYPE(ItemKind); -SER_MAKE_FOR_TYPE(PropKind); -SER_MAKE_FOR_TYPE(NpcKind); -SER_MAKE_FOR_TYPE(CharacterState); -SER_MAKE_FOR_TYPE(Memory); -SER_MAKE_FOR_TYPE(Vec2); -SER_MAKE_FOR_TYPE(AnimKind); -SER_MAKE_FOR_TYPE(EntityRef); -SER_MAKE_FOR_TYPE(NPCPlayerStanding); #define SER_BUFF(ser, BuffElemType, buff_ptr) {ser_int(ser, &((buff_ptr)->cur_index));\ if((buff_ptr)->cur_index > ARRLEN((buff_ptr)->data))\ @@ -2127,11 +2242,15 @@ stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs stbtt_fontinfo font; +// @Place(sokol state struct) static struct { sg_pass_action pass_action; sg_pipeline pip; sg_bindings bind; + + sg_pipeline threedee_pip; + sg_bindings threedee_bind; } state; @@ -2309,6 +2428,8 @@ void do_serialization_tests() } #endif +Mesh mesh_player = {0}; + void init(void) { #ifdef WEB @@ -2318,7 +2439,9 @@ void init(void) #endif frame_arena = MD_ArenaAlloc(); - next_arena_big = true; +#ifdef WEB + next_arena_big = true; +#endif persistent_arena = MD_ArenaAlloc(); #ifdef DEVTOOLS @@ -2350,6 +2473,11 @@ void init(void) DialogNode cur_node = { 0 }; load_assets(); + + MD_String8 binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Signpost.bin")); + mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("Player.bin")); + MD_ArenaClear(frame_arena); + reset_level(); #ifdef WEB @@ -2451,6 +2579,36 @@ void init(void) .label = "quad-pipeline", }); + desc = threedee_program_shader_desc(sg_query_backend()); + assert(desc); + shd = sg_make_shader(desc); + + state.threedee_pip = sg_make_pipeline(&(sg_pipeline_desc) + { + .shader = shd, + .depth = { + .compare = SG_COMPAREFUNC_LESS_EQUAL, + .write_enabled = true + }, + .layout = { + .attrs = + { + [ATTR_threedee_vs_position].format = SG_VERTEXFORMAT_FLOAT3, + } + }, + .colors[0].blend = (sg_blend_state) { // allow transparency + .enabled = true, + .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, + .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + .op_rgb = SG_BLENDOP_ADD, + .src_factor_alpha = SG_BLENDFACTOR_ONE, + .dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + .op_alpha = SG_BLENDOP_ADD, + }, + .label = "threedee", + }); + + state.pass_action = (sg_pass_action) { //.colors[0] = { .action=SG_ACTION_CLEAR, .value={12.5f/255.0f, 12.5f/255.0f, 12.5f/255.0f, 1.0f } } @@ -4034,12 +4192,37 @@ void frame(void) } sg_begin_default_pass(&state.pass_action, sapp_width(), sapp_height()); + + sg_apply_pipeline(state.threedee_pip); + state.threedee_bind.vertex_buffers[0] = mesh_player.loaded_buffer; + sg_apply_bindings(&state.threedee_bind); + + Mat4 model = M4D(1.0f); + + Mat4 view = Translate(V3(0.0, 1.0, -5.0f)); + //view = LookAt_RH(V3(0,1,-5 + if(flycam) + { + Basis basis = flycam_basis(); + printf("Flycam forward: %f %f %f Flycam position: %f %f %f Flycam rotation %f %f\n", basis.forward.x, basis.forward.y, basis.forward.z, flycam_pos.x, flycam_pos.y, flycam_pos.z, flycam_horizontal_rotation, flycam_vertical_rotation); + view = LookAt_RH(flycam_pos, AddV3(flycam_pos, basis.forward), V3(0, 1, 0)); + //view = flycam_matrix(); + } + Mat4 projection = Perspective_RH_NO(PI32/4.0f, screen_size().x / screen_size().y, 0.001f, 1000.0f); + + threedee_vs_params_t params = {0}; + memcpy(params.model, (float*)&model, sizeof(model)); + memcpy(params.view, (float*)&view, sizeof(view)); + memcpy(params.projection, (float*)&projection, sizeof(projection)); + sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_threedee_vs_params, &SG_RANGE(params)); + sg_draw(0, (int)mesh_player.num_vertices, 1); + sg_apply_pipeline(state.pip); Level *cur_level = &level_level0; // Draw Tilemap draw tilemap tilemap drawing -#if 1 +#if 0 PROFILE_SCOPE("tilemap") { Vec2 starting_world = AddV2(world_cam_aabb().upper_left, V2(-TILE_SIZE, TILE_SIZE)); @@ -5124,6 +5307,17 @@ void frame(void) pressed = before_gameplay_loops; +#ifdef DEVTOOLS + if(flycam) + { + Basis basis = flycam_basis(); + const float speed = 2.0f; + flycam_pos = AddV3(flycam_pos, MulV3F(basis.forward, ((float)keydown[SAPP_KEYCODE_W] - (float)keydown[SAPP_KEYCODE_S])*speed*dt)); + flycam_pos = AddV3(flycam_pos, MulV3F(basis.right, ((float)keydown[SAPP_KEYCODE_D] - (float)keydown[SAPP_KEYCODE_A])*speed*dt)); + flycam_pos = AddV3(flycam_pos, MulV3F(basis.up, (((float)keydown[SAPP_KEYCODE_SPACE] + (float)keydown[SAPP_KEYCODE_LEFT_CONTROL]) - (float)keydown[SAPP_KEYCODE_LEFT_SHIFT])*speed*dt)); + } +#endif + // @Place(player rendering) PROFILE_SCOPE("render player") // draw character draw player render character { @@ -5786,7 +5980,7 @@ void frame(void) Vec2 pos = V2(0.0, screen_size().Y); int num_entities = 0; ENTITIES_ITER(gs.entities) num_entities++; - MD_String8 stats = tprint("Frametime: %.1f ms\nProcessing: %.1f ms\nGameplay processing: %.1f ms\nEntities: %d\nDraw calls: %d\nProfiling: %s\nNumber gameplay processing loops: %d\n", dt*1000.0, last_frame_processing_time*1000.0, last_frame_gameplay_processing_time*1000.0, num_entities, num_draw_calls, profiling ? "yes" : "no", num_timestep_loops); + MD_String8 stats = tprint("Frametime: %.1f ms\nProcessing: %.1f ms\nGameplay processing: %.1f ms\nEntities: %d\nDraw calls: %d\nProfiling: %s\nNumber gameplay processing loops: %d\nFlyecam: %s\n", dt*1000.0, last_frame_processing_time*1000.0, last_frame_gameplay_processing_time*1000.0, num_entities, num_draw_calls, profiling ? "yes" : "no", num_timestep_loops, flycam ? "yes" : "no"); AABB bounds = draw_text((TextParams) { false, true, stats, pos, BLACK, 1.0f }); pos.Y -= bounds.upper_left.Y - screen_size().Y; bounds = draw_text((TextParams) { false, true, stats, pos, BLACK, 1.0f }); @@ -5811,6 +6005,7 @@ void frame(void) } } + // @Place(actually render) PROFILE_SCOPE("flush rendering") { ARR_ITER_I(RenderingQueue, rendering_queues, i) @@ -5979,6 +6174,24 @@ void event(const sapp_event *e) } #endif +#ifdef DEVTOOLS + if (e->type == SAPP_EVENTTYPE_KEY_DOWN && e->key_code == SAPP_KEYCODE_F) + { + flycam = !flycam; + sapp_lock_mouse(flycam); + } + if(flycam) + { + if (e->type == SAPP_EVENTTYPE_MOUSE_MOVE) + { + const float rotation_speed = 0.001f; + flycam_horizontal_rotation -= e->mouse_dx * rotation_speed; + flycam_vertical_rotation -= e->mouse_dy * rotation_speed; + flycam_vertical_rotation = clampf(flycam_vertical_rotation, -PI32/2.0f + 0.01f, PI32/2.0f - 0.01f); + } + } +#endif + // mobile handling touch controls handling touch input if (mobile_controls) diff --git a/playgippity.png b/playgippity.png index b3cbdc4..d2f510d 100644 Binary files a/playgippity.png and b/playgippity.png differ diff --git a/run_codegen.bat b/run_codegen.bat index fbb57ab..be1bec0 100644 --- a/run_codegen.bat +++ b/run_codegen.bat @@ -26,13 +26,18 @@ copy "rpgpt_private_assets\ForgottenMemories\WaterTiles-6frames.png" "assets\cop copy "rpgpt_private_assets\knight_idle.png" "assets\copyrighted\knight_idle.png" || goto :error copy "rpgpt_private_assets\knight_attack.png" "assets\copyrighted\knight_attack.png" || goto :error copy "rpgpt_private_assets\knight_run_start.png" "assets\copyrighted\knight_run_start.png" || goto :error + +rmdir /S /q "assets\exported_3d" +mkdir "assets\exported_3d" || goto :error +copy "rpgpt_private_assets\exported\*" "assets\exported_3d\" || goto :error @echo off rmdir /S /q gen mkdir gen @REM shaders -thirdparty\sokol-shdc.exe --input quad.glsl --output gen\quad-sapp.glsl.h --slang glsl100:hlsl5:metal_macos || goto :error +thirdparty\sokol-shdc.exe --input quad.glsl --output gen\quad-sapp.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error +thirdparty\sokol-shdc.exe --input threedee.glsl --output gen\threedee.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error @REM metadesk codegen cl /Ithirdparty /W3 /Zi /WX codegen.c || goto :error diff --git a/ser.h b/ser.h index 9a1d801..dd721f6 100644 --- a/ser.h +++ b/ser.h @@ -26,6 +26,11 @@ typedef struct void ser_bytes(SerState *ser, MD_u8 *bytes, MD_u64 bytes_size) { + if(!ser->data && !ser->serializing) + { + ser->cur_error = (SerError){.failed = true, .why = MD_S8Lit("Deserializing but the data is null")}; + } + if(!ser->cur_error.failed) { if(ser->data) diff --git a/thirdparty/HandmadeMath.h b/thirdparty/HandmadeMath.h index fb30501..93c40fe 100644 --- a/thirdparty/HandmadeMath.h +++ b/thirdparty/HandmadeMath.h @@ -262,6 +262,11 @@ typedef union Vec3 float X, Y, Z; }; + struct + { + float x, y, z; + }; + struct { float U, V, W; @@ -322,6 +327,19 @@ typedef union Vec4 float W; }; struct + { + union + { + Vec3 xyz; + struct + { + float x, y, z; + }; + }; + + float w; + }; + struct { union { diff --git a/threedee.glsl b/threedee.glsl new file mode 100644 index 0000000..3add026 --- /dev/null +++ b/threedee.glsl @@ -0,0 +1,28 @@ +@module threedee + +@vs vs +in vec3 position; +out vec3 pos; + +uniform vs_params { + mat4 model; + mat4 view; + mat4 projection; +}; + +void main() { + pos = position; + gl_Position = projection * view * model * vec4(position, 1.0); +} +@end + +@fs fs +in vec3 pos; +out vec4 frag_color; + +void main() { + frag_color = vec4(pos, 1.0); +} +@end + +@program program vs fs