Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[OpenGL GLFW GLAD] Snowstorm - Czyli system cząstek i płatki śniegu

Ostatnio zmodyfikowano 2025-02-15 08:05
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-10 10:29:29
Udało się ale ... ale każdy płatek to oddzielny obiekt więc optymalizacja leży..


C/C++
const char * snowflake_vertex_shader_source = R"( #version 330 core layout (location = 0) in vec3 position; layout (location = 1) in vec2 texcoords; uniform mat4 projection; uniform mat4 view; uniform mat4 model; out vec2 TexCoords; out vec4 FragPosition; void main() { TexCoords = texcoords; FragPosition = view * model * vec4(position, 1.0); gl_Position = projection * FragPosition; } )";

const char * snowflake_fragment_shader_source = R"( #version 330 core in vec2 TexCoords; in vec4 FragPosition; uniform sampler2D tex; // Tekstura uniform vec3 fogColor; uniform float fogStart; uniform float fogEnd; out vec4 FragColor; void main() { // Obliczenie współczynnika mgły float fogFactor = (fogEnd - abs(FragPosition.z)) / (fogEnd - fogStart); fogFactor = clamp(fogFactor, 0.0, 1.0); // Pobranie koloru tekstury vec3 texColor = texture(tex, TexCoords).rgb; // Finalny kolor z uwzględnieniem mgły FragColor = vec4(mix(fogColor, texColor, fogFactor), 1.0); } )";

std::random_device rd;
std::mt19937 generator = std::mt19937( rd() );

glm::vec3 generateFallingSnowFlakePosition( glm::vec3 rect_position, glm::vec3 rect_size ) {
   
   
glm::vec3 pos;
   
   
std::uniform_real_distribution < > dis;
   
dis = std::uniform_real_distribution < >( rect_position.x - rect_size.x / 2.0f, rect_position.x + rect_size.x / 2.0f );
   
pos.x = rect_position.x + dis( generator );
   
   
dis = std::uniform_real_distribution < >( 0, rect_position.y + rect_size.y / 2.0f );
   
pos.y = rect_position.y + dis( generator );
   
   
dis = std::uniform_real_distribution < >( rect_position.z - rect_size.z / 2.0f, rect_position.z + rect_size.z / 2.0f );
   
pos.z = rect_position.z + dis( generator );
   
   
return pos;
}

class Snowflake {
public:
   
unsigned int VAO; // VERTEX ARRAY OBJECTS (VAO stores information about how data in VBO and EBO is used)
   
unsigned int vertices_buffer; // VERTEX BUFFER OBJECTS (VERTEXES)
   
   
Transform transform;
   
   
std::vector < float > vertices;
   
float speed = 0.1f;
   
   
Program * prog;
   
   
unsigned int tex;
   
   
Snowflake() {
       
// transform
       
transform.position = glm::vec3( 0 );
       
transform.scale = glm::vec3( 1 );
       
       
// texture
       
tex = 0;
       
       
// program
       
prog = nullptr;
       
       
// vertexes
       
vertices = {
           
// x, y, z, tu, tv
           
- 0.1f, - 0.1f, 0.0f, 0.0f, 0.0f,
           
0.1f, - 0.1f, 0.0f, 1.0f, 0.0f,
           
- 0.1f, 0.1f, 0.0f, 0.0f, 1.0f,
           
// x, y, z, tu, tv
           
0.1f, - 0.1f, 0.0f, 1.0f, 0.0f,
           
0.1f, 0.1f, 0.0f, 1.0f, 1.0f,
           
- 0.1f, 0.1f, 0.0f, 0.0f, 1.0f
       
};
       
       
       
glGenVertexArrays( 1, & VAO );
       
glGenBuffers( 1, & vertices_buffer );
       
       
glBindVertexArray( VAO );
       
glBindBuffer( GL_ARRAY_BUFFER, vertices_buffer );
       
glBufferData( GL_ARRAY_BUFFER, vertices.size() * sizeof( float ), vertices.data(), GL_STATIC_DRAW );
       
       
// Pozycja wierzchołka (layout 0)
       
glEnableVertexAttribArray( 0 );
       
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof( float ),( void * ) 0 );
       
       
// Współrzędne tekstury (layout 1)
       
glEnableVertexAttribArray( 1 );
       
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof( float ),( void * )( 3 * sizeof( float ) ) );
       
       
glBindVertexArray( 0 );
       
       
   
}
   
   
void setPosition( glm::vec3 position ) {
       
transform.setPosition( position );
   
}
   
   
void setProgram( Program * program ) {
       
prog = program;
   
}
   
   
void setTexture( unsigned int & texture ) {
       
tex = texture;
   
}
   
   
void update( glm::vec3 rect_position, glm::vec3 rect_size ) {
       
transform.position.y -= 0.01f;
       
       
if( transform.position.y < 0 ) {
           
transform.setPosition( generateFallingSnowFlakePosition( rect_position, rect_size ) );
       
}
    }
   
   
void draw( Camera * cam ) {
       
       
glUseProgram( prog->shader_program );
       
       
// active the texture
       
glActiveTexture( GL_TEXTURE0 );
       
glBindTexture( GL_TEXTURE_2D, tex );
       
glUniform1i( glGetUniformLocation( prog->shader_program, "tex" ), 0 );
       
glUniform3f( glGetUniformLocation( prog->shader_program, "fogColor" ), 0.25f, 0.25f, 0.25f );
       
glUniform1f( glGetUniformLocation( prog->shader_program, "fogStart" ), 1.0f );
       
glUniform1f( glGetUniformLocation( prog->shader_program, "fogEnd" ), 15.0f );
       
       
// send metrices
       
glm::mat4 view = cam->GetViewMatrix();
       
glm::mat4 projection = glm::perspective( glm::radians( 45.0f ), 800.0f / 600.0f, 0.1f, 100.0f );
       
glm::mat4 model = glm::mat4( 1.0f );
       
       
model = glm::translate( model, transform.position );
       
model = glm::rotate( model, glm::radians( transform.rotation.x ), glm::vec3( 1.0f, 0.0f, 0.0f ) );
       
model = glm::rotate( model, glm::radians( transform.rotation.y ), glm::vec3( 0.0f, 1.0f, 0.0f ) );
       
model = glm::rotate( model, glm::radians( transform.rotation.z ), glm::vec3( 0.0f, 0.0f, 1.0f ) );
       
model = glm::scale( model, transform.scale );
       
       
glUniformMatrix4fv( glGetUniformLocation( prog->shader_program, "projection" ), 1, GL_FALSE, & projection[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( prog->shader_program, "view" ), 1, GL_FALSE, & view[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( prog->shader_program, "model" ), 1, GL_FALSE, & model[ 0 ][ 0 ] );
       
       
// draw object
       
glPointSize( 10.0f );
       
glBindVertexArray( VAO );
       
glDrawArrays( GL_TRIANGLES, 0, vertices.size() / 5 );
       
glBindVertexArray( 0 );
   
}
   
}
;

class SnowStorm {
public:
   
glm::vec3 rect_position;
   
glm::vec3 rect_size;
   
short snowflakes_count;
   
std::vector < Snowflake * > snowflakes;
   
   
int texture_width, texture_height, texture_nrChannels;
   
unsigned int texture;
   
   
SnowStorm( Program * program ) {
       
       
rect_position = glm::vec3( 0, 20, 0 );
       
rect_size = glm::vec3( 15, 5, 15 );
       
       
snowflakes_count = 1000;
       
       
loadTexture( "textures/snowflake.png" );
       
       
for( short i = 0; i < snowflakes_count; i++ ) {
           
Snowflake * snow = new Snowflake();
           
glm::vec3 position = generateFallingSnowFlakePosition( rect_position, rect_size );
           
snow->setProgram( program );
           
snow->setTexture( texture );
           
snow->setPosition( position );
           
snowflakes.push_back( snow );
       
}
       
    }
   
   
~SnowStorm() {
       
       
for( auto & snow: snowflakes ) {
           
delete snow;
       
}
       
       
snowflakes.clear();
   
}
   
   
void loadTexture( std::string texture_pathfile ) {
       
       
glGenTextures( 1, & texture );
       
glBindTexture( GL_TEXTURE_2D, texture );
       
       
// Konfiguracja tekstury
       
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
       
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
       
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
       
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
       
       
stbi_set_flip_vertically_on_load( true );
       
unsigned char * data = stbi_load( texture_pathfile.c_str(), & texture_width, & texture_height, & texture_nrChannels, 0 );
       
       
if( data ) {
           
GLenum format =( texture_nrChannels == 4 ) ? GL_RGBA
                : GL_RGB;
           
glTexImage2D( GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, data );
           
glGenerateMipmap( GL_TEXTURE_2D );
           
stbi_image_free( data );
       
}
       
else {
           
std::cout << "Failed to load texture: " << texture_pathfile << "\n";
       
}
       
       
glBindTexture( GL_TEXTURE_2D, 0 ); // Odpięcie tekstury!
       
       
   
}
   
   
void update() {
       
for( auto & snow: snowflakes ) {
           
snow->update( rect_position, rect_size );
       
}
    }
   
   
void draw( Camera * cam ) {
       
for( auto & snow: snowflakes ) {
           
snow->draw( cam );
       
}
    }
}
;
P-182123
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-10 11:15:07
należy dopiać poniższy kod aby usunąć czarne tło z płatków śniegu

C/C++
glEnable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

P-182124
DejaVu
» 2025-02-10 15:03:51
Czyli sam ogarnąłeś rozwiązanie :) good job!
P-182125
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-12 07:39:26
No tak prawie, bo znalazłem BUGa. Gdy jeden płatek śniegu nachodzi na drugi to przezroczyste tło zamalowuje drugi płatek.


I jeszcze znalazłem taki oto kurs z GLFW  GLAD tak więc jest to drugi kurs z którego można się uczyć (pierwszy to http://learnopengl.com)

https://helion.pl/kurs/opengl-kurs-video-wprowadzenie-do-programowania-grafiki-komputerowej-krzysztof-szenk
P-182127
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-12 11:45:38
Podmieniłem teksturę płatka śniegu na taką, która tło ma przezroczyste a płatek jest częściowo sam półprzezroczysty oraz zaktualizowałem fragment shader odpowiedzialny za renderowanie płatka:


C/C++
const char * snowflake_fragment_shader_source = R"( #version 330 core in vec2 TexCoords; in vec4 FragPosition; uniform sampler2D tex; // Tekstura płatka śniegu uniform vec4 fogColor; uniform float fogStart; uniform float fogEnd; out vec4 FragColor; void main() { // Pobranie koloru tekstury (z kanałem alfa) vec4 texColor = texture(tex, TexCoords); // Jeśli piksel jest prawie niewidoczny -> pomijamy go if (texColor.a < 0.1) discard; // Obliczenie współczynnika mgły na podstawie głębi fragmentu float fogFactor = (fogEnd - gl_FragCoord.z) / (fogEnd - fogStart); fogFactor = clamp(fogFactor, 0.0, 1.0); // Finalny kolor: mgła + tekstura + przezroczystość FragColor = mix(fogColor, texColor, fogFactor); FragColor.a = texColor.a; // Utrzymanie przezroczystości płatka } )";
P-182128
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-12 12:40:25
Płatki śniegu opadają to fakt, ale zazwyczaj działa na nie wiatr no i opadają z różnym przesunięciem tzn raz w prawo, raz w lewo, naprzemiennie lub też nie. Zastanawiam się jak to zrealizować, aby wyglądało to naturalnie. Ma ktoś jakiś pomysł jak to zrealizować?
P-182129
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-15 08:05:10
Dodałem wiatr do płatków śniegu - teraz poruszają się w osii x i z podczas opadania, a także niektóre są spowolnianie (opór wiatru)

https://youtu.be/uuJWxvZl6IE

C/C++
void update( glm::vec3 rect_position, glm::vec3 rect_size ) {
   
   
transform.position.y -= 0.01f;
   
   
if( transform.position.y < 0 ) {
       
transform.setPosition( generateFallingSnowFlakePosition( rect_position, rect_size ) );
       
wind = glm::vec3( 0, 0, 0 );
       
wind_time = 0;
   
}
   
   
if( current_time - wind_start_time > wind_time ) {
       
       
float range = 0.005f;
       
wind.x = generateRandFloat( - range, range );
       
wind.y = generateRandFloat( 0, range ); // slower
       
wind.z = generateRandFloat( - range, range );
       
       
wind_time = generateRandFloat( 2, 5 );
       
wind_start_time = current_time;
   
}
   
   
// face to camera
   
transform.rotation.y = 90.0f - cam->_yaw;
   
transform.position.x -= wind.x;
   
transform.position.y -= wind.y;
   
transform.position.z -= wind.z;
}
P-182133
1 « 2 »
Poprzednia strona Strona 2 z 2