diff --git a/assets/image/blue_brick_floor.png b/assets/image/blue_brick_floor.png new file mode 100644 index 0000000..5aa2bc4 Binary files /dev/null and b/assets/image/blue_brick_floor.png differ diff --git a/assets/image/blue_brick_wall.png b/assets/image/blue_brick_wall.png new file mode 100644 index 0000000..bd12078 Binary files /dev/null and b/assets/image/blue_brick_wall.png differ diff --git a/assets/image/cross.png b/assets/image/cross.png new file mode 100644 index 0000000..24c9ce4 Binary files /dev/null and b/assets/image/cross.png differ diff --git a/assets/image/white_brick_floor.png b/assets/image/white_brick_floor.png new file mode 100644 index 0000000..2cfe009 Binary files /dev/null and b/assets/image/white_brick_floor.png differ diff --git a/assets/image/white_brick_wall.png b/assets/image/white_brick_wall.png new file mode 100644 index 0000000..b8cba1a Binary files /dev/null and b/assets/image/white_brick_wall.png differ diff --git a/assets/image/yellow_brick_floor.png b/assets/image/yellow_brick_floor.png new file mode 100644 index 0000000..99ec7ab Binary files /dev/null and b/assets/image/yellow_brick_floor.png differ diff --git a/assets/shader/header.glsl b/assets/shader/header.glsl index 69f97a4..9fd25ac 100644 --- a/assets/shader/header.glsl +++ b/assets/shader/header.glsl @@ -4,7 +4,8 @@ #define SSBO_ATLAS_BUFFER 1 #define SSBO_PARTICLES_IN 2 #define SSBO_PARTICLES_OUT 3 -#define UBO_PARTICLES_INFO 4 +#define SSBO_PARTICLES_LOOKUP 4 +#define UBO_PARTICLES_INFO 5 #define TEX_ATLAS 1 diff --git a/assets/shader/model.vert b/assets/shader/model.vert index b32644a..a3e5acf 100644 --- a/assets/shader/model.vert +++ b/assets/shader/model.vert @@ -3,8 +3,9 @@ layout (location = 0) in vec4 v_pos; layout (location = 1) in vec4 v_colour; -layout (location = 2) in vec2 v_uv; -layout (location = 3) in uint v_texid; +layout (location = 2) in vec2 v_screen_offset; +layout (location = 3) in vec2 v_uv; +layout (location = 4) in uint v_texid; out VS_OUT { vec4 pos; @@ -23,7 +24,6 @@ void main() { vout.colour = v_colour; vout.uv = v_uv; vout.texid = v_texid; - vec4 p = u_projection * vout.pos; - gl_Position = vec4(p.xy, 2 / (p.z + 2) - 1, p.w); + gl_Position = u_projection * (vout.pos + vec4(v_screen_offset, 0, 0)); } diff --git a/assets/shader/particles.comp b/assets/shader/particles.comp index cb7954f..0cec95c 100644 --- a/assets/shader/particles.comp +++ b/assets/shader/particles.comp @@ -2,22 +2,28 @@ #include "header.glsl" #include "random.glsl" -layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in; +layout (local_size_x = 1, local_size_y = 64, local_size_z = 1) in; struct VertType { vec4 pos; vec4 colour; + vec2 screen_offset; vec2 uv; - float texid; + int texid; }; struct ParticleType { - vec4 pos; // xyz: pos, w: vel random scale - vec4 velocity; // xyz: vel, w: colour random scale + vec4 pos; + vec4 vel; + vec4 acc; vec4 colour; + float random_pos; + float random_vel; + float random_time; float time_start; float duration; float size; + int texid; int seed; }; @@ -29,34 +35,47 @@ layout (binding = SSBO_PARTICLES_OUT) writeonly buffer ParticleBufferOut { VertType vertices_out[]; }; +layout (binding = SSBO_PARTICLES_LOOKUP) readonly buffer ParticleLookupIn { + int lookup_in[]; +}; + layout (binding = UBO_PARTICLES_INFO) uniform ParticleInfo { float p_time; int p_size; }; -void main() { - ParticleType particle = particles_in[gl_WorkGroupID.x]; - int seed = particle.seed; - rand_mix(seed, int(gl_LocalInvocationID.x)); +const vec2 QUADS[4] = { + vec2(0, 0), + vec2(1, 0), + vec2(0, 1), + vec2(1, 1) +}; - float duration = clamp((p_time - particle.time_start) / particle.duration, 0, 1); - vec3 velocity = normalize(vec3( - rand_float(seed) * 2 - 1, - rand_float(seed) * 2 - 1, - rand_float(seed) * 2 - 1 - )) * particle.pos.w + particle.velocity.xyz; - vec4 colour = normalize(vec4( - rand_float(seed) * 2 - 1, - rand_float(seed) * 2 - 1, - rand_float(seed) * 2 - 1, - rand_float(seed) * 2 - 1 - )) * particle.velocity.w + particle.colour; - vec3 pos = particle.pos.xyz + velocity * duration; - colour.a *= (1 - duration); +void main() { + ParticleType p = particles_in[lookup_in[gl_GlobalInvocationID.x]]; - uint v_id = gl_GlobalInvocationID.x; - vertices_out[v_id].pos = vec4(pos, 1); - vertices_out[v_id].colour = colour; - vertices_out[v_id].texid = TEXID_WHITE; + int n = p.seed; + rand_mix(n, int(gl_GlobalInvocationID.y)); + + float t_total = p.duration + p.random_time * (rand_float(n)*2-1); + float t = clamp(p_time - p.time_start, 0, t_total); + float t_ratio = t / t_total; + + vec3 vel = p.vel.xyz + normalize(rand_vec3(n)*2-1) * p.random_vel; + vec4 pos = vec4(p.pos.xyz + normalize(rand_vec3(n)*2-1) * p.random_pos + (vel + 0.5 * p.acc.xyz * t) * t, 1); + vec4 colour = vec4(p.colour.rgb, p.colour.a * (1 - t_ratio)); + pos.z *= (pos.z > 0 ? 1 : 0); + + mat2 uv = mat2(rand_vec2(n), rand_vec2(n)); + uv = mat2(min(uv[0], uv[1]), max(uv[0], uv[1])); + uint v_id = (gl_GlobalInvocationID.x * gl_WorkGroupSize.y * p_size + gl_GlobalInvocationID.y) * 4; + + for(int i = 0; i < 4; i++) { + vertices_out[v_id+i].pos = pos; + vertices_out[v_id+i].colour = colour; + vertices_out[v_id+i].screen_offset = (QUADS[i]*2-1) * p.size; + vertices_out[v_id+i].uv = QUADS[i] * (uv[1] - uv[0]) + uv[0]; + vertices_out[v_id+i].texid = p.texid; + } } diff --git a/assets/shader/random.glsl b/assets/shader/random.glsl index bdf0a44..3537a8d 100644 --- a/assets/shader/random.glsl +++ b/assets/shader/random.glsl @@ -9,6 +9,18 @@ float rand_float(inout int n) { return float(n) / float(0x7fffffff); } +vec2 rand_vec2(inout int n) { + return vec2(rand_float(n), rand_float(n)); +} + +vec3 rand_vec3(inout int n) { + return vec3(rand_float(n), rand_float(n), rand_float(n)); +} + +vec4 rand_vec4(inout int n) { + return vec4(rand_float(n), rand_float(n), rand_float(n), rand_float(n)); +} + void rand_mix(inout int n, int v) { n = rand_gen(n ^ v); } diff --git a/src/graphics/context.cpp b/src/graphics/context.cpp index 87891b2..437480d 100644 --- a/src/graphics/context.cpp +++ b/src/graphics/context.cpp @@ -1,7 +1,7 @@ #include "context.hpp" +#include "../world/state.hpp" #include "gl/uniform.hpp" -#include "window.hpp" #include #include #include @@ -9,15 +9,13 @@ using Graphics::Context; -Context::Context(GLFWwindow* window, unsigned int program) { - assert(window); +Context::Context(unsigned int program) { glUseProgram(program); m_u_model = glGetUniformLocation(program, "u_model"); m_u_view = glGetUniformLocation(program, "u_view"); m_u_projection = glGetUniformLocation(program, "u_projection"); m_u_colour = glGetUniformLocation(program, "u_colour"); m_program = program; - m_window = window; } void Context::set_model_matrix(glm::mat4 mat) const { @@ -38,9 +36,10 @@ void Context::set_projection_matrix(glm::mat4 mat) { m_projection = mat; } -void Context::set_player(const World::Player& player) { - set_projection_matrix(glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 10.f)); - set_view_matrix(player.get_view_matrix()); +void Context::set_from_state(const World::State& state) { + const World::Player& player = state.m_player; + set_projection_matrix(player.m_projection); + set_view_matrix(player.m_view); m_transform = player.m_pos; } diff --git a/src/graphics/context.hpp b/src/graphics/context.hpp index 2541976..2c5c850 100644 --- a/src/graphics/context.hpp +++ b/src/graphics/context.hpp @@ -3,12 +3,13 @@ #include #include -#include "../world/player.hpp" -#include "window.hpp" + +namespace World { + struct State; +}; namespace Graphics { struct Context { - GLFWwindow* m_window; unsigned int m_program; unsigned int m_u_model; unsigned int m_u_view; @@ -18,13 +19,13 @@ namespace Graphics { glm::mat4 m_view; glm::mat4 m_projection; - Context(GLFWwindow* window, unsigned int program); + Context(unsigned int program); void set_model_matrix(glm::mat4 mat) const; void set_view_matrix(glm::mat4 mat); void set_projection_matrix(glm::mat4 mat); void set_colour_matrix(glm::mat4 mat) const; - void set_player(const World::Player& player); + void set_from_state(const World::State& state); glm::mat4 get_vp() const; }; diff --git a/src/graphics/particles.cpp b/src/graphics/particles.cpp index ec26138..b66913c 100644 --- a/src/graphics/particles.cpp +++ b/src/graphics/particles.cpp @@ -1,15 +1,15 @@ #include "particles.hpp" -#include "context.hpp" #include "pipeline.hpp" #include "shader.hpp" #include "vertex.hpp" #include #include +#include +#include using Graphics::Particles; - struct InfoType { float m_time; int m_size; @@ -18,60 +18,86 @@ struct InfoType { Particles::Particles() { m_time_started = glfwGetTime(); - glNamedBufferStorage(m_ssbo_particles, sizeof(Type) * MAX_PARTICLES, nullptr, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); - glNamedBufferData(m_ssbo_vertices, sizeof(Vertex) * MAX_PARTICLES, nullptr, GL_DYNAMIC_COPY); - glNamedBufferData(m_ubo_info, sizeof(InfoType), nullptr, GL_DYNAMIC_DRAW); - m_particles_mapping = (Type*)glMapNamedBuffer(m_ssbo_particles, GL_READ_WRITE); + std::vector indices(MAX_PARTICLES*6); + std::vector lookup(MAX_PARTICLE_GROUPS); - glBindVertexArray(m_vao); - glBindBuffer(GL_ARRAY_BUFFER, m_ssbo_vertices); - glBindVertexArray(0); + for(int i = 0; i < MAX_PARTICLES; i++) { + int i4 = i*4; + int i6 = i*6; + indices[i6+0] = i4+0; + indices[i6+1] = i4+1; + indices[i6+2] = i4+3; + indices[i6+3] = i4+0; + indices[i6+4] = i4+3; + indices[i6+5] = i4+2; + } + + for(int i = 0; i < MAX_PARTICLE_GROUPS; i++) { + lookup[i] = i; + } + + glNamedBufferStorage(m_buff_particles, sizeof(Type) * MAX_PARTICLE_GROUPS, nullptr, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + glNamedBufferStorage(m_buff_lookup, sizeof(int) * MAX_PARTICLE_GROUPS, lookup.data(), GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + glNamedBufferData(m_buff_vertices, sizeof(Vertex) * MAX_PARTICLES * 4, nullptr, GL_DYNAMIC_COPY); + glNamedBufferData(m_buff_indices, sizeof(int) * MAX_PARTICLES * 6, indices.data(), GL_STATIC_COPY); + glNamedBufferData(m_buff_info, sizeof(InfoType), nullptr, GL_DYNAMIC_DRAW); + m_particles_mapping = (Type*)glMapNamedBuffer(m_buff_particles, GL_READ_WRITE); + m_lookup_mapping = (int*)glMapNamedBuffer(m_buff_lookup, GL_READ_WRITE); + + Vertex::set_vertex_attribs(m_vao, m_buff_vertices); + glVertexArrayElementBuffer(m_vao, m_buff_indices); } -void Particles::update(const Pipeline& pipeline) { +void Particles::update() { double now = get_time_diff(); int j = 0; - for(int i = 0; i < m_particles_mapping_size; i++) { - Type& p = m_particles_mapping[i]; - if(p.m_time_start + p.m_duration < now) { + for(int i = 0; i < m_mapping_size; i++) { + Type& p = m_particles_mapping[m_lookup_mapping[i]]; + if(p.m_time_start + p.m_duration > now) { if(i > j) { - m_particles_mapping[j] = m_particles_mapping[i]; + std::swap(m_lookup_mapping[j], m_lookup_mapping[i]); } j++; } } - m_particles_mapping_size = j; + m_mapping_size = j; InfoType info { .m_time = (float)now, - .m_size = m_particles_mapping_size, + .m_size = 1, }; - glNamedBufferSubData(m_ubo_info, 0, sizeof(InfoType), &info); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Shader::SSBO_PARTICLES_IN, m_ssbo_particles); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Shader::SSBO_PARTICLES_OUT, m_ssbo_vertices); - glBindBufferBase(GL_UNIFORM_BUFFER, Shader::UBO_PARTICLES_INFO, m_ubo_info); - glUseProgram(pipeline.m_program_particles); - glDispatchCompute(m_particles_mapping_size, 1, 1); + glNamedBufferSubData(m_buff_info, 0, sizeof(InfoType), &info); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Shader::SSBO_PARTICLES_IN, m_buff_particles); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Shader::SSBO_PARTICLES_OUT, m_buff_vertices); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Shader::SSBO_PARTICLES_LOOKUP, m_buff_lookup); + glBindBufferBase(GL_UNIFORM_BUFFER, Shader::UBO_PARTICLES_INFO, m_buff_info); + glUseProgram(Graphics::Pipeline::CURRENT->m_program_particles); + glDispatchCompute(m_mapping_size, info.m_size, 1); } void Particles::render(const Context& ctx) const { + if(m_mapping_size == 0) { + return; + } + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - ctx.set_colour_matrix(glm::mat4(1)); ctx.set_model_matrix(glm::mat4(1)); + ctx.set_colour_matrix(glm::mat4(1)); glBindVertexArray(m_vao); - glDrawArrays(GL_POINTS, 0, m_particles_mapping_size); - glBindVertexArray(0); + glDrawElements(GL_TRIANGLES, m_mapping_size * PARTICLES_PER_GROUP * 6, GL_UNSIGNED_INT, 0); } -void Particles::add(const Type& type) { - if(m_particles_mapping_size < MAX_PARTICLES) { - m_particles_mapping[m_particles_mapping_size++] = type; +void Particles::add(Type type) { + if(m_mapping_size < MAX_PARTICLE_GROUPS) { + type.m_time_start = (float)get_time_diff(); + type.m_seed = random(); + m_particles_mapping[m_lookup_mapping[m_mapping_size++]] = type; } } -double Particles::get_time_diff() { - return m_time_started - glfwGetTime(); +double Particles::get_time_diff() const { + return glfwGetTime() - m_time_started; } diff --git a/src/graphics/particles.hpp b/src/graphics/particles.hpp index ca8b4e9..e23e28d 100644 --- a/src/graphics/particles.hpp +++ b/src/graphics/particles.hpp @@ -7,36 +7,51 @@ #include namespace Graphics { - struct Pipeline; struct Particles { struct Type { glm::vec3 m_pos; - float m_random_velocity_scale; - glm::vec3 m_velocity; - float m_random_colour_scale; - glm::vec4 m_colour; + int _padding_1; + + glm::vec3 m_vel; + int _padding_2; + + glm::vec3 m_acc; + int _padding_3; + + glm::vec4 m_colour = {1, 1, 1, 1}; + + float m_random_pos; + float m_random_vel; + float m_random_time; float m_time_start; + float m_duration; float m_size; - int m_seed; + unsigned int m_texid; + unsigned int m_seed; }; - static_assert(sizeof(Type) == 64); + static_assert(sizeof(Type) == 96); - static constexpr int MAX_PARTICLES = 1024; + static constexpr int MAX_PARTICLE_GROUPS = 1024; + static constexpr int PARTICLES_PER_GROUP = 64; + static constexpr int MAX_PARTICLES = MAX_PARTICLE_GROUPS * PARTICLES_PER_GROUP; GL::VertexArray m_vao; - GL::ArrayBuffer m_ssbo_particles; - GL::ArrayBuffer m_ssbo_vertices; - GL::ArrayBuffer m_ubo_info; + GL::ArrayBuffer m_buff_particles; + GL::ArrayBuffer m_buff_lookup; + GL::ArrayBuffer m_buff_vertices; + GL::ArrayBuffer m_buff_indices; + GL::ArrayBuffer m_buff_info; Type* m_particles_mapping; - int m_particles_mapping_size = 0; + int* m_lookup_mapping; + int m_mapping_size = 0; double m_time_started; Particles(); - void add(const Type& type); - double get_time_diff(); - void update(const Pipeline& pipeline); + void update(); + void add(Type type); + double get_time_diff() const; void render(const Context& ctx) const; }; }; diff --git a/src/graphics/pipeline.cpp b/src/graphics/pipeline.cpp index 39a5a8c..3095d0e 100644 --- a/src/graphics/pipeline.cpp +++ b/src/graphics/pipeline.cpp @@ -7,6 +7,8 @@ #include "shader/compile.hpp" #include "shader/link.hpp" #include "texture/generate_atlas.hpp" +#include "../world/state.hpp" +#include "../util/debug.hpp" using Graphics::Pipeline; @@ -19,6 +21,9 @@ Pipeline::Pipeline() { Graphics::Shader::link(m_program_model, {model_vert, model_frag}); Graphics::Shader::link(m_program_particles, {particles_comp}); + + CHECK_DEBUG(CURRENT == nullptr); + CURRENT = this; } bool Pipeline::should_close() const { @@ -27,7 +32,6 @@ bool Pipeline::should_close() const { void Pipeline::update() { m_window.update(); - m_particles.update(*this); } void Pipeline::render(const World::State& state, const Context& ctx) const { @@ -36,7 +40,6 @@ void Pipeline::render(const World::State& state, const Context& ctx) const { glClearColor(0.1, 0.1, 0.12, 1); state.render(ctx); - m_particles.render(ctx); m_window.swap_buffers(); } diff --git a/src/graphics/pipeline.hpp b/src/graphics/pipeline.hpp index e1106b7..a356dff 100644 --- a/src/graphics/pipeline.hpp +++ b/src/graphics/pipeline.hpp @@ -1,18 +1,21 @@ #pragma once -#include "context.hpp" #include "gl/program.hpp" -#include "particles.hpp" #include "texture/generate_atlas.hpp" +#include "context.hpp" #include "window.hpp" -#include "../world/state.hpp" + +namespace World { + struct State; +}; namespace Graphics { struct Pipeline { + static inline Pipeline* CURRENT = nullptr; + Window m_window; Texture::GeneratedAtlas m_generated_atlas; - Particles m_particles; GL::Program m_program_model; GL::Program m_program_particles; diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index 1fdc1fe..e3d728f 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -5,7 +5,8 @@ namespace Graphics::Shader { constexpr int SSBO_ATLAS_BUFFER = 1; constexpr int SSBO_PARTICLES_IN = 2; constexpr int SSBO_PARTICLES_OUT = 3; - constexpr int UBO_PARTICLES_INFO = 4; + constexpr int SSBO_PARTICLES_LOOKUP = 4; + constexpr int UBO_PARTICLES_INFO = 5; constexpr int TEX_ATLAS = 1; }; diff --git a/src/graphics/texture.hpp b/src/graphics/texture.hpp index 252755d..bfdbb38 100644 --- a/src/graphics/texture.hpp +++ b/src/graphics/texture.hpp @@ -6,12 +6,20 @@ namespace Graphics::Texture { inline Image MISSING {"missing.png", Image::Edge::REPEATING}; inline Image WHITE {"white.png", Image::Edge::REPEATING}; + inline Image CROSS {"cross.png", Image::Edge::CLAMP}; inline Image YELLOW_BRICK_WALL {"yellow_brick_wall.png", Image::Edge::REPEATING}; + inline Image YELLOW_BRICK_FLOOR {"yellow_brick_floor.png", Image::Edge::REPEATING}; + inline Image WHITE_BRICK_WALL {"white_brick_wall.png", Image::Edge::REPEATING}; + inline Image WHITE_BRICK_FLOOR {"white_brick_floor.png", Image::Edge::REPEATING}; inline Image* const IMAGES[] { &MISSING, &WHITE, + &CROSS, &YELLOW_BRICK_WALL, + &YELLOW_BRICK_FLOOR, + &WHITE_BRICK_WALL, + &WHITE_BRICK_FLOOR, }; }; diff --git a/src/graphics/texture/generate_atlas.cpp b/src/graphics/texture/generate_atlas.cpp index b169afe..1a8a057 100644 --- a/src/graphics/texture/generate_atlas.cpp +++ b/src/graphics/texture/generate_atlas.cpp @@ -5,6 +5,7 @@ #include "atlas.hpp" #include "image.hpp" #include "uv.hpp" +#include #include #include #include @@ -60,8 +61,8 @@ void Graphics::Texture::generate_atlas(GeneratedAtlas& ga) { src->clear_host(); uvs[it->id] = { - .uv0={(it->x + offset + 0.5f) / size, (it->y + offset + 0.5f) / size}, - .uv1={(it->x + offset + src->m_size.x - 0.5f) / size, (it->y + offset + src->m_size.y - 0.5f) / size}, + .uv0={float(it->x + offset) / size, float(it->y + offset) / size}, + .uv1={float(it->x + offset + src->m_size.x) / size, float(it->y + offset + src->m_size.y) / size}, .zpos=zpos, .edges=src->m_edges, }; @@ -70,6 +71,8 @@ void Graphics::Texture::generate_atlas(GeneratedAtlas& ga) { } } + std::cout << "Finished stitching " << size << "x" << size << "x" << atlas.m_size.z << " atlas" << std::endl; + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, Graphics::Shader::SSBO_ATLAS_BUFFER, ga.m_ssbo_id); glNamedBufferData(ga.m_ssbo_id, sizeof(UV) * uvs.size(), uvs.data(), GL_STATIC_DRAW); diff --git a/src/graphics/vertex.cpp b/src/graphics/vertex.cpp index c951881..166b60e 100644 --- a/src/graphics/vertex.cpp +++ b/src/graphics/vertex.cpp @@ -11,10 +11,11 @@ void Vertex::set_vertex_attribs(unsigned int vao, unsigned int vbo) { glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(v)); glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, false, Util::pointer_diff(&v, &v.m_pos)); glVertexArrayAttribFormat(vao, 1, 4, GL_FLOAT, false, Util::pointer_diff(&v, &v.m_colour)); - glVertexArrayAttribFormat(vao, 2, 2, GL_FLOAT, false, Util::pointer_diff(&v, &v.m_uv)); - glVertexArrayAttribIFormat(vao, 3, 1, GL_UNSIGNED_INT, Util::pointer_diff(&v, &v.m_texid)); + glVertexArrayAttribFormat(vao, 2, 2, GL_FLOAT, false, Util::pointer_diff(&v, &v.m_screen_offset)); + glVertexArrayAttribFormat(vao, 3, 2, GL_FLOAT, false, Util::pointer_diff(&v, &v.m_uv)); + glVertexArrayAttribIFormat(vao, 4, 1, GL_UNSIGNED_INT, Util::pointer_diff(&v, &v.m_texid)); - for(int i = 0; i < 4; i++) { + for(int i = 0; i < 5; i++) { glEnableVertexArrayAttrib(vao, i); glVertexArrayAttribBinding(vao, i, 0); } diff --git a/src/graphics/vertex.hpp b/src/graphics/vertex.hpp index 2c51820..5cb4360 100644 --- a/src/graphics/vertex.hpp +++ b/src/graphics/vertex.hpp @@ -7,13 +7,14 @@ namespace Graphics { struct Vertex { glm::vec4 m_pos; glm::vec4 m_colour = {1, 1, 1, 1}; + glm::vec2 m_screen_offset = {0, 0}; glm::vec2 m_uv; unsigned int m_texid = 0; - int _padding_1 = 0; + int _padding_1[3] = {0}; static void set_vertex_attribs(unsigned int vao, unsigned int vbo); }; - static_assert(sizeof(Vertex) == 48); + static_assert(sizeof(Vertex) == 64); }; diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index 8291f1f..086d464 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -76,6 +76,7 @@ Window::Window() { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } Window::Window(Window&& o) { diff --git a/src/main.cpp b/src/main.cpp index 012402b..5f031bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,11 +9,11 @@ int main() { World::State state; while(!pipeline.should_close()) { - Graphics::Context ctx(pipeline.m_window, pipeline.m_program_model); - ctx.set_player(state.m_player); - pipeline.update(); - state.update(ctx); + state.update(); + + Graphics::Context ctx(pipeline.m_program_model); + ctx.set_from_state(state); pipeline.render(state, ctx); } } diff --git a/src/world/builder.cpp b/src/world/builder.cpp index e9c6056..d786a15 100644 --- a/src/world/builder.cpp +++ b/src/world/builder.cpp @@ -4,6 +4,8 @@ #include "../graphics/texture.hpp" #include "chunk.hpp" #include "map.hpp" +#include "player.hpp" +#include "state.hpp" #include "tile/empty.hpp" #include "tile/tile_base.hpp" #include @@ -18,7 +20,7 @@ using World::Builder; Builder::Builder() { Graphics::Mesh mesh; auto prim = Chunk::PRIMITIVE_B; - prim.m_texid = Graphics::Texture::YELLOW_BRICK_WALL; + prim.m_texid = Graphics::Texture::YELLOW_BRICK_FLOOR; mesh.add_primitive(prim); for(int i = 0; i < 4; i++) { @@ -30,17 +32,20 @@ Builder::Builder() { m_model.set(mesh, GL_STATIC_DRAW); } -void Builder::update(Map& map, const Graphics::Context& ctx) { +void Builder::update(State& state) { m_has_intersect = false; if(Graphics::Window::mouse_locked) { return; } + Player& player = state.m_player; + Map& map = state.m_map; + glm::vec<2, double> mpos; - glfwGetCursorPos(ctx.m_window, &mpos.x, &mpos.y); + glfwGetCursorPos(glfwGetCurrentContext(), &mpos.x, &mpos.y); mpos.y = Graphics::Window::size.y - mpos.y; - glm::vec<3, double> near = glm::unProject(glm::vec3(mpos, -1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size)); - glm::vec<3, double> far = glm::unProject(glm::vec3(mpos, 1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size)); + glm::vec<3, double> near = glm::unProject(glm::vec3(mpos, -1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); + glm::vec<3, double> far = glm::unProject(glm::vec3(mpos, 1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); glm::vec<3, double> direction = far - near; const glm::vec<2, double> CHECK_TILES[] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; bool found = false; @@ -49,7 +54,7 @@ void Builder::update(Map& map, const Graphics::Context& ctx) { return; } - m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + ctx.m_transform); + m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos); m_has_intersect = true; if(map.get_tile(m_intersect)) { @@ -71,6 +76,16 @@ void Builder::update(Map& map, const Graphics::Context& ctx) { tile = nullptr; } map.set_tile(m_intersect, std::move(tile)); + + state.m_particles.add({ + .m_pos = {m_intersect, 0.75/2}, + .m_acc = {0, 0, -0.98}, + .m_random_pos = 0.5, + .m_random_vel = 0.05, + .m_duration = 1, + .m_size = 0.025, + .m_texid = Graphics::Texture::YELLOW_BRICK_WALL, + }); } void Builder::render(const Graphics::Context& ctx) const { diff --git a/src/world/builder.hpp b/src/world/builder.hpp index 6612a0b..5c58a83 100644 --- a/src/world/builder.hpp +++ b/src/world/builder.hpp @@ -3,9 +3,9 @@ #include "../graphics/context.hpp" #include "../graphics/gl/model.hpp" -#include "map.hpp" namespace World { + struct State; struct Builder { enum Mode { SET, @@ -19,7 +19,7 @@ namespace World { Builder(); - void update(Map& map, const Graphics::Context& ctx); + void update(State& state); void render(const Graphics::Context& ctx) const; }; }; diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index 7e8a49a..a2d2021 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -79,7 +79,7 @@ void Chunk::update(Map& map) { auto prim = PRIMITIVE_B; prim.m_offset = {t_off, 0, 0}; - prim.m_texid = Graphics::Texture::MISSING; + prim.m_texid = Graphics::Texture::YELLOW_BRICK_FLOOR; mesh.add_primitive(prim); for(int i = 0; i < std::size(neighbours); i++) { diff --git a/src/world/chunk.hpp b/src/world/chunk.hpp index dbd7bcf..e4af606 100644 --- a/src/world/chunk.hpp +++ b/src/world/chunk.hpp @@ -32,9 +32,9 @@ namespace World { static const inline Graphics::Primitive<4, 6> PRIMITIVE_0 = { .m_vertices={ {.m_pos={-0.5, -0.5, 0.75, 1}, .m_uv={0, 0}}, - {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 2}}, + {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 1.5}}, {.m_pos={+0.5, -0.5, 0.75, 1}, .m_uv={2, 0}}, - {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 2}}, + {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 1.5}}, }, .m_indices={ 0, 2, 3, diff --git a/src/world/map.hpp b/src/world/map.hpp index 5064515..4cc08de 100644 --- a/src/world/map.hpp +++ b/src/world/map.hpp @@ -14,6 +14,7 @@ namespace World { #include namespace World { + struct State; struct Map { static constexpr int N = 16; std::map m_chunks; diff --git a/src/world/player.cpp b/src/world/player.cpp index c76c9a7..36b0a89 100644 --- a/src/world/player.cpp +++ b/src/world/player.cpp @@ -1,7 +1,6 @@ #include "player.hpp" #include "../graphics/window.hpp" -#include "../util/math/mod.hpp" #include #include #include @@ -64,13 +63,13 @@ void Player::update() { m_vel += m_accel; m_pos += m_vel; m_accel = -m_vel * 0.125; -} -glm::mat4 Player::get_view_matrix() const { glm::mat4 mat(1); mat = glm::translate(mat, {0, 0, -m_distance}); mat = glm::rotate(mat, (float)m_yaw, {-1, 0, 0}); mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1}); - return mat; + + m_view = mat; + m_projection = glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 10.f); } diff --git a/src/world/player.hpp b/src/world/player.hpp index 72400e6..39496fd 100644 --- a/src/world/player.hpp +++ b/src/world/player.hpp @@ -11,13 +11,16 @@ namespace World { glm::vec<2, double> m_vel = {0.01, 0}; glm::vec<2, double> m_accel = {0, 0}; glm::vec<2, double> m_cursor_last; + + glm::mat4 m_view; + glm::mat4 m_projection; + double m_distance = 2; double m_pitch = 0; double m_yaw = glm::pi() * 5.0 / 16.0; Player(); void update(); - glm::mat4 get_view_matrix() const; }; }; diff --git a/src/world/state.cpp b/src/world/state.cpp index 5d2d145..940a9cc 100644 --- a/src/world/state.cpp +++ b/src/world/state.cpp @@ -9,14 +9,16 @@ State::State() { m_map.set_tile({0, 0}, std::make_unique()); } -void State::update(const Graphics::Context& ctx) { - m_builder.update(m_map, ctx); +void State::update() { m_player.update(); + m_builder.update(*this); m_map.update(); + m_particles.update(); } void State::render(const Graphics::Context& ctx) const { m_map.render(ctx); m_builder.render(ctx); + m_particles.render(ctx); } diff --git a/src/world/state.hpp b/src/world/state.hpp index a46c79e..abc3549 100644 --- a/src/world/state.hpp +++ b/src/world/state.hpp @@ -1,20 +1,26 @@ #pragma once -#include "../graphics/context.hpp" +namespace World { + struct State; +}; + +#include +#include "../graphics/particles.hpp" #include "builder.hpp" #include "player.hpp" #include "map.hpp" namespace World { struct State { + Graphics::Particles m_particles; Builder m_builder; Player m_player; Map m_map; State(); - void update(const Graphics::Context& ctx); + void update(); void render(const Graphics::Context& ctx) const; }; };