working particle system
This commit is contained in:
parent
82146468f3
commit
3d18ccf04e
Binary file not shown.
After Width: | Height: | Size: 804 B |
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 775 B |
Binary file not shown.
After Width: | Height: | Size: 780 B |
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 808 B |
|
@ -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
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
const vec2 QUADS[4] = {
|
||||
vec2(0, 0),
|
||||
vec2(1, 0),
|
||||
vec2(0, 1),
|
||||
vec2(1, 1)
|
||||
};
|
||||
|
||||
void main() {
|
||||
ParticleType particle = particles_in[gl_WorkGroupID.x];
|
||||
int seed = particle.seed;
|
||||
rand_mix(seed, int(gl_LocalInvocationID.x));
|
||||
ParticleType p = particles_in[lookup_in[gl_GlobalInvocationID.x]];
|
||||
|
||||
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);
|
||||
int n = p.seed;
|
||||
rand_mix(n, int(gl_GlobalInvocationID.y));
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#include "context.hpp"
|
||||
#include "../world/state.hpp"
|
||||
#include "gl/uniform.hpp"
|
||||
#include "window.hpp"
|
||||
#include <GL/glew.h>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/ext/matrix_float4x4.hpp>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
|
||||
#include <glm/ext/matrix_float4x4.hpp>
|
||||
#include <glm/matrix.hpp>
|
||||
#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;
|
||||
};
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
#include "particles.hpp"
|
||||
#include "context.hpp"
|
||||
#include "pipeline.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "vertex.hpp"
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
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<int> indices(MAX_PARTICLES*6);
|
||||
std::vector<int> 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;
|
||||
}
|
||||
|
||||
void Particles::update(const Pipeline& pipeline) {
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,36 +7,51 @@
|
|||
#include <glm/matrix.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "atlas.hpp"
|
||||
#include "image.hpp"
|
||||
#include "uv.hpp"
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <stb/stb_rect_pack.h>
|
||||
#include <GL/glew.h>
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <GL/glew.h>
|
||||
|
@ -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<float>(glm::vec3(mpos, -1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size));
|
||||
glm::vec<3, double> far = glm::unProject<float>(glm::vec3(mpos, 1), ctx.m_view, ctx.m_projection, glm::vec4(0, 0, Graphics::Window::size));
|
||||
glm::vec<3, double> near = glm::unProject<float>(glm::vec3(mpos, -1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size));
|
||||
glm::vec<3, double> far = glm::unProject<float>(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 {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace World {
|
|||
#include <memory>
|
||||
|
||||
namespace World {
|
||||
struct State;
|
||||
struct Map {
|
||||
static constexpr int N = 16;
|
||||
std::map<uint64_t, Chunk> m_chunks;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
#include "player.hpp"
|
||||
#include "../graphics/window.hpp"
|
||||
#include "../util/math/mod.hpp"
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<double>() * 5.0 / 16.0;
|
||||
|
||||
Player();
|
||||
void update();
|
||||
glm::mat4 get_view_matrix() const;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -9,14 +9,16 @@ State::State() {
|
|||
m_map.set_tile({0, 0}, std::make_unique<Tile::Empty>());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../graphics/context.hpp"
|
||||
namespace World {
|
||||
struct State;
|
||||
};
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
#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;
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue