diff --git a/Makefile b/Makefile index 278e852..5b2480c 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ DEBUG_MODE := no COMPILER_FLAGS := -std=c++17 -Wno-enum-compare -O3 -flto -msse4.2 -mavx COMPILER_FLAGS += -DRPROF_IMPLEMENTATION COMPILER_FLAGS += -DRAYGUI_IMPLEMENTATION +COMPILER_FLAGS += -Idepends/raylib/src/external LINKER_FLAGS := -lraylib # SOURCES := $(wildcard src/*.cpp) @@ -82,6 +83,7 @@ ifeq ($(PLATFORM), web) EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten COMPILER_FLAGS += -I$(EMSCRIPTEN_PATH)/cache/sysroot/include COMPILER_FLAGS += -D_DEFAULT_SOURCE + COMPILER_FLAGS += -DGRAPHICS_API_OPENGL_ES2 COMPILER_FLAGS += -msimd128 LINKER_FLAGS += -s USE_GLFW=3 LINKER_FLAGS += -s FORCE_FILESYSTEM=1 diff --git a/compile_flags.txt b/compile_flags.txt index d7df871..6f3d775 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,8 +1,10 @@ -Idepends/raylib-cpp/include/ -Idepends/raylib/src/ -Idepends/raygui/src/ +-Idepends/raylib/src/external -DRLGL_IMPLEMENTATION -DRPROF_IMPLEMENTATION -DRAYGUI_IMPLEMENTATION +-DPLATFORM_DESKTOP -DDEBUG -DSIMD256 diff --git a/src/boid-playground.hpp b/src/boid-playground.hpp index 6be2d03..6118577 100644 --- a/src/boid-playground.hpp +++ b/src/boid-playground.hpp @@ -2,8 +2,7 @@ #include #include -#include -#include "rlgl.h" +#include "raylib.h" #include "memory-arena.hpp" @@ -66,6 +65,16 @@ struct Visuals { Camera2D camera; + struct { + uint32_t id; + int32_t vertex_position_loc; + int32_t frag_color_loc; + int32_t mvp_loc; + + uint32_t vao; + uint32_t vbo; + } boid_shader; + bool show_control_panel = true; bool draw_boid_direction = false; diff --git a/src/main.cpp b/src/main.cpp index aa924df..2ee3ee8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,3 @@ -#include "raylib.h" -#include "raymath.h" #include #include @@ -10,12 +8,10 @@ // #define RPROF_ONLY_TOTAL_TIME #include "rprof.h" -#include "boid-playground.hpp" - +#include "world.cpp" #include "raycast.cpp" #include "memory-arena.cpp" #include "boid-list.cpp" -#include "world.cpp" #include "ui.cpp" #define FRAMERATE 60 @@ -42,8 +38,8 @@ int main() { int screen_width = 1280; int screen_height = 720; - raylib::Window window(screen_width, screen_height, "Boid Playground"); - window.SetState(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE); + InitWindow(screen_width, screen_height, "Boid Playground"); + SetWindowState(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE); GuiLoadStyleDefault(); @@ -64,13 +60,14 @@ int main() { emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else SetTargetFPS(FRAMERATE); - while (!window.ShouldClose()) { + while (!WindowShouldClose()) { UpdateDrawFrame(); } #endif - window.Close(); world_free(&g_world); + visuals_cleanup(&g_visuals); + CloseWindow(); rprof_end(); diff --git a/src/world.cpp b/src/world.cpp index 62cd40e..2c908bb 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,10 +1,80 @@ #include "boid-playground.hpp" + +#if defined(PLATFORM_DESKTOP) + #if defined(GRAPHICS_API_OPENGL_ES2) + #include "glad_gles2.h" // Required for: OpenGL functionality + #define glGenVertexArrays glGenVertexArraysOES + #define glBindVertexArray glBindVertexArrayOES + #define glDeleteVertexArrays glDeleteVertexArraysOES + #define GLSL_VERSION 100 + #else + #if defined(__APPLE__) + #include // OpenGL 3 library for OSX + #include // OpenGL 3 extensions library for OSX + #else + #include "glad.h" // Required for: OpenGL functionality + #endif + #define GLSL_VERSION 330 + #endif +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 + + #define GL_GLEXT_PROTOTYPES + //#include // EGL library -> not required, platform layer + #include // OpenGL ES 2.0 library + #include // OpenGL ES 2.0 extensions library +#endif + +#include "rlgl.h" + +#if defined(GRAPHICS_API_OPENGL_21) + #define GLSL_SHADER_HEADER "#version 120\n" + #define GLSL_VERT_SHADER_HEADER GLSL_SHADER_HEADER + #define GLSL_FRAG_SHADER_HEADER GLSL_SHADER_HEADER "varying vec4 outputColor;\n" + #define GLSL_FRAG_OUTPUT_COLOR "outputColor" + #define GLSL_IN "attribute " + #define GLSL_OUT "varying " +#elif defined(GRAPHICS_API_OPENGL_33) + #define GLSL_SHADER_HEADER "#version 330\n" + #define GLSL_VERT_SHADER_HEADER GLSL_SHADER_HEADER + #define GLSL_FRAG_SHADER_HEADER GLSL_SHADER_HEADER "out vec4 outputColor;\n" + #define GLSL_FRAG_OUTPUT_COLOR "outputColor" + #define GLSL_IN "in " + #define GLSL_OUT "out " +#elif defined(GRAPHICS_API_OPENGL_ES2) + #define GLSL_SHADER_HEADER "#version 100\n" + #define GLSL_VERT_SHADER_HEADER GLSL_SHADER_HEADER + #define GLSL_FRAG_SHADER_HEADER GLSL_SHADER_HEADER "precision mediump float;" + #define GLSL_FRAG_OUTPUT_COLOR "gl_FragColor" + #define GLSL_IN "attribute " + #define GLSL_OUT "varying " +#endif + +#include "raymath.h" #include "raycast.hpp" #include "rprof.h" #include "boid-list.hpp" #include "simd.cpp" +#define BOID_VERT_SHADER \ + GLSL_VERT_SHADER_HEADER \ + GLSL_IN "vec2 vertexPosition;\n" \ + "uniform mat4 mvp;\n" \ + "void main()\n" \ + "{\n" \ + " gl_Position = mvp*vec4(vertexPosition.x, vertexPosition.y, 0.0, 1.0);\n" \ + "}\0" + +#define BOID_FRAG_SHADER \ + GLSL_FRAG_SHADER_HEADER \ + "uniform vec4 fragColor;\n" \ + "void main()\n" \ + "{\n" \ + " " GLSL_FRAG_OUTPUT_COLOR " = fragColor;\n" \ + "}\0" + + static float vector2_atan2(Vector2 a) { return std::atan2(a.y, a.x); } @@ -117,15 +187,41 @@ static void world_init(World *world, float width, float height) { world->size = { width, height }; } -static void visuals_init(World *world, Visuals *visuals) { - visuals->camera = { 0 }; - visuals->camera.zoom = 1; -} - static void world_free(World *world) { arena_free(&world->frame_arena); } +static int visuals_init(World *world, Visuals *visuals) { + visuals->camera = { 0 }; + visuals->camera.zoom = 1; + + int vert_shader_id = rlCompileShader(BOID_VERT_SHADER, GL_VERTEX_SHADER); + int frag_shader_id = rlCompileShader(BOID_FRAG_SHADER, GL_FRAGMENT_SHADER); + + int shader_id = rlLoadShaderProgram(vert_shader_id, frag_shader_id); + if (shader_id <= 0) return -1; + + visuals->boid_shader.id = shader_id; + visuals->boid_shader.vertex_position_loc = glGetAttribLocation(shader_id, "vertexPosition"); + visuals->boid_shader.frag_color_loc = glGetUniformLocation(shader_id, "fragColor"); + visuals->boid_shader.mvp_loc = glGetUniformLocation(shader_id, "mvp"); + + visuals->boid_shader.vao = rlLoadVertexArray(); + unsigned int vertex_position_buffer = 0; + + rlEnableVertexArray(visuals->boid_shader.vao); + glGenBuffers(1, &visuals->boid_shader.vbo); + rlDisableVertexArray(); + + return 0; +} + +static void visuals_cleanup(Visuals *visuals) { + glDeleteBuffers(1, &visuals->boid_shader.vbo); + rlUnloadVertexArray(visuals->boid_shader.vao); + rlUnloadShaderProgram(visuals->boid_shader.id); +} + // --------------------- Utils ----------------------- void world_adjust_boid_count(World *world, int new_boid_count) { @@ -609,15 +705,15 @@ static void draw_circle_sector(Vector2 center, float radius, float start_angle, } static void draw_boids(World *world, Visuals *visuals) { - int boid_count = world->boids.size(); - float boid_length = visuals->boid_edge_size * std::sqrt(3)/2; float boid_width = visuals->boid_edge_size * 0.6; - Color color = visuals->boid_color; + int boid_count = world->boids.size(); + int vertex_count = boid_count*3; + Vector2 *vertices = (Vector2*)arena_malloc(&world->frame_arena, vertex_count); - rlBegin(RL_TRIANGLES); for (int i = 0; i < boid_count; i++) { Boid *boid = &world->boids[i]; + Vector2 *boid_vertices = &vertices[3*i]; Vector2 triangle[] = { { boid_length*2/3.0f, 0 }, @@ -627,20 +723,36 @@ static void draw_boids(World *world, Visuals *visuals) { float facing = std::atan2(boid->dir.y, boid->dir.x); float facing_cos = cos(facing); float facing_sin = sin(facing); - for (int i = 0; i < 3; i++) { - Vector2 new_pos = boid->pos; - new_pos.x += triangle[i].x * facing_cos - triangle[i].y * facing_sin; - new_pos.y += triangle[i].x * facing_sin + triangle[i].y * facing_cos; - triangle[i] = new_pos; + for (int j = 0; j < 3; j++) { + boid_vertices[j].x = boid->pos.x + (triangle[j].x * facing_cos - triangle[j].y * facing_sin); + boid_vertices[j].y = boid->pos.y + (triangle[j].x * facing_sin + triangle[j].y * facing_cos); } - - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(triangle[0].x, triangle[0].y); - rlVertex2f(triangle[1].x, triangle[1].y); - rlVertex2f(triangle[2].x, triangle[2].y); } - rlEnd(); + rlDrawRenderBatchActive(); + + int32_t vertex_position_loc = visuals->boid_shader.vertex_position_loc; + int32_t frag_color_loc = visuals->boid_shader.frag_color_loc; + int32_t mvp_loc = visuals->boid_shader.mvp_loc; + uint32_t vao = visuals->boid_shader.vao; + uint32_t vbo = visuals->boid_shader.vbo; + Color color = visuals->boid_color; + + glUseProgram(visuals->boid_shader.id); + Matrix modelViewProjection = MatrixMultiply(rlGetMatrixModelview(), rlGetMatrixProjection()); + glUniformMatrix4fv(mvp_loc, 1, false, MatrixToFloat(modelViewProjection)); + glUniform4f(frag_color_loc, (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255); + + rlEnableVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vertex_count*sizeof(Vector2), vertices, GL_DYNAMIC_DRAW); + glVertexAttribPointer(vertex_position_loc, 2, GL_FLOAT, 0, 0, NULL); + rlEnableVertexAttribute(vertex_position_loc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDrawArrays(GL_TRIANGLES, 0, vertex_count); + rlDisableVertexArray(); + glUseProgram(0); } static void visuals_update(World *world, Visuals *visuals) {