From 12f2044980b86250aab68d20c27c0f4cd8b89687 Mon Sep 17 00:00:00 2001 From: Marcin Kwapisz Date: Mon, 1 Feb 2021 00:26:43 +0100 Subject: [PATCH 1/3] =?UTF-8?q?Particle=20co=C5=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grk-project.vcxproj | 8 +- grk-project.vcxproj.filters | 6 + shader_particle.frag | 14 ++ shader_particle.vert | 29 ++++ shaders/shader_particle.frag | 14 ++ shaders/shader_particle.vert | 29 ++++ src/main.cpp | 262 ++++++++++++++++++++++++++++++++--- 7 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 shader_particle.frag create mode 100644 shader_particle.vert create mode 100644 shaders/shader_particle.frag create mode 100644 shaders/shader_particle.vert diff --git a/grk-project.vcxproj b/grk-project.vcxproj index 3cabe13..898082b 100644 --- a/grk-project.vcxproj +++ b/grk-project.vcxproj @@ -17,6 +17,8 @@ + + @@ -49,7 +51,7 @@ {1B448102-E76C-4347-BDC7-40D02A567DB6} Win32Proj grk-cw9 - 10.0.17134.0 + 10.0 grk-project @@ -57,14 +59,14 @@ Application true Unicode - v141 + v142 Application false true Unicode - v141 + v142 diff --git a/grk-project.vcxproj.filters b/grk-project.vcxproj.filters index 46e4667..7589c2e 100644 --- a/grk-project.vcxproj.filters +++ b/grk-project.vcxproj.filters @@ -54,6 +54,12 @@ Shader Files + + Shader Files + + + Shader Files + diff --git a/shader_particle.frag b/shader_particle.frag new file mode 100644 index 0000000..7c3ba2d --- /dev/null +++ b/shader_particle.frag @@ -0,0 +1,14 @@ +#version 330 core + +in vec2 UV; +in vec4 ParticleColor; + +out vec4 color; + +uniform sampler2D sprite; + +void main() +{ + color = texture( sprite, UV ) * ParticleColor; + +} \ No newline at end of file diff --git a/shader_particle.vert b/shader_particle.vert new file mode 100644 index 0000000..e08cd46 --- /dev/null +++ b/shader_particle.vert @@ -0,0 +1,29 @@ +#version 330 core +layout(location = 0) in vec3 squareVertices; +layout(location = 1) in vec4 xyzs; +layout(location = 2) in vec4 color; + +out vec2 UV; +out vec4 ParticleColor; + +uniform vec3 CameraRight_worldspace; +uniform vec3 CameraUp_worldspace; +uniform mat4 VP; + +void main() +{ + float particleSize = xyzs.w; // because we encoded it this way. + vec3 particleCenter_wordspace = xyzs.xyz; + + vec3 vertexPosition_worldspace = + particleCenter_wordspace + + CameraRight_worldspace * squareVertices.x * particleSize + + CameraUp_worldspace * squareVertices.y * particleSize; + + // Output position of the vertex + gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f); + + // UV of the vertex. No special space for this one. + UV = squareVertices.xy + vec2(0.5, 0.5); + ParticleColor = color; +} \ No newline at end of file diff --git a/shaders/shader_particle.frag b/shaders/shader_particle.frag new file mode 100644 index 0000000..7c3ba2d --- /dev/null +++ b/shaders/shader_particle.frag @@ -0,0 +1,14 @@ +#version 330 core + +in vec2 UV; +in vec4 ParticleColor; + +out vec4 color; + +uniform sampler2D sprite; + +void main() +{ + color = texture( sprite, UV ) * ParticleColor; + +} \ No newline at end of file diff --git a/shaders/shader_particle.vert b/shaders/shader_particle.vert new file mode 100644 index 0000000..e08cd46 --- /dev/null +++ b/shaders/shader_particle.vert @@ -0,0 +1,29 @@ +#version 330 core +layout(location = 0) in vec3 squareVertices; +layout(location = 1) in vec4 xyzs; +layout(location = 2) in vec4 color; + +out vec2 UV; +out vec4 ParticleColor; + +uniform vec3 CameraRight_worldspace; +uniform vec3 CameraUp_worldspace; +uniform mat4 VP; + +void main() +{ + float particleSize = xyzs.w; // because we encoded it this way. + vec3 particleCenter_wordspace = xyzs.xyz; + + vec3 vertexPosition_worldspace = + particleCenter_wordspace + + CameraRight_worldspace * squareVertices.x * particleSize + + CameraUp_worldspace * squareVertices.y * particleSize; + + // Output position of the vertex + gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f); + + // UV of the vertex. No special space for this one. + UV = squareVertices.xy + vec2(0.5, 0.5); + ParticleColor = color; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5a78149..10116a8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,12 +29,24 @@ GLuint programSkybox; GLuint programSun; GLuint programBlur; GLuint programBloom; +GLuint programParticle; +GLuint VertexArrayID; unsigned int pingpongFBO[2]; unsigned int pingpongColorbuffers[2]; unsigned int FBO; unsigned int colorBuffers[2]; - +//particlepart +double lastTime; +static GLfloat* g_particule_position_size_data; +static GLubyte* g_particule_color_data; +GLuint particle_vertex_buffer; +GLuint particles_position_buffer; +GLuint particles_color_buffer; +GLuint CameraRight_worldspace_ID; +GLuint CameraUp_worldspace_ID; +GLuint ViewProjMatrixID; +GLuint TextureParticle; Core::Shader_Loader shaderLoader; @@ -48,6 +60,7 @@ GLuint earthTexture; GLuint moonTexture; GLuint skyboxTexture; GLuint shipTexture; +GLuint particleTexture; obj::Model sphereModel; obj::Model cubeModel; obj::Model shipModel; @@ -71,8 +84,47 @@ glm::mat4 cameraMatrix, perspectiveMatrix; glm::vec3 sunPos = glm::vec3(10.0f, 0.0f, -5.0f); glm::vec3 sunPos2 = glm::vec3(25.0f, -1.0f, 10.0f); +//particlepart +struct Particle { + glm::vec3 pos, speed; + unsigned char r, g, b, a; // Color + float size, angle, weight; + float life; // Remaining life of the particle. if <0 : dead and unused. + float cameradistance; // *Squared* distance to the camera. if dead : -1.0f + bool operator<(const Particle& that) const { + return this->cameradistance > that.cameradistance; + } +}; +const int MaxParticles = 1000; +Particle ParticlesContainer[MaxParticles]; +int LastUsedParticle = 0; + +void SortParticles() { + std::sort(&ParticlesContainer[0], &ParticlesContainer[MaxParticles]); +} + +int FindUnusedParticle() { + + for (int i = LastUsedParticle; i < MaxParticles; i++) { + if (ParticlesContainer[i].life < 0) { + LastUsedParticle = i; + return i; + } + } + + for (int i = 0; i < LastUsedParticle; i++) { + if (ParticlesContainer[i].life < 0) { + LastUsedParticle = i; + return i; + } + } + + return 0; // All particles are taken, override the first one +} + +//Light struct Light { glm::vec3 position; glm::vec3 color; @@ -101,7 +153,7 @@ void keyboard(unsigned char key, int x, int y) float moveSpeed = 0.1f; switch (key) { - case 'q': + case 'q': { cameraAngle -= angleSpeed; lights[3].intensity = 0.005; @@ -109,7 +161,7 @@ void keyboard(unsigned char key, int x, int y) break; } - case 'e': + case 'e': { cameraAngle += angleSpeed; lights[2].intensity = 0.005; @@ -117,7 +169,7 @@ void keyboard(unsigned char key, int x, int y) break; } - case 'w': + case 'w': { cameraPos += cameraDir * moveSpeed; lights[2].intensity = 0.005; @@ -167,7 +219,7 @@ glm::mat4 createCameraMatrix() cameraDir = glm::vec3(cosf(cameraAngle), 0.0f, sinf(cameraAngle)); glm::vec3 up = glm::vec3(0, 1, 0); - cameraSide = glm::cross(cameraDir,up); + cameraSide = glm::cross(cameraDir, up); return Core::createViewMatrix(cameraPos, cameraDir, up); } @@ -218,7 +270,7 @@ unsigned int loadCubemap(std::vector faces) int width, height, nrChannels; for (unsigned int i = 0; i < faces.size(); i++) { - unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0); + unsigned char* data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0); if (data) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, @@ -276,7 +328,7 @@ void drawObjectTexture(GLuint program, Core::RenderContext context, glm::mat4 mo glm::mat4 drawPlanet(float time, glm::vec3 sunPos, glm::vec3 orbit, glm::vec3 translation, glm::vec3 scale) { glm::mat4 planetModelMatrix = glm::mat4(1.0f); - planetModelMatrix = glm::translate(planetModelMatrix, sunPos); + planetModelMatrix = glm::translate(planetModelMatrix, sunPos); planetModelMatrix = glm::rotate(planetModelMatrix, time, orbit); planetModelMatrix = glm::translate(planetModelMatrix, translation); planetModelMatrix = glm::scale(planetModelMatrix, scale); @@ -324,13 +376,13 @@ void renderScene() lights[0].position = sunPos; lights[1].position = sunPos2; - - glm::mat4 engineLeft = glm::translate(shipModelMatrix, glm::vec3(700,0,-1500)); + + glm::mat4 engineLeft = glm::translate(shipModelMatrix, glm::vec3(700, 0, -1500)); lights[2].position = glm::vec3(engineLeft[3][0], engineLeft[3][1], engineLeft[3][2]); glm::mat4 engineRight = glm::translate(shipModelMatrix, glm::vec3(-700, 0, -1500)); lights[3].position = glm::vec3(engineRight[3][0], engineRight[3][1], engineRight[3][2]); - + for (int i = 0; i < lights.size(); i++) { std::string col = "pointLights[" + std::to_string(i) + "].color"; @@ -347,9 +399,9 @@ void renderScene() drawFromAssimpModel(programTex, crewmate, crewmateModelMatrix, glm::vec3(1)); //rysowanie Ziemi z ksiezycem - glm::mat4 earth = drawPlanet(time / 5.0f, sunPos*glm::vec3(1.5f,1,1), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(-10.5f, 0.0f, -10.5f), glm::vec3(0.5f, 0.5f, 0.5f)); - glm::mat4 moon = drawMoon(earth, time/2.0f, glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0, 1, 1), glm::vec3(1.5f, 1.0f, 1.0f), glm::vec3(0.3f, 0.3f, 0.3f)); - earth = glm::rotate(earth, time/3.0f, glm::vec3(0.0f, 0.0f, 1.0f)); + glm::mat4 earth = drawPlanet(time / 5.0f, sunPos * glm::vec3(1.5f, 1, 1), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(-10.5f, 0.0f, -10.5f), glm::vec3(0.5f, 0.5f, 0.5f)); + glm::mat4 moon = drawMoon(earth, time / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0, 1, 1), glm::vec3(1.5f, 1.0f, 1.0f), glm::vec3(0.3f, 0.3f, 0.3f)); + earth = glm::rotate(earth, time / 3.0f, glm::vec3(0.0f, 0.0f, 1.0f)); drawObjectTexture(programTex, sphereContext, earth, glm::vec3(0.8f, 0.8f, 0.8f), earthTexture); drawObjectTexture(programTex, sphereContext, moon, glm::vec3(0.9f, 1.0f, 0.9f), moonTexture); @@ -369,7 +421,7 @@ void renderScene() { glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); glUniform1i(glGetUniformLocation(programBlur, "horizontal"), horizontal); - glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); + glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); renderQuad(); horizontal = !horizontal; if (first_iteration) @@ -393,8 +445,143 @@ void renderScene() } - glUseProgram(0); glutSwapBuffers(); + //particlepart + glUseProgram(programParticle); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.f; + double delta = currentTime - lastTime; + lastTime = currentTime; + glm::mat4 ProjectionMatrix = perspectiveMatrix * glm::mat4(glm::mat3(cameraMatrix)); + glm::mat4 ViewMatrix = cameraMatrix; + glm::vec3 CameraPosition(glm::inverse(ViewMatrix)[3]); + glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ViewMatrix; + + int newparticles = (int)(delta * 10000.0); + if (newparticles > (int)(0.016f * 10000.0)) + newparticles = (int)(0.016f * 10000.0); + + for (int i = 0; i < newparticles; i++) { + int particleIndex = FindUnusedParticle(); + ParticlesContainer[particleIndex].life = 100.0f; + ParticlesContainer[particleIndex].pos = glm::vec3(0, 0, 0.0f); + + float spread = 1.5f; + glm::vec3 maindir = glm::vec3(0.0f, 0.0f, 0.0f); + glm::vec3 randomdir = glm::vec3( + (rand() % 2000 - 1000.0f) / 1000.0f, + (rand() % 2000 - 1000.0f) / 1000.0f, + (rand() % 2000 - 1000.0f) / 1000.0f + ); + + ParticlesContainer[particleIndex].speed = maindir + randomdir * spread; + + + // Very bad way to generate a random color + ParticlesContainer[particleIndex].r = rand() % 256; + ParticlesContainer[particleIndex].g = rand() % 256; + ParticlesContainer[particleIndex].b = rand() % 256; + ParticlesContainer[particleIndex].a = (rand() % 256) / 3; + + ParticlesContainer[particleIndex].size = (rand() % 1000) / 2000.0f + 0.1f; + + } + // Simulate all particles + int ParticlesCount = 0; + for (int i = 0; i < MaxParticles; i++) { + + Particle& p = ParticlesContainer[i]; // shortcut + + if (p.life > 0.0f) { + + // Decrease life + p.life -= delta; + if (p.life > 0.0f) { + + // Simulate simple physics : gravity only, no collisions + p.speed += glm::vec3(0.0f, -9.81f, 0.0f) * (float)delta * 0.5f; + p.pos += p.speed * (float)delta; + p.cameradistance = glm::length2(p.pos - cameraPos); + //ParticlesContainer[i].pos += glm::vec3(0.0f,10.0f, 0.0f) * (float)delta; + + // Fill the GPU buffer + g_particule_position_size_data[4 * ParticlesCount + 0] = p.pos.x; + g_particule_position_size_data[4 * ParticlesCount + 1] = p.pos.y; + g_particule_position_size_data[4 * ParticlesCount + 2] = p.pos.z; + + g_particule_position_size_data[4 * ParticlesCount + 3] = p.size; + + g_particule_color_data[4 * ParticlesCount + 0] = p.r; + g_particule_color_data[4 * ParticlesCount + 1] = p.g; + g_particule_color_data[4 * ParticlesCount + 2] = p.b; + g_particule_color_data[4 * ParticlesCount + 3] = p.a; + + } + else { + // Particles that just died will be put at the end of the buffer in SortParticles(); + p.cameradistance = -1.0f; + } + + ParticlesCount++; + + } + } + + SortParticles(); + glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. + glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data); + + glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. + glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, particleTexture); + glUniform1i(TextureParticle, 0); + glUniform3f(CameraRight_worldspace_ID, ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); + glUniform3f(CameraUp_worldspace_ID, ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); + + glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, particle_vertex_buffer); + glVertexAttribPointer( + 0, // attribute. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); + glVertexAttribPointer( + 1, // attribute. No particular reason for 1, but must match the layout in the shader. + 4, // size : x + y + z + size => 4 + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); + glVertexAttribPointer( + 2, // attribute. No particular reason for 1, but must match the layout in the shader. + 4, // size : r + g + b + a => 4 + GL_UNSIGNED_BYTE, // type + GL_TRUE, // normalized? *** YES, this means that the unsigned char[4] will be accessible with a vec4 (floats) in the shader *** + 0, // stride + (void*)0 // array buffer offset + ); + glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0 + glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1 + glVertexAttribDivisor(2, 1); // color : one per quad -> 1 + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); } void init() @@ -405,6 +592,7 @@ void init() programSun = shaderLoader.CreateProgram("shaders/shader_sun.vert", "shaders/shader_sun.frag"); programBlur = shaderLoader.CreateProgram("shaders/shader_blur.vert", "shaders/shader_blur.frag"); programBloom = shaderLoader.CreateProgram("shaders/shader_bloom.vert", "shaders/shader_bloom.frag"); + programParticle = shaderLoader.CreateProgram("shaders/shader_particle.vert", "shaders/shader_particle.frag"); glUseProgram(programBlur); glUniform1i(glGetUniformLocation(programBlur, "image"), 0); @@ -413,7 +601,7 @@ void init() glUniform1i(glGetUniformLocation(programBloom, "bloomBlur"), 1); glUseProgram(0); - + corvette = std::make_shared("models/Corvette-F3.obj"); crewmate = std::make_shared("models/space_humster.obj"); //shipModel = obj::loadModelFromFile("models/spaceship.obj"); @@ -427,10 +615,47 @@ void init() sunTexture = Core::LoadTexture("textures/sun.png"); earthTexture = Core::LoadTexture("textures/earth2.png"); moonTexture = Core::LoadTexture("textures/moon.png"); + particleTexture = Core::LoadTexture("textures/sun.png"); skyboxTexture = loadCubemap(faces); glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); + //particlepart + glGenVertexArrays(1, &VertexArrayID); + glBindVertexArray(VertexArrayID); + CameraRight_worldspace_ID = glGetUniformLocation(programParticle, "CameraRight_worldspace"); + CameraUp_worldspace_ID = glGetUniformLocation(programParticle, "CameraUp_worldspace"); + ViewProjMatrixID = glGetUniformLocation(programParticle, "VP"); + TextureParticle = glGetUniformLocation(programParticle, "sprite"); + g_particule_position_size_data = new GLfloat[MaxParticles * 4]; + g_particule_color_data = new GLubyte[MaxParticles * 4]; + for (int i = 0; i < MaxParticles; i++) { + ParticlesContainer[i].life = 100.0f; + ParticlesContainer[i].cameradistance = -1.0f; + } + static const GLfloat g_vertex_buffer_data[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + }; + glGenBuffers(1, &particle_vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, particle_vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); + // The VBO containing the positions and sizes of the particles + glGenBuffers(1, &particles_position_buffer); + glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); + // Initialize with empty (NULL) buffer : it will be updated later, each frame. + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); + + // The VBO containing the colors of the particles + glGenBuffers(1, &particles_color_buffer); + glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); + // Initialize with empty (NULL) buffer : it will be updated later, each frame. + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); + lastTime = glutGet(GLUT_ELAPSED_TIME) / 1000.f; + + glGenTextures(2, colorBuffers); for (unsigned int i = 0; i < 2; i++) @@ -503,7 +728,7 @@ void init() void shutdown() { - + } void onReshape(int width, int height) @@ -524,6 +749,8 @@ int main(int argc, char** argv) glutSetOption(GLUT_MULTISAMPLE, 8); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE); glEnable(GL_MULTISAMPLE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutInitWindowPosition(100, 200); glutInitWindowSize(SCR_WIDTH, SCR_HEIGHT); glutCreateWindow("GRK-PROJECT WIP"); @@ -531,6 +758,7 @@ int main(int argc, char** argv) //glutFullScreen(); glewInit(); + init(); glutKeyboardFunc(keyboard); //to sprawia, że obiekty ukryte przed kamerą nie są renderowane From b3abac8b972c283753c23b08f3800dcf493a9f22 Mon Sep 17 00:00:00 2001 From: xkamikoo <58092037+xkamikoo@users.noreply.github.com> Date: Mon, 1 Feb 2021 01:12:15 +0100 Subject: [PATCH 2/3] kinda works, but ship looks like it's on fire --- grk-project.vcxproj | 4 +-- src/main.cpp | 86 ++++++++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/grk-project.vcxproj b/grk-project.vcxproj index 898082b..5332a2d 100644 --- a/grk-project.vcxproj +++ b/grk-project.vcxproj @@ -51,7 +51,7 @@ {1B448102-E76C-4347-BDC7-40D02A567DB6} Win32Proj grk-cw9 - 10.0 + 10.0.17134.0 grk-project @@ -66,7 +66,7 @@ false true Unicode - v142 + v141 diff --git a/src/main.cpp b/src/main.cpp index 10116a8..eabea19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -410,50 +410,15 @@ void renderScene() drawObjectTexture(programSun, sphereContext, sunModelMatrix, glm::vec3(3.5f, 3.8f, 3.8f), sunTexture); drawObjectTexture(programSun, sphereContext, sunModelMatrix2, glm::vec3(0.9f, 0.9f, 2.0f), sunTexture); - drawSkybox(programSkybox, cubeContext, skyboxTexture); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - bool horizontal = true, first_iteration = true; - unsigned int amount = 10; - glUseProgram(programBlur); - for (unsigned int i = 0; i < amount; i++) - { - glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); - glUniform1i(glGetUniformLocation(programBlur, "horizontal"), horizontal); - glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); - renderQuad(); - horizontal = !horizontal; - if (first_iteration) - first_iteration = false; - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glUseProgram(programBloom); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); - renderQuad(); - - - if (engineLightTimer < 50) engineLightTimer++; - else - { - lights[2].intensity = 0.00001; - lights[3].intensity = 0.00001; - } - - - glutSwapBuffers(); + //particlepart glUseProgram(programParticle); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.f; double delta = currentTime - lastTime; lastTime = currentTime; - glm::mat4 ProjectionMatrix = perspectiveMatrix * glm::mat4(glm::mat3(cameraMatrix)); + glm::mat4 ProjectionMatrix = perspectiveMatrix;// *glm::mat4(glm::mat3(cameraMatrix)); glm::mat4 ViewMatrix = cameraMatrix; glm::vec3 CameraPosition(glm::inverse(ViewMatrix)[3]); glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ViewMatrix; @@ -465,7 +430,7 @@ void renderScene() for (int i = 0; i < newparticles; i++) { int particleIndex = FindUnusedParticle(); ParticlesContainer[particleIndex].life = 100.0f; - ParticlesContainer[particleIndex].pos = glm::vec3(0, 0, 0.0f); + ParticlesContainer[particleIndex].pos = lights[2].position; float spread = 1.5f; glm::vec3 maindir = glm::vec3(0.0f, 0.0f, 0.0f); @@ -484,7 +449,7 @@ void renderScene() ParticlesContainer[particleIndex].b = rand() % 256; ParticlesContainer[particleIndex].a = (rand() % 256) / 3; - ParticlesContainer[particleIndex].size = (rand() % 1000) / 2000.0f + 0.1f; + ParticlesContainer[particleIndex].size = (rand() % 1000) / 50000.0f; } // Simulate all particles @@ -582,6 +547,47 @@ void renderScene() glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); + + + + drawSkybox(programSkybox, cubeContext, skyboxTexture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + bool horizontal = true, first_iteration = true; + unsigned int amount = 10; + glUseProgram(programBlur); + for (unsigned int i = 0; i < amount; i++) + { + glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); + glUniform1i(glGetUniformLocation(programBlur, "horizontal"), horizontal); + glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); + renderQuad(); + horizontal = !horizontal; + if (first_iteration) + first_iteration = false; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glUseProgram(programBloom); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); + renderQuad(); + + + if (engineLightTimer < 50) engineLightTimer++; + else + { + lights[2].intensity = 0.00001; + lights[3].intensity = 0.00001; + } + + + glutSwapBuffers(); + //particlepart + } void init() From 09b261ec905c0c5a33ebc9a7d86be5c15806f260 Mon Sep 17 00:00:00 2001 From: xkamikoo <58092037+xkamikoo@users.noreply.github.com> Date: Mon, 1 Feb 2021 02:22:35 +0100 Subject: [PATCH 3/3] Fixed particles --- grk-project.vcxproj | 2 +- src/main.cpp | 285 +++++++++++++++++++++++--------------------- 2 files changed, 151 insertions(+), 136 deletions(-) diff --git a/grk-project.vcxproj b/grk-project.vcxproj index 5332a2d..1ac3838 100644 --- a/grk-project.vcxproj +++ b/grk-project.vcxproj @@ -59,7 +59,7 @@ Application true Unicode - v142 + v141 Application diff --git a/src/main.cpp b/src/main.cpp index eabea19..89bc249 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,16 +43,14 @@ static GLubyte* g_particule_color_data; GLuint particle_vertex_buffer; GLuint particles_position_buffer; GLuint particles_color_buffer; -GLuint CameraRight_worldspace_ID; -GLuint CameraUp_worldspace_ID; -GLuint ViewProjMatrixID; -GLuint TextureParticle; Core::Shader_Loader shaderLoader; Core::RenderContext armContext; std::vector arm; int ballIndex; +bool bothEngines = true; + GLuint textureShip_normals; GLuint sunTexture; @@ -131,7 +129,7 @@ struct Light { float intensity; }; -int engineLightTimer; +int engineLightTimer = 50; //wczytywanie skyboxa (musi byc jpg!) std::vector faces @@ -309,6 +307,63 @@ void drawSkybox(GLuint program, Core::RenderContext context, GLuint texID) glUseProgram(0); } +void drawParticles(int ParticlesCount, glm::mat4 &transformation) +{ + glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. + glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data); + + glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); + glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. + glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, particleTexture); + glUniform1i(glGetUniformLocation(programParticle, "sprite"), 0); + glUniform3f(glGetUniformLocation(programParticle, "CameraRight_worldspace"), cameraSide.x, cameraSide.y, cameraSide.z); + glUniform3f(glGetUniformLocation(programParticle, "CameraUp_worldspace"), 0, 1, 0); + + glUniformMatrix4fv(glGetUniformLocation(programParticle, "VP"), 1, GL_FALSE, &transformation[0][0]); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, particle_vertex_buffer); + glVertexAttribPointer( + 0, // attribute. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); + glVertexAttribPointer( + 1, // attribute. No particular reason for 1, but must match the layout in the shader. + 4, // size : x + y + z + size => 4 + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); + glVertexAttribPointer( + 2, // attribute. No particular reason for 1, but must match the layout in the shader. + 4, // size : r + g + b + a => 4 + GL_UNSIGNED_BYTE, // type + GL_TRUE, // normalized? *** YES, this means that the unsigned char[4] will be accessible with a vec4 (floats) in the shader *** + 0, // stride + (void*)0 // array buffer offset + ); + glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0 + glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1 + glVertexAttribDivisor(2, 1); // color : one per quad -> 1 + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); +} + //Textures void drawObjectTexture(GLuint program, Core::RenderContext context, glm::mat4 modelMatrix, glm::vec3 texture, GLuint texID) { @@ -377,10 +432,10 @@ void renderScene() lights[0].position = sunPos; lights[1].position = sunPos2; - glm::mat4 engineLeft = glm::translate(shipModelMatrix, glm::vec3(700, 0, -1500)); + glm::mat4 engineLeft = glm::translate(shipModelMatrix, glm::vec3(450, 0, -1500)); lights[2].position = glm::vec3(engineLeft[3][0], engineLeft[3][1], engineLeft[3][2]); - glm::mat4 engineRight = glm::translate(shipModelMatrix, glm::vec3(-700, 0, -1500)); + glm::mat4 engineRight = glm::translate(shipModelMatrix, glm::vec3(-450, 0, -1500)); lights[3].position = glm::vec3(engineRight[3][0], engineRight[3][1], engineRight[3][2]); for (int i = 0; i < lights.size(); i++) @@ -415,41 +470,62 @@ void renderScene() glUseProgram(programParticle); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.f; - double delta = currentTime - lastTime; - lastTime = currentTime; - glm::mat4 ProjectionMatrix = perspectiveMatrix;// *glm::mat4(glm::mat3(cameraMatrix)); - glm::mat4 ViewMatrix = cameraMatrix; - glm::vec3 CameraPosition(glm::inverse(ViewMatrix)[3]); - glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ViewMatrix; - - int newparticles = (int)(delta * 10000.0); - if (newparticles > (int)(0.016f * 10000.0)) - newparticles = (int)(0.016f * 10000.0); + double delta = time - lastTime; + lastTime = time; + + glm::mat4 transformation = perspectiveMatrix * cameraMatrix; + + int newparticles = 0; + + if (engineLightTimer < 40) + { + engineLightTimer++; + newparticles = (int)(delta * 10000.0); + if (newparticles > (int)(0.016f * 10000.0)) + newparticles = (int)(0.016f * 10000.0); + } + else + { + lights[2].intensity = 0.00001; + lights[3].intensity = 0.00001; + } for (int i = 0; i < newparticles; i++) { int particleIndex = FindUnusedParticle(); ParticlesContainer[particleIndex].life = 100.0f; - ParticlesContainer[particleIndex].pos = lights[2].position; + if (lights[2].intensity > 0.001 && lights[3].intensity > 0.001) + { + if (rand() % 2) + ParticlesContainer[particleIndex].pos = lights[2].position; - float spread = 1.5f; + else + ParticlesContainer[particleIndex].pos = lights[3].position; + } + else if(lights[2].intensity > 0.001) + ParticlesContainer[particleIndex].pos = lights[2].position; + + else if (lights[3].intensity > 0.001) + ParticlesContainer[particleIndex].pos = lights[3].position; + + + float spread = 1.0f; glm::vec3 maindir = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 randomdir = glm::vec3( - (rand() % 2000 - 1000.0f) / 1000.0f, - (rand() % 2000 - 1000.0f) / 1000.0f, - (rand() % 2000 - 1000.0f) / 1000.0f + (rand() % 2000 - 1000.0f) / 5000.0f, + (rand() % 2000 - 1000.0f) / 5000.0f, + (rand() % 2000 - 1000.0f) / 5000.0f ); ParticlesContainer[particleIndex].speed = maindir + randomdir * spread; // Very bad way to generate a random color - ParticlesContainer[particleIndex].r = rand() % 256; - ParticlesContainer[particleIndex].g = rand() % 256; - ParticlesContainer[particleIndex].b = rand() % 256; + ParticlesContainer[particleIndex].r = rand() % 100 + 100; + ParticlesContainer[particleIndex].g = 0; + ParticlesContainer[particleIndex].b = rand() % 100 + 50; ParticlesContainer[particleIndex].a = (rand() % 256) / 3; - ParticlesContainer[particleIndex].size = (rand() % 1000) / 50000.0f; + ParticlesContainer[particleIndex].size = (rand() % 1000) / 50000.0f + 0.01f; } // Simulate all particles @@ -492,64 +568,9 @@ void renderScene() } } - + SortParticles(); - glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); - glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. - glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data); - - glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); - glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. - glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, particleTexture); - glUniform1i(TextureParticle, 0); - glUniform3f(CameraRight_worldspace_ID, ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]); - glUniform3f(CameraUp_worldspace_ID, ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]); - - glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]); - - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, particle_vertex_buffer); - glVertexAttribPointer( - 0, // attribute. No particular reason for 0, but must match the layout in the shader. - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - (void*)0 // array buffer offset - ); - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); - glVertexAttribPointer( - 1, // attribute. No particular reason for 1, but must match the layout in the shader. - 4, // size : x + y + z + size => 4 - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - (void*)0 // array buffer offset - ); - glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); - glVertexAttribPointer( - 2, // attribute. No particular reason for 1, but must match the layout in the shader. - 4, // size : r + g + b + a => 4 - GL_UNSIGNED_BYTE, // type - GL_TRUE, // normalized? *** YES, this means that the unsigned char[4] will be accessible with a vec4 (floats) in the shader *** - 0, // stride - (void*)0 // array buffer offset - ); - glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0 - glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1 - glVertexAttribDivisor(2, 1); // color : one per quad -> 1 - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount); - - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - glDisableVertexAttribArray(2); - - - + drawParticles(ParticlesCount, transformation); drawSkybox(programSkybox, cubeContext, skyboxTexture); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -576,63 +597,13 @@ void renderScene() glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); renderQuad(); - - if (engineLightTimer < 50) engineLightTimer++; - else - { - lights[2].intensity = 0.00001; - lights[3].intensity = 0.00001; - } - - glutSwapBuffers(); - //particlepart - } -void init() +void init_particles() { - glEnable(GL_DEPTH_TEST); - programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag"); - programSkybox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag"); - programSun = shaderLoader.CreateProgram("shaders/shader_sun.vert", "shaders/shader_sun.frag"); - programBlur = shaderLoader.CreateProgram("shaders/shader_blur.vert", "shaders/shader_blur.frag"); - programBloom = shaderLoader.CreateProgram("shaders/shader_bloom.vert", "shaders/shader_bloom.frag"); - programParticle = shaderLoader.CreateProgram("shaders/shader_particle.vert", "shaders/shader_particle.frag"); - - glUseProgram(programBlur); - glUniform1i(glGetUniformLocation(programBlur, "image"), 0); - glUseProgram(programBloom); - glUniform1i(glGetUniformLocation(programBloom, "scene"), 0); - glUniform1i(glGetUniformLocation(programBloom, "bloomBlur"), 1); - glUseProgram(0); - - - corvette = std::make_shared("models/Corvette-F3.obj"); - crewmate = std::make_shared("models/space_humster.obj"); - //shipModel = obj::loadModelFromFile("models/spaceship.obj"); - sphereModel = obj::loadModelFromFile("models/sphere.obj"); - cubeModel = obj::loadModelFromFile("models/cube.obj"); - - sphereContext.initFromOBJ(sphereModel); - cubeContext.initFromOBJ(cubeModel); - //shipContext.initFromOBJ(shipModel); - shipTexture = Core::LoadTexture("textures/spaceship.png"); - sunTexture = Core::LoadTexture("textures/sun.png"); - earthTexture = Core::LoadTexture("textures/earth2.png"); - moonTexture = Core::LoadTexture("textures/moon.png"); - particleTexture = Core::LoadTexture("textures/sun.png"); - skyboxTexture = loadCubemap(faces); - - glGenFramebuffers(1, &FBO); - glBindFramebuffer(GL_FRAMEBUFFER, FBO); - //particlepart glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); - CameraRight_worldspace_ID = glGetUniformLocation(programParticle, "CameraRight_worldspace"); - CameraUp_worldspace_ID = glGetUniformLocation(programParticle, "CameraUp_worldspace"); - ViewProjMatrixID = glGetUniformLocation(programParticle, "VP"); - TextureParticle = glGetUniformLocation(programParticle, "sprite"); g_particule_position_size_data = new GLfloat[MaxParticles * 4]; g_particule_color_data = new GLubyte[MaxParticles * 4]; for (int i = 0; i < MaxParticles; i++) { @@ -660,7 +631,12 @@ void init() // Initialize with empty (NULL) buffer : it will be updated later, each frame. glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); lastTime = glutGet(GLUT_ELAPSED_TIME) / 1000.f; +} +void init_bloom() +{ + glGenFramebuffers(1, &FBO); + glBindFramebuffer(GL_FRAMEBUFFER, FBO); glGenTextures(2, colorBuffers); @@ -705,6 +681,45 @@ void init() if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer not complete!" << std::endl; } +} + +void init() +{ + glEnable(GL_DEPTH_TEST); + programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag"); + programSkybox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag"); + programSun = shaderLoader.CreateProgram("shaders/shader_sun.vert", "shaders/shader_sun.frag"); + programBlur = shaderLoader.CreateProgram("shaders/shader_blur.vert", "shaders/shader_blur.frag"); + programBloom = shaderLoader.CreateProgram("shaders/shader_bloom.vert", "shaders/shader_bloom.frag"); + programParticle = shaderLoader.CreateProgram("shaders/shader_particle.vert", "shaders/shader_particle.frag"); + + glUseProgram(programBlur); + glUniform1i(glGetUniformLocation(programBlur, "image"), 0); + glUseProgram(programBloom); + glUniform1i(glGetUniformLocation(programBloom, "scene"), 0); + glUniform1i(glGetUniformLocation(programBloom, "bloomBlur"), 1); + glUseProgram(0); + + + corvette = std::make_shared("models/Corvette-F3.obj"); + crewmate = std::make_shared("models/space_humster.obj"); + //shipModel = obj::loadModelFromFile("models/spaceship.obj"); + sphereModel = obj::loadModelFromFile("models/sphere.obj"); + cubeModel = obj::loadModelFromFile("models/cube.obj"); + + sphereContext.initFromOBJ(sphereModel); + cubeContext.initFromOBJ(cubeModel); + //shipContext.initFromOBJ(shipModel); + shipTexture = Core::LoadTexture("textures/spaceship.png"); + sunTexture = Core::LoadTexture("textures/sun.png"); + earthTexture = Core::LoadTexture("textures/earth2.png"); + moonTexture = Core::LoadTexture("textures/moon.png"); + particleTexture = Core::LoadTexture("textures/sun.png"); + skyboxTexture = loadCubemap(faces); + + init_particles(); + init_bloom(); + Light l1; l1.position = sunPos;