particles attached to cameraPos, cleaning code
This commit is contained in:
parent
782d777654
commit
dcdbcb9588
@ -1,16 +1,13 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
// Interpolated values from the vertex shaders
|
|
||||||
in vec2 UV;
|
in vec2 UV;
|
||||||
in vec4 particlecolor;
|
in vec4 particlecolor;
|
||||||
|
|
||||||
// Ouput data
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
uniform sampler2D myTextureSampler;
|
uniform sampler2D myTextureSampler;
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
// Output color = color of the texture at the specified UV
|
|
||||||
color = texture( myTextureSampler, UV ) * particlecolor;
|
color = texture( myTextureSampler, UV ) * particlecolor;
|
||||||
|
|
||||||
}
|
}
|
@ -1,22 +1,19 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
// Input vertex data, different for all executions of this shader.
|
|
||||||
layout(location = 0) in vec3 squareVertices;
|
layout(location = 0) in vec3 squareVertices;
|
||||||
layout(location = 1) in vec4 xyzs; // Position of the center of the particule and size of the square
|
layout(location = 1) in vec4 xyzs; // Position of the center of the particule and size of the square
|
||||||
layout(location = 2) in vec4 color; // Position of the center of the particule and size of the square
|
layout(location = 2) in vec4 color; // Position of the center of the particule and size of the square
|
||||||
|
|
||||||
// Output data ; will be interpolated for each fragment.
|
|
||||||
out vec2 UV;
|
out vec2 UV;
|
||||||
out vec4 particlecolor;
|
out vec4 particlecolor;
|
||||||
|
|
||||||
// Values that stay constant for the whole mesh.
|
|
||||||
uniform vec3 CameraRight_worldspace;
|
uniform vec3 CameraRight_worldspace;
|
||||||
uniform vec3 CameraUp_worldspace;
|
uniform vec3 CameraUp_worldspace;
|
||||||
uniform mat4 VP; // Model-View-Projection matrix, but without the Model (the position is in BillboardPos; the orientation depends on the camera)
|
uniform mat4 VP;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float particleSize = xyzs.w; // because we encoded it this way.
|
float particleSize = xyzs.w;
|
||||||
vec3 particleCenter_wordspace = xyzs.xyz;
|
vec3 particleCenter_wordspace = xyzs.xyz;
|
||||||
|
|
||||||
vec3 vertexPosition_worldspace =
|
vec3 vertexPosition_worldspace =
|
||||||
@ -24,10 +21,8 @@ void main()
|
|||||||
+ CameraRight_worldspace * squareVertices.x * particleSize
|
+ CameraRight_worldspace * squareVertices.x * particleSize
|
||||||
+ CameraUp_worldspace * squareVertices.y * particleSize;
|
+ CameraUp_worldspace * squareVertices.y * particleSize;
|
||||||
|
|
||||||
// Output position of the vertex
|
|
||||||
gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f);
|
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);
|
UV = squareVertices.xy + vec2(0.5, 0.5);
|
||||||
particlecolor = color;
|
particlecolor = color;
|
||||||
}
|
}
|
@ -36,13 +36,12 @@ double lastTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
|
|||||||
// CPU representation of a particle
|
// CPU representation of a particle
|
||||||
struct Particle {
|
struct Particle {
|
||||||
glm::vec3 pos, speed;
|
glm::vec3 pos, speed;
|
||||||
unsigned char r, g, b, a; // Color
|
unsigned char r, g, b, a;
|
||||||
float size, angle, weight;
|
float size, angle, weight;
|
||||||
float life; // Remaining life of the particle. if <0 : dead and unused.
|
float life;
|
||||||
float cameradistance; // *Squared* distance to the camera. if dead : -1.0f
|
float cameradistance;
|
||||||
|
|
||||||
bool operator<(const Particle& that) const {
|
bool operator<(const Particle& that) const {
|
||||||
// Sort in reverse order : far particles drawn first.
|
|
||||||
return this->cameradistance > that.cameradistance;
|
return this->cameradistance > that.cameradistance;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -57,7 +56,7 @@ void addParticleSource(glm::vec3 pos, double amount, float spread) {
|
|||||||
particleSources.push_back(particleSource);
|
particleSources.push_back(particleSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MaxParticles = 10000;
|
const int MaxParticles = 100000;
|
||||||
Particle ParticlesContainer[MaxParticles];
|
Particle ParticlesContainer[MaxParticles];
|
||||||
int LastUsedParticle = 0;
|
int LastUsedParticle = 0;
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ int FindUnusedParticle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; // All particles are taken, override the first one
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SortParticles() {
|
void SortParticles() {
|
||||||
@ -216,23 +215,18 @@ void initParticles() {
|
|||||||
|
|
||||||
void spawnParticles(double deltaTime, glm::vec3 sourcePosition, double amount, float spread) {
|
void spawnParticles(double deltaTime, glm::vec3 sourcePosition, double amount, float spread) {
|
||||||
|
|
||||||
// Generate 10 new particule each millisecond,
|
|
||||||
// but limit this to 16 ms (60 fps), or if you have 1 long frame (1sec),
|
|
||||||
// newparticles will be huge and the next frame even longer.
|
|
||||||
int newparticles = (int)(deltaTime * amount);
|
int newparticles = (int)(deltaTime * amount);
|
||||||
if (newparticles > (int)(0.016f * amount))
|
if (newparticles > (int)(0.016f * amount))
|
||||||
newparticles = (int)(0.016f * amount);
|
newparticles = (int)(0.016f * amount);
|
||||||
|
|
||||||
for (int i = 0; i < newparticles; i++) {
|
for (int i = 0; i < newparticles; i++) {
|
||||||
int particleIndex = FindUnusedParticle();
|
int particleIndex = FindUnusedParticle();
|
||||||
ParticlesContainer[particleIndex].life = 20.0f; // This particle will live 5 seconds.
|
ParticlesContainer[particleIndex].life = 20.0f;
|
||||||
|
|
||||||
ParticlesContainer[particleIndex].pos = sourcePosition;
|
ParticlesContainer[particleIndex].pos = sourcePosition;
|
||||||
|
|
||||||
glm::vec3 maindir = glm::vec3(0.0f, 0.4f, 0.0f);
|
glm::vec3 maindir = glm::vec3(0.0f, 0.4f, 0.0f);
|
||||||
// Very bad way to generate a random direction;
|
|
||||||
// See for instance http://stackoverflow.com/questions/5408276/python-uniform-spherical-distribution instead,
|
|
||||||
// combined with some user-controlled parameters (main direction, spread, etc)
|
|
||||||
glm::vec3 randomdir = glm::vec3(
|
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) / 1000.0f,
|
||||||
@ -241,8 +235,6 @@ void spawnParticles(double deltaTime, glm::vec3 sourcePosition, double amount, f
|
|||||||
|
|
||||||
ParticlesContainer[particleIndex].speed = maindir + randomdir * spread;
|
ParticlesContainer[particleIndex].speed = maindir + randomdir * spread;
|
||||||
|
|
||||||
|
|
||||||
// Very bad way to generate a random color
|
|
||||||
ParticlesContainer[particleIndex].r = 200;
|
ParticlesContainer[particleIndex].r = 200;
|
||||||
ParticlesContainer[particleIndex].g = 200;
|
ParticlesContainer[particleIndex].g = 200;
|
||||||
ParticlesContainer[particleIndex].b = 255;
|
ParticlesContainer[particleIndex].b = 255;
|
||||||
@ -254,11 +246,10 @@ void spawnParticles(double deltaTime, glm::vec3 sourcePosition, double amount, f
|
|||||||
}
|
}
|
||||||
|
|
||||||
void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
||||||
// Simulate all particles
|
|
||||||
ParticlesCount = 0;
|
ParticlesCount = 0;
|
||||||
for (int i = 0; i < MaxParticles; i++) {
|
for (int i = 0; i < MaxParticles; i++) {
|
||||||
|
|
||||||
Particle& p = ParticlesContainer[i]; // shortcut
|
Particle& p = ParticlesContainer[i];
|
||||||
|
|
||||||
if (p.life > 0.0f) {
|
if (p.life > 0.0f) {
|
||||||
|
|
||||||
@ -271,7 +262,6 @@ void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
|||||||
p.speed += glm::vec3(0.0f, 1.0f, 0.0f) * (float)deltaTime * 0.5f;
|
p.speed += glm::vec3(0.0f, 1.0f, 0.0f) * (float)deltaTime * 0.5f;
|
||||||
p.pos += p.speed * (float)deltaTime;
|
p.pos += p.speed * (float)deltaTime;
|
||||||
p.cameradistance = glm::length2(p.pos - cameraPos);
|
p.cameradistance = glm::length2(p.pos - cameraPos);
|
||||||
//ParticlesContainer[i].pos += glm::vec3(0.0f,10.0f, 0.0f) * (float)delta;
|
|
||||||
|
|
||||||
// Fill the GPU buffer
|
// Fill the GPU buffer
|
||||||
g_particule_position_size_data[4 * ParticlesCount + 0] = p.pos.x;
|
g_particule_position_size_data[4 * ParticlesCount + 0] = p.pos.x;
|
||||||
@ -287,7 +277,6 @@ void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Particles that just died will be put at the end of the buffer in SortParticles();
|
|
||||||
p.cameradistance = -1.0f;
|
p.cameradistance = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,24 +284,17 @@ void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SortParticles();
|
SortParticles();
|
||||||
|
|
||||||
// printf("%d ", ParticlesCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateParticles() {
|
void updateParticles() {
|
||||||
// Update the buffers that OpenGL uses for rendering.
|
|
||||||
// There are much more sophisticated means to stream data from the CPU to the GPU,
|
|
||||||
// but this is outside the scope of this tutorial.
|
|
||||||
// http://www.opengl.org/wiki/Buffer_Object_Streaming
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
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.
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
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.
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,13 +313,11 @@ void bindParticles(GLuint programParticles, glm::vec3 cameraSide, glm::vec3 came
|
|||||||
// fragment shader
|
// fragment shader
|
||||||
GLuint TextureID = glGetUniformLocation(programParticles, "myTextureSampler");
|
GLuint TextureID = glGetUniformLocation(programParticles, "myTextureSampler");
|
||||||
|
|
||||||
// Bind our texture in Texture Unit 0
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, particleTexture);
|
glBindTexture(GL_TEXTURE_2D, particleTexture);
|
||||||
// Set our "myTextureSampler" sampler to user Texture Unit 0
|
|
||||||
glUniform1i(TextureID, 0);
|
glUniform1i(TextureID, 0);
|
||||||
|
|
||||||
// Same as the billboards tutorial
|
|
||||||
glUniform3f(CameraRight_worldspace_ID, cameraSide.x, cameraSide.y, cameraSide.z);
|
glUniform3f(CameraRight_worldspace_ID, cameraSide.x, cameraSide.y, cameraSide.z);
|
||||||
glUniform3f(CameraUp_worldspace_ID, cameraVertical.x, cameraVertical.y, cameraVertical.z);
|
glUniform3f(CameraUp_worldspace_ID, cameraVertical.x, cameraVertical.y, cameraVertical.z);
|
||||||
|
|
||||||
@ -345,58 +325,28 @@ void bindParticles(GLuint programParticles, glm::vec3 cameraSide, glm::vec3 came
|
|||||||
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, (float*)&transformation);
|
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, (float*)&transformation);
|
||||||
|
|
||||||
|
|
||||||
// 1rst attribute buffer : vertices
|
// vertices
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
|
||||||
glVertexAttribPointer(
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0, (void*)0);
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2nd attribute buffer : positions of particles' centers
|
// positions of particles' centers
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
||||||
glVertexAttribPointer(
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,0, (void*)0);
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3rd attribute buffer : particles' colors
|
// particles' colors
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
||||||
glVertexAttribPointer(
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderParticles() {
|
void renderParticles() {
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
||||||
// These functions are specific to glDrawArrays*Instanced*.
|
|
||||||
// The first parameter is the attribute buffer we're talking about.
|
|
||||||
// The second parameter is the "rate at which generic vertex attributes advance when rendering multiple instances"
|
|
||||||
// http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml
|
|
||||||
glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
|
glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
|
||||||
glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1
|
glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1
|
||||||
glVertexAttribDivisor(2, 1); // color : one per quad -> 1
|
glVertexAttribDivisor(2, 1); // color : one per quad -> 1
|
||||||
|
|
||||||
// Draw the particules !
|
|
||||||
// This draws many times a small triangle_strip (which looks like a quad).
|
|
||||||
// This is equivalent to :
|
|
||||||
// for(i in ParticlesCount) : glDrawArrays(GL_TRIANGLE_STRIP, 0, 4),
|
|
||||||
// but faster.
|
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
||||||
|
|
||||||
glDisableVertexAttribArray(0);
|
glDisableVertexAttribArray(0);
|
||||||
@ -408,12 +358,14 @@ void handleAllParticleSources(glm::vec3 cameraPos, GLuint programParticles, glm:
|
|||||||
double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
|
double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
|
||||||
double delta = currentTime - lastTime;
|
double delta = currentTime - lastTime;
|
||||||
lastTime = currentTime;
|
lastTime = currentTime;
|
||||||
//std::cout << particleSources.size() << std::endl;
|
|
||||||
for (ParticleSource particleSource : particleSources)
|
for (ParticleSource particleSource : particleSources)
|
||||||
{
|
{
|
||||||
//std::cout << particleSource.pos.x << " " << particleSource.pos.y << "" << particleSource.pos.z << "" << std::endl;
|
|
||||||
spawnParticles(delta, particleSource.pos, particleSource.amount, particleSource.spread);
|
spawnParticles(delta, particleSource.pos, particleSource.amount, particleSource.spread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((int)currentTime % 1 == 0) {
|
||||||
|
particleSources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
simulateParticles(cameraPos, delta);
|
simulateParticles(cameraPos, delta);
|
||||||
updateParticles();
|
updateParticles();
|
||||||
|
@ -206,6 +206,7 @@ void keyboard(unsigned char key, int x, int y)
|
|||||||
float angleSpeed = 10.f;
|
float angleSpeed = 10.f;
|
||||||
float moveSpeed = 1.0f;
|
float moveSpeed = 1.0f;
|
||||||
glm::vec3 nextPosition;
|
glm::vec3 nextPosition;
|
||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 'z': cursorDiff.z -= angleSpeed; break;
|
case 'z': cursorDiff.z -= angleSpeed; break;
|
||||||
@ -214,12 +215,15 @@ void keyboard(unsigned char key, int x, int y)
|
|||||||
nextPosition = cameraPos + (cameraDir * moveSpeed);
|
nextPosition = cameraPos + (cameraDir * moveSpeed);
|
||||||
if (isInBoundaries(nextPosition)) {
|
if (isInBoundaries(nextPosition)) {
|
||||||
cameraPos = nextPosition;
|
cameraPos = nextPosition;
|
||||||
|
addParticleSource(cameraPos, 1000.0f, 0.6f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
|
||||||
nextPosition = cameraPos - (cameraDir * moveSpeed);
|
nextPosition = cameraPos - (cameraDir * moveSpeed);
|
||||||
if (isInBoundaries(nextPosition)) {
|
if (isInBoundaries(nextPosition)) {
|
||||||
cameraPos = nextPosition;
|
cameraPos = nextPosition;
|
||||||
|
addParticleSource(cameraPos, 1000.0f, 0.6f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
@ -271,7 +275,6 @@ glm::mat4 createCameraMatrix()
|
|||||||
|
|
||||||
glm::quat rotationChange = rotation_x * rotation_y * rotation_z;
|
glm::quat rotationChange = rotation_x * rotation_y * rotation_z;
|
||||||
rotation = glm::normalize(rotationChange * rotation);
|
rotation = glm::normalize(rotationChange * rotation);
|
||||||
|
|
||||||
cameraDir = glm::inverse(rotation) * glm::vec3(0, 0, -1);
|
cameraDir = glm::inverse(rotation) * glm::vec3(0, 0, -1);
|
||||||
cameraSide = glm::inverse(rotation) * glm::vec3(1, 0, 0);
|
cameraSide = glm::inverse(rotation) * glm::vec3(1, 0, 0);
|
||||||
cameraVertical = glm::inverse(rotation) * glm::vec3(0, 1, 0);
|
cameraVertical = glm::inverse(rotation) * glm::vec3(0, 1, 0);
|
||||||
@ -359,6 +362,7 @@ void renderScene()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.f;
|
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.f;
|
||||||
|
|
||||||
glUseProgram(skyboxProgram);
|
glUseProgram(skyboxProgram);
|
||||||
glUniform1i(glGetUniformLocation(skyboxProgram, "skybox"), 0);
|
glUniform1i(glGetUniformLocation(skyboxProgram, "skybox"), 0);
|
||||||
glm::mat4 transformation = perspectiveMatrix * cameraMatrix;
|
glm::mat4 transformation = perspectiveMatrix * cameraMatrix;
|
||||||
@ -370,7 +374,7 @@ void renderScene()
|
|||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
addParticleSource(glm::vec3(cameraPos.x, cameraPos.y - 0.5, cameraPos.z -0.4), 100.0f, 1.5f);
|
|
||||||
glm::mat4 submarineInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.25f));
|
glm::mat4 submarineInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.25f));
|
||||||
glm::mat4 submarineModelMatrix = glm::translate(cameraPos + cameraDir) * glm::mat4_cast(glm::inverse(rotation)) * submarineInitialTransformation;
|
glm::mat4 submarineModelMatrix = glm::translate(cameraPos + cameraDir) * glm::mat4_cast(glm::inverse(rotation)) * submarineInitialTransformation;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user