From a86b620d2f7df9e84e9ee491f5aee6e4f0706e42 Mon Sep 17 00:00:00 2001 From: Brett Date: Sun, 2 Apr 2023 23:49:58 -0400 Subject: [PATCH] geometry shader, billboarding --- include/shaders/geometry.geom | 50 +++++++++++++++++++++++- include/shaders/vertex.vert | 18 ++++----- src/high_perf/high_perf.cpp | 71 ++++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 39 deletions(-) diff --git a/include/shaders/geometry.geom b/include/shaders/geometry.geom index 0471b0d..1c24f6e 100644 --- a/include/shaders/geometry.geom +++ b/include/shaders/geometry.geom @@ -1,8 +1,56 @@ +#ifdef __cplusplus +#include +std::string shader_geom = R"(" #version 460 layout (points) in; layout (triangle_strip, max_vertices = 4) out; -void main() { +in vec4 pos_[]; +out vec2 uv_; +out float index; + +const vec3 vertices[] = { + vec3(0.5f, 0.5f, 0.0f), + vec3(0.5f, -0.5f, 0.0f), + vec3(-0.5f, -0.5f, 0.0f), + vec3(-0.5f, 0.5f, 0.0f) +}; + +uniform mat4 pvm; +uniform vec4 up; +uniform vec4 right; + +void emitTransformed(vec3 pos){ + // passthough index + index = pos_[0].w; + //gl_Position = pvm * vec4(pos_[0].xyz + vertices[0], 1.0); + gl_Position = pvm * vec4(pos, 1.0); } + +void main() { + const float quad_size = 0.5; + vec3 pos = pos_[0].xyz; + + emitTransformed(pos + up.xyz * quad_size + right.xyz * quad_size); + uv_ = vec2(0, 0); + EmitVertex(); + + emitTransformed(pos + up.xyz * quad_size - right.xyz * quad_size); + uv_ = vec2(0, 1); + EmitVertex(); + + emitTransformed(pos - up.xyz * quad_size + right.xyz * quad_size); + uv_ = vec2(1, 0); + EmitVertex(); + + emitTransformed(pos - up.xyz * quad_size - right.xyz * quad_size); + uv_ = vec2(1, 1); + EmitVertex(); + + EndPrimitive(); +} + +")"; +#endif \ No newline at end of file diff --git a/include/shaders/vertex.vert b/include/shaders/vertex.vert index 91fc4ed..46581bc 100644 --- a/include/shaders/vertex.vert +++ b/include/shaders/vertex.vert @@ -3,22 +3,18 @@ std::string shader_vert = R"(" #version 460 -layout (location = 0) in vec3 vertex; -layout (location = 1) in vec2 uv; -layout (location = 2) in vec4 pos; -layout (location = 3) in vec4 dir; +//layout (location = 0) in vec3 vertex; +//layout (location = 1) in vec2 uv; +layout (location = 0) in vec4 pos; +layout (location = 1) in vec4 dir; -out vec2 uv_; -out float index; +out vec4 pos_; uniform mat4 pvm; void main() { - // passthough the UV (OpenGL interpolates this per fragment) - uv_ = uv; - index = pos.w; - // offset the vertex by the particle's position - gl_Position = pvm * vec4(vertex + pos.xyz, 1.0); + // passthrough point position to geometry shader + pos_ = pos; } ")"; diff --git a/src/high_perf/high_perf.cpp b/src/high_perf/high_perf.cpp index 1955aba..77b7b0b 100644 --- a/src/high_perf/high_perf.cpp +++ b/src/high_perf/high_perf.cpp @@ -3,7 +3,7 @@ * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ -#include +#include #include #include #include @@ -11,6 +11,7 @@ #include "blt/std/memory.h" #include #include +#include #include #include #include @@ -55,7 +56,7 @@ const unsigned int TEXTURE_WIDTH = 512; const unsigned int TEXTURE_HEIGHT = 512; // -------{Particles}------- -const unsigned int particle_count = 128 * 5000; +const unsigned int particle_count = 128 * 50000; const unsigned int offset_count = 8192; // generally alignment to multiples of 4 floats helps performance, plus we can use that extra space for info we need. @@ -116,19 +117,35 @@ void render() { perspectiveMatrix = blt::perspective(FOV, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 1000.0f); auto pvm = perspectiveMatrix * viewMatrix; + auto inverseView = viewMatrix.transpose(); + + // we need the up and right vectors for fast geometry shader billboard + // thankfully they are easy to extract from our view matrix. + blt::vec4 up {inverseView.m01(), inverseView.m11(), inverseView.m21()}; + blt::vec4 right {inverseView.m00(), inverseView.m10(), inverseView.m20()}; + +// +// up = viewMatrix * up; +// right = viewMatrix * right; + + //BLT_TRACE("Up {%f, %f, %f} || Right {%f, %f, %f}", up.x(), up.y(), up.z(), right.x(), right.y(), right.z()); + BLT_START_INTERVAL("Particles", "Compute Shader"); runPhysicsShader(); BLT_END_INTERVAL("Particles", "Compute Shader"); BLT_START_INTERVAL("Particles", "Render"); instance_shader->bind(); + instance_shader->setVec4("up", up); + instance_shader->setVec4("right", right); instance_shader->setMatrix("pvm", pvm); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, textureArrayID); glBindVertexArray(particleVAO); - glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, particle_count); + //glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, particle_count); + glDrawArrays(GL_POINTS, 0, particle_count); glBindVertexArray(0); BLT_END_INTERVAL("Particles", "Render"); } @@ -195,31 +212,31 @@ void init() { BLT_TRACE("Uploading VBO data and assigning to VAO"); glBindVertexArray(particleVAO); - // bind and upload vertices data to the GPU - glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12, vertices, GL_STATIC_DRAW); - // tell OpenGL how to handle the vertex data when rendering the VAO, the vertices will be bound to slot 0. - // (we will tell OpenGL what variable uses slot 0 in the shader!) - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*) 0); - // tell OpenGL we will be using the first VAO slot, prevents us from having to call it before rendering - glEnableVertexAttribArray(0); - - - glBindBuffer(GL_ARRAY_BUFFER, uvsVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, uvs, GL_STATIC_DRAW); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*) 0); - glEnableVertexAttribArray(1); +// // bind and upload vertices data to the GPU +// glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); +// glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12, vertices, GL_STATIC_DRAW); +// // tell OpenGL how to handle the vertex data when rendering the VAO, the vertices will be bound to slot 0. +// // (we will tell OpenGL what variable uses slot 0 in the shader!) +// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*) 0); +// // tell OpenGL we will be using the first VAO slot, prevents us from having to call it before rendering +// glEnableVertexAttribArray(0); +// +// +// glBindBuffer(GL_ARRAY_BUFFER, uvsVBO); +// glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, uvs, GL_STATIC_DRAW); +// glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*) 0); +// glEnableVertexAttribArray(1); int translations_size = sizeof(particle_record) * particle_count; glBindBuffer(GL_ARRAY_BUFFER, particleTranslationsBuffer); glBufferData(GL_ARRAY_BUFFER, translations_size, translations.buffer, GL_DYNAMIC_DRAW); // allocate some memory on the GPU - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(particle_record), (void*) 0); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(particle_record), (void*) offsetof(particle_record, dir)); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(particle_record), (void*) 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(particle_record), (void*) offsetof(particle_record, dir)); // tells opengl that we want to present this data per 1 instance instead of per vertex. - glVertexAttribDivisor(2, 1); - glVertexAttribDivisor(3, 1); - glEnableVertexAttribArray(2); - glEnableVertexAttribArray(3); +// glVertexAttribDivisor(2, 1); +// glVertexAttribDivisor(3, 1); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); // allow the particle buffer to be used in the computer shader! glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleTranslationsBuffer); @@ -230,8 +247,8 @@ void init() { glBufferData(GL_SHADER_STORAGE_BUFFER, offset_count * sizeof(vec4), offsets.buffer, GL_STATIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, particleOffsetsBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesEBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(float) * 6, indices, GL_STATIC_DRAW); +// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesEBO); +// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(float) * 6, indices, GL_STATIC_DRAW); // ---------------------------------- @@ -261,7 +278,7 @@ void init() { constexpr int channel_count = 4; int level = 0; - stbi_set_flip_vertically_on_load(true); + stbi_set_flip_vertically_on_load(false); for (const std::string& texture_loc : texture_locations){ // load the texture int width, height, channels; @@ -313,7 +330,7 @@ void init() { BLT_TRACE("Loading shaders"); - instance_shader = new shader(shader_vert, shader_frag, "", true); + instance_shader = new shader(shader_vert, shader_frag, shader_geom, true); physics_shader = new compute_shader(shader_physics); BLT_DEBUG("High performance subsystem init complete!");