From 05038da3df0dd5f074d4a9d79256ec723bfde30e Mon Sep 17 00:00:00 2001 From: Niklas Birk Date: Tue, 11 Feb 2020 19:01:50 +0100 Subject: [PATCH] Shader --- initOpenGL.c | 12 ++- initOpenGL.h | 3 +- main.c | 170 ++++++++++++++++++++++++++++++------ particlesystem.c | 49 ++++++++++- particlesystem.h | 7 +- shaders/FragmentShader.glsl | 10 +++ shaders/VertexShader.glsl | 26 ++++++ 7 files changed, 242 insertions(+), 35 deletions(-) create mode 100644 shaders/FragmentShader.glsl create mode 100644 shaders/VertexShader.glsl diff --git a/initOpenGL.c b/initOpenGL.c index d7f28cc..4229717 100644 --- a/initOpenGL.c +++ b/initOpenGL.c @@ -63,10 +63,16 @@ void framebufferSizeCallback(GLFWwindow *window, int width, int height) glViewport(0, 0, width, height); } -void initVertexBuffer(unsigned int *VBO, float *vertices) +void initVertexBufferObject(unsigned int *VBO, float *vertices) { glGenBuffers(1, VBO); - glBindBuffer(GL_ARRAY_BUFFER, *VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, *VBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); +} + +void initVertexArrayBuffer(unsigned int *VAO) +{ + glGenVertexArrays(1, VAO); + glBindVertexArray(*VAO); } diff --git a/initOpenGL.h b/initOpenGL.h index 794daa0..a71bb15 100644 --- a/initOpenGL.h +++ b/initOpenGL.h @@ -18,6 +18,7 @@ void terminateGLFW(GLFWwindow *window); void errorCallback(int error, const char* description); void framebufferSizeCallback(GLFWwindow *window, int width, int height); -void initVertexBuffer(unsigned int *VBO,float *vertices); +void initVertexBufferObject(unsigned int *VBO, float *vertices); +void initVertexArrayBuffer(unsigned int *VAO); #endif //INFORMATIKPROJEKT_INITOPENGL_H diff --git a/main.c b/main.c index 09fdfa0..8b362cf 100644 --- a/main.c +++ b/main.c @@ -14,8 +14,12 @@ void error_callback(int error, const char* description); void calcPos(particle *p, float dt); void calcCol(particle *p); +float *serializeParticles(const particle_system *ps); + int main() { + + /************* INIT *************/ // Init OpenGL and GLFW initGLFW(); setErrorCallbackGL(); @@ -29,17 +33,121 @@ int main() // glad initGlad(); - vector3f *epos = initVector3f(0, 0, 0); - emitter *e = initEmitter(epos, 1000); + /************* PARTICLE SYSTEM *************/ + int particelAmount = 10000; + vector3f *epos1 = initVector3f(0, 0, 0); + emitter *e1 = initEmitter(epos1, particelAmount); + particle_system *ps = initParticleSystem(1); - (ps->emitters)[0] = e; + (ps->emitters)[0] = e1; - initRandomParticles(e); + initRandomParticles(e1); + /************* COMPILING SHADER *************/ + const char *vertexShaderSource = "#version 460 core\n" + "\n" + "layout (location = 0) in vec3 pos; // the position variable has attribute position 0\n" + "layout (location = 1) in vec3 dir; // the direction variable has attribute position 1\n" + "layout (location = 2) in vec3 col; // the color variable has attribute position 2\n" + "layout (location = 3) in float age; // the age variable has attribute position 3\n" + "\n" + "//in vec3 emitterPos; // the emitter pos variable\n" + "//in float newAge; // the age variable\n" + "\n" + "out vec3 outCol; // output a color to the fragment shader\n" + "\n" + "void main()\n" + "{\n" + " if (age < 0)\n" + " {\n" + " //pos = vec3(0, 0, 0); //emitterPos;\n" + " //age = 200; //newAge;\n" + " }\n" + "\n" + " age -= 0.1f;\n" + " vec3 newPos = pos.xyz + dir.xyz;\n" + " gl_Position = vec4(newPos, 1.0);\n" + "\n" + " outCol = col; // set ourColor to the input color we got from the vertex data\n" + "}"; + + unsigned int vertexShader; + vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); + + int successCompileVertex; + char infoLogCompileVertex[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &successCompileVertex); + if (!successCompileVertex) + { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLogCompileVertex); + printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s", infoLogCompileVertex); + } + + const char *fragmentShaderSource = "#version 460 core\n" + "\n" + "in vec3 col; // the input variable from the vertex shader (same name and same type)\n" + "\n" + "out vec4 outCol;\n" + "\n" + "void main()\n" + "{\n" + " outCol = vec4(col, 1.0);\n" + "}"; + + unsigned int fragmentShader; + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + + int successCompileFragment; + char infoLogCompileFragment[512]; + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &successCompileFragment); + if (!successCompileFragment) + { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLogCompileFragment); + printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s", infoLogCompileFragment); + } + + /************* LINKING SHADER *************/ + unsigned int shaderProgram; + shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + + int successLink; + char infoLogLink[512]; + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successLink); + if (!successLink) + { + glGetProgramInfoLog(shaderProgram, 512, NULL, infoLogLink); + printf("ERROR::SHADER::LINKING_FAILED\n%s", infoLogLink); + } + + /*************** VAO / VBO ***************/ + // Init vertex data + unsigned int vao, vbo; + float *vertexData = serializeParticlesystem(ps); + initVertexArrayBuffer(&vao); + initVertexBufferObject(&vbo, vertexData); + + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + // direction attribute + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + // color attribute + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(6 * sizeof(float))); + glEnableVertexAttribArray(2); + // age attribute + glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(9 * sizeof(float))); + glEnableVertexAttribArray(3); + + /************* RENDER LOOP *************/ double time, tFrame, tLast = 0; - unsigned int vbo; - float vert[3] = {0.1f, 0.2f, 0.3f}; - while (!glfwWindowShouldClose(window)) { time = glfwGetTime(); @@ -49,38 +157,40 @@ int main() glClear(GL_COLOR_BUFFER_BIT); glfwGetFramebufferSize(window, &width, &height); - initVertexBuffer(&vbo, vert); + glUseProgram(shaderProgram); + glBindVertexArray(vao); + glDrawArrays(GL_POINTS, 0, particelAmount); - updateParticles((float) tFrame, ps, calcPos, calcCol); + /*updateParticles((float) tFrame, ps, calcPos, calcCol); + emitter *e; particle *p; vector3f *pos; - for (int i = 0; i < e->pamount; i++) + for (int j = 0; j < ps->eamount; j++) { - p = (e->particles)[i]; - glColor3f(p->color->x, p->color->y, p->color->z); - pos = p->position; + e = (ps->emitters)[j]; + for (int i = 0; i < e->pamount; i++) + { + p = (e->particles)[i]; + pos = p->position; - glBegin(GL_POINTS); - glVertex3f(pos->x, pos->y, pos->z); - glEnd(); - - /*glBegin(GL_QUADS); - glVertex3f(pos->x, pos->y, pos->z); - glVertex3f(pos->x+.01, pos->y, pos->z); - glVertex3f(pos->x+.01, pos->y-.01, pos->z); - glVertex3f(pos->x, pos->y-.01, pos->z); - glEnd();*/ - } + glColor3f(p->color->x, p->color->y, p->color->z); + glBegin(GL_POINTS); + glVertex3f(pos->x, pos->y, pos->z); + glEnd(); + } + }*/ glfwSwapBuffers(window); glfwPollEvents(); } //END + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + terminateGLFW(window); - free(epos); freeParticleSystem(ps); return 0; @@ -95,9 +205,9 @@ void calcPos(particle *p, float dt) void calcCol(particle *p) { - p->color->x = 1; - p->color->y = 1; - p->color->z = 1; +// p->color->x -= 0.01f; +// p->color->y -= 0.01f; +// p->color->z -= 0.01f; } /*************************************************************************************************************/ @@ -109,7 +219,9 @@ void initRandomParticles(emitter *e) vector3f *dir = initVector3f(((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX, ((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX, ((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX); - vector3f *color = initVector3f(1, 1, 1); + vector3f *color = initVector3f(((float) (rand() % 255)) / 255, + ((float) (rand() % 255)) / 255, + ((float) (rand() % 255)) / 255); (e->particles)[i] = initParticle(pos, dir, color, rand() / 100.0f); } } diff --git a/particlesystem.c b/particlesystem.c index 0644d4b..629f0cf 100644 --- a/particlesystem.c +++ b/particlesystem.c @@ -1,5 +1,6 @@ #include #include +#include #include "particlesystem.h" @@ -77,7 +78,7 @@ void resetParticle(emitter *e, particle *p) p->direction->y = ((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX; p->direction->z = ((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX; - p->age = rand() / 100.0f; + p->age = rand() / 10; } /* @@ -122,6 +123,7 @@ void freeEmitter(emitter *e) freeParticle((e->particles)[j]); } + free(e->position); free(e); } @@ -144,3 +146,48 @@ void freeParticleSystem(particle_system *ps) freeEmitters(ps); free(ps); } + +/* + * Creates float array out of a particle system + */ +float *serializeParticlesystem(particle_system *ps) +{ + int particleAmount = 0; + for (int i = 0; i < ps->eamount; i++) + { + particleAmount += (ps->emitters[i])->pamount; + } + + unsigned long particleBytesAmount = sizeof(vector3f) * 3 + sizeof(float); + float *vert = malloc(particleBytesAmount * particleAmount); + + emitter *e; + particle *p; + for (int y = 0, j = 0; y < ps->eamount; y++) + { + e = (ps->emitters)[y]; + for (int x = 0; x < e->pamount; x++) + { + p = e->particles[x]; + // Position + vert[j++] = p->position->x; + vert[j++] = p->position->y; + vert[j++] = p->position->z; + + // Direction + vert[j++] = p->direction->x; + vert[j++] = p->direction->y; + vert[j++] = p->direction->z; + + // Color + vert[j++] = p->color->x; + vert[j++] = p->color->y; + vert[j++] = p->color->z; + + // Age + vert[j++] = p->age; + } + } + + return vert; +} diff --git a/particlesystem.h b/particlesystem.h index adef1e3..378d31a 100644 --- a/particlesystem.h +++ b/particlesystem.h @@ -102,4 +102,9 @@ void freeEmitters(particle_system *ps); /* * Frees all emitter and particles within a particle system */ -void freeParticleSystem(particle_system *ps); \ No newline at end of file +void freeParticleSystem(particle_system *ps); + +/* + * Creates float array out of a particle system + */ +float *serializeParticlesystem(particle_system *ps); \ No newline at end of file diff --git a/shaders/FragmentShader.glsl b/shaders/FragmentShader.glsl new file mode 100644 index 0000000..21ed54e --- /dev/null +++ b/shaders/FragmentShader.glsl @@ -0,0 +1,10 @@ +#version 460 core + +in vec3 col; // the input variable from the vertex shader (same name and same type) + +out vec4 outCol; + +void main() +{ + outCol = vec4(vertexColor, 1.0); +} \ No newline at end of file diff --git a/shaders/VertexShader.glsl b/shaders/VertexShader.glsl new file mode 100644 index 0000000..475ad4c --- /dev/null +++ b/shaders/VertexShader.glsl @@ -0,0 +1,26 @@ +#version 460 core + +layout (location = 0) in vec3 pos; // the position variable has attribute position 0 +layout (location = 1) in vec3 dir; // the direction variable has attribute position 1 +layout (location = 2) in vec3 col; // the color variable has attribute position 2 +layout (location = 3) in float age; // the age variable has attribute position 3 + +//in vec3 emitterPos; // the emitter pos variable +//in float newAge; // the age variable + +out vec3 outCol; // output a color to the fragment shader + +void main() +{ + if (age < 0) + { + pos = emitterPos; + age = newAge; + } + + age -= 0.1f; + vec3 newPos = pos.xyz + dir.xyz; + gl_Position = vec4(newPos, 1.0); + + outCol = col; // set ourColor to the input color we got from the vertex data +} \ No newline at end of file