1
0
rwu_particles_informatikpro.../openglMain.c
2020-03-31 15:09:07 +02:00

217 lines
11 KiB
C

#include <stdlib.h>
#include "particlesystem.h"
#include "initOpenGL.h"
#include "utils.h"
#define PARTICLE_AMOUNT 1000000
int main()
{
/************* INIT *************/
// Init OpenGL and GLFW
initGLFW();
setErrorCallbackGL();
int width = WIDTH, height = HEIGHT;
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL");
setCurrentContextGL(window);
setFramebufferSizeCallbackGL(window);
// glad
initGlad();
/************* PARTICLE SYSTEM *************/
vector3f *epos1 = initVector3f(0, 0, 0);
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
particle_system *ps = initParticleSystem(1);
(ps->emitters)[0] = e1;
initRandomParticles(e1);
/************* SHADER *************/
const GLchar *computeShaderSource = "#version 460\n"
"\n"
"#define FLOAT_MAX 4294967296.0f\n"
"#define FLOAT_FACTOR 0.00000000023283064365386962890625f\n"
"\n"
"struct particle\n"
"{\n"
" float px, py, pz;\n"
" float vx, vy, vz;\n"
" float cx, cy, cz;\n"
" float age;\n"
"};\n"
"\n"
"layout(std430, binding = 0) buffer particles\n"
"{\n"
" particle p[];\n"
"};\n"
"\n"
"layout(location = 0) uniform float dt;\n"
"layout(location = 1) uniform vec3 resetPos;\n"
"layout(location = 2) uniform uint maxParticles;\n"
"\n"
"layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"uint hash(uvec3 seed)\n"
"{\n"
" uint hash;\n"
" hash = (seed.x ^ 61u) ^ (seed.y >> 16u);\n"
" hash *= 9u;\n"
" hash = seed.z ^ (seed.x >> 4u);\n"
" hash *= 0x27d4eb2du;\n"
" hash = seed.y ^ (seed.z >> 15u);\n"
" return hash;\n"
"}\n"
"\n"
"uint rand(uint seed)\n"
"{\n"
" seed ^= (seed << 13u);\n"
" seed ^= (seed >> 17u);\n"
" seed ^= (seed << 5u);\n"
" return seed;\n"
"}\n"
"\n"
"int foreSign(uint seed)\n"
"{\n"
" return rand(seed) % 2 == 0 ? 1 : -1;\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" uint gid = gl_GlobalInvocationID.x;\n"
"\n"
" if (gid <= maxParticles)\n"
" {\n"
" particle part = p[gid];\n"
"\n"
" uint hash1 = hash(uvec3(uint(part.px * FLOAT_MAX), uint(part.cy * FLOAT_MAX), uint(part.vz * FLOAT_MAX)));\n"
" uint hash2 = hash(uvec3(uint(part.vx * FLOAT_MAX), uint(part.py * FLOAT_MAX), uint(part.cz * FLOAT_MAX)));\n"
" uint hash3 = hash(uvec3(uint(part.cx * FLOAT_MAX), uint(part.vy * FLOAT_MAX), uint(part.pz * FLOAT_MAX)));\n"
"\n"
" if (part.age < 0 || part.px > 1 || part.py > 1 || part.pz > 1 || part.px < -1 || part.py < -1 || part.pz < -1)\n"
" {\n"
" part.px = resetPos.x;\n"
" part.py = resetPos.y;\n"
" part.pz = resetPos.z;\n"
"\n"
" part.age = rand(hash(uvec3(hash1, hash2, hash3))) % (250 - 60 + 1) + 60;\n"
"\n"
" part.vx = foreSign(hash1) * float(rand(hash2)) * FLOAT_FACTOR;\n"
" part.vy = foreSign(hash3) * float(rand(hash1)) * FLOAT_FACTOR;\n"
" part.vz = foreSign(hash2) * float(rand(hash3)) * FLOAT_FACTOR;\n"
"\n"
" part.cx = float(rand(hash1 ^ hash2)) * FLOAT_FACTOR;\n"
" part.cy = float(rand(hash2 ^ hash3)) * FLOAT_FACTOR;\n"
" part.cz = float(rand(hash3 ^ hash1)) * FLOAT_FACTOR;\n"
" }\n"
" else\n"
" {\n"
" part.px += part.vx * dt;\n"
" part.py += part.vy * dt;\n"
" part.pz += part.vz * dt;\n"
"\n"
" part.age -= 0.01f;\n"
" }\n"
"\n"
" p[gid] = part;\n"
" }\n"
"}";
const GLchar *vertexShaderSource = "#version 460\n"
"\n"
"layout(location = 0) in vec3 pos;\n"
"layout(location = 1) in vec3 colIn;\n"
"\n"
"layout(location = 0) out vec3 colV;\n"
"\n"
"void main(void)\n"
"{\n"
" colV = colIn;\n"
" gl_Position = vec4(pos, 1);\n"
"}";
const GLchar *fragmentShaderSource = "#version 460\n"
"\n"
"layout(location = 0) in vec3 colV;\n"
"layout(location = 0) out vec4 colOut;\n"
"\n"
"void main(void)\n"
"{\n"
" colOut = vec4(colV, 1);\n"
"}";
GLuint computeShader = compileShader(computeShaderSource, GL_COMPUTE_SHADER);
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint computeShaders[] = { computeShader };
GLuint computeShaderProgram = linkShaders(computeShaders, 1);
glUseProgram(computeShaderProgram);
GLint dtUniformLocation = glGetUniformLocation(computeShaderProgram, "dt");
GLint resetPosUniformLocation = glGetUniformLocation(computeShaderProgram, "resetPos");
glUniform3f(resetPosUniformLocation, e1->position->x, e1->position->y, e1->position->z);
GLint maxParticlesUniformLocation = glGetUniformLocation(computeShaderProgram, "maxParticles");
glUniform1ui(maxParticlesUniformLocation, PARTICLE_AMOUNT);
GLuint renderShaders[] = { vertexShader, fragmentShader };
GLuint renderShaderProgram = linkShaders(renderShaders, 2);
float *particles = serializeParticlesystem(ps);
GLsizeiptr sizeOfParticle = 3 * sizeof(vector3f) + sizeof(float);
GLuint particleBuffer;
glGenBuffers(1, &particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, PARTICLE_AMOUNT * sizeOfParticle, particles, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLuint vertexArray;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
// position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)0);
// color
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)24); // 32
glBindVertexArray(0);
/************* RENDER LOOP *************/
double time, tFrame, tLast = 0;
while (!glfwWindowShouldClose(window))
{
time = glfwGetTime();
tFrame = time - tLast;
tLast = time;
/*** UPDATE ***/
glUseProgram(computeShaderProgram);
glUniform1f(dtUniformLocation, tFrame);
glDispatchCompute(PARTICLE_AMOUNT / 256, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
/*** RENDER ***/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
glBindVertexArray(vertexArray);
glUseProgram(renderShaderProgram);
glDrawArrays(GL_POINTS, 0, PARTICLE_AMOUNT);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
//END
deleteShaders(renderShaders, 2);
deleteShaders(computeShaders, 1);
terminateGLFW(window);
freeParticleSystem(ps);
return 0;
}