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 wczoraj o godz. 8:05
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[OpenGL GLFW GLAD] Snowstorm - Czyli system cząstek i płatki śniegu
» 2025-01-27 18:24:29
Cześć. Uczę się OpenGL GLFW GLAD. Zastanawiam się jak pracować z systemem cząstek takim np. jak SnowStorm lub deszcz. Czy prawidłowym podejściem będzie stworzenie menadżera cząstek i dla każdej cząstki generować VAO dla quad oraz renderować na nim teksturę i w ten sposób to wszystko generować?
P-182064
DejaVu
» 2025-01-27 20:51:20
Prawidłowym podejściem jest zrobienie 'czegokolwiek' co działa w pierwszej iteracji, aby nauczyć się/zrozumieć jak takie rzeczy się implementuje. W kolejnej iteracji możesz zacząć się zastanawiać 'co zrobić lepiej'. Jeżeli chcesz 'od razu' zrobić 'dobrze', to poszukaj artykułów na ten temat lub zapytaj ChatGPT i pomęcz go trochę pytaniami, w tym również kwestionuj proponowane rozwiązania.
P-182065
tBane
Temat założony przez niniejszego użytkownika
» 2025-01-28 16:27:54
Dobra. Mam pomysł jak dobrze wygenerować SnowStorm. Dziś spróbuję napisać i jak się uda to wrzucę kod.
P-182067
tBane
Temat założony przez niniejszego użytkownika
» 2025-01-28 20:36:51
Częściowo napisane. Jeszcze trzeba napisać renderowanie tekstury dla każdego płatka śniegu zamiast rysowania punktu oraz dać różne prędkości opadania.
Jutro wrzucę poprawiony kod a dziś no tylko tyle.

https://youtu.be/D9VtoZeobHg

C/C++
#ifndef SnowStorm_hpp
#define SnowStorm_hpp

class FallingSnowflake {
public:
   
float speed = 0.1f;
};

class SnowStorm {
public:
   
// rect for generate new fallSnowflakes
   
glm::vec3 rect_position;
   
glm::vec3 rect_size;
   
short falling_snowflakes_count;
   
   
// generator
   
std::random_device rd;
   
std::mt19937 generator;
   
   
// FallingSnowflakes
   
std::vector < FallingSnowflake * > falling_snowflakes;
   
std::vector < float > falling_snowflakes_positions; // positions of
   
    // VAO/VBO
   
unsigned int _VAO; // VERTEX ARRAY OBJECTS (VAO stores information about how data in VBO and EBO is used)
   
unsigned int _VBO; // VERTEX BUFFER OBJECTS (VERTEXES)
   
    // texture
   
int _width, _height, _nrChannels;
   
unsigned int _texture_snowflake;
   
   
// shader program
   
Program * _program;
   
   
SnowStorm() {
       
       
rect_position = glm::vec3( 0, 20, 0 );
       
rect_size = glm::vec3( 2, 5, 2 );
       
       
falling_snowflakes_count = 1000;
       
       
// for generate random float
       
generator = std::mt19937( rd() );
       
       
// create a FallingSnowflakes
       
for( short i = 0; i < falling_snowflakes_count; i++ ) {
           
           
falling_snowflakes.push_back( new FallingSnowflake() );
           
           
glm::vec3 pos = generateFallingSnowFlakePosition();
           
           
falling_snowflakes_positions.push_back( pos.x );
           
falling_snowflakes_positions.push_back( pos.y );
           
falling_snowflakes_positions.push_back( pos.z );
       
}
       
       
// create VAO/VBO/EBO
       
glGenVertexArrays( 1, & _VAO ); // VAO
       
glBindVertexArray( _VAO ); // VAO
       
glGenBuffers( 1, & _VBO ); // ... vertices
       
        // VBO - VERTEXES
       
glBindBuffer( GL_ARRAY_BUFFER, _VBO );
       
glBufferData( GL_ARRAY_BUFFER, falling_snowflakes_positions.size() * sizeof( float ), falling_snowflakes_positions.data(), GL_STATIC_DRAW );
       
       
// position attribute (layout 0 in shader)
       
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 );
       
glEnableVertexAttribArray( 0 );
       
       
glBindVertexArray( 0 ); // VAO
       
       
loadTextureOfSnowflake( "snowflake.png" );
       
       
_program = new Program( snow_vertex_shader_source, snow_fragment_shader_source );
       
   
}
   
~SnowStorm() {
       
glDeleteVertexArrays( 1, & _VAO );
       
glDeleteBuffers( 1, & _VBO );
       
glDeleteTextures( 1, & _texture_snowflake );
       
       
for( auto & snow: falling_snowflakes ) {
           
delete snow;
       
}
       
       
delete _program;
   
}
   
   
void loadTextureOfSnowflake( std::string texture_pathfile ) {
       
       
glGenTextures( 1, & _texture_snowflake );
       
glBindTexture( GL_TEXTURE_2D, _texture_snowflake );
       
       
// load the texture
       
stbi_set_flip_vertically_on_load( true ); // tell stb_image.h to flip loaded texture's on the y-axis.
       
unsigned char * data = stbi_load( texture_pathfile.c_str(), & _width, & _height, & _nrChannels, 0 );
       
       
if( data ) {
           
GLenum format = _nrChannels == 4 ? GL_RGBA: GL_RGB;
           
glTexImage2D( GL_TEXTURE_2D, 0, format, _width, _height, 0, format, GL_UNSIGNED_BYTE, data );
           
glGenerateMipmap( GL_TEXTURE_2D ); // mip-map create a textures ..., 64x64, 32x32, 16x16, 8x8, 4x4, 2x2, 1x1
       
}
       
else
           
 std::cout << "Failed to load texture\n";
       
       
stbi_image_free( data );
       
   
}
   
   
glm::vec3 generateFallingSnowFlakePosition() {
       
       
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;
   
}
   
   
void update() {
       
for( short i = 0; i < falling_snowflakes_count; i++ ) {
           
falling_snowflakes_positions[ i * 3 + 1 ] -= falling_snowflakes[ i ]->speed;
           
           
if( falling_snowflakes_positions[ i * 3 + 1 ] < 0 ) {
               
               
glm::vec3 pos = generateFallingSnowFlakePosition();
               
falling_snowflakes_positions[ i * 3 ] = pos.x;
               
falling_snowflakes_positions[ i * 3 + 1 ] = pos.y;
               
falling_snowflakes_positions[ i * 3 + 2 ] = pos.z;
               
           
}
        }
       
       
glBindBuffer( GL_ARRAY_BUFFER, _VBO );
       
glBufferSubData( GL_ARRAY_BUFFER, 0, falling_snowflakes_positions.size() * sizeof( float ), falling_snowflakes_positions.data() );
       
glBindBuffer( GL_ARRAY_BUFFER, 0 );
   
}
   
   
void draw( Camera * cam ) {
       
glUseProgram( _program->shader_program );
       
       
// Aktywacja tekstury
       
glActiveTexture( GL_TEXTURE0 );
       
glBindTexture( GL_TEXTURE_2D, _texture_snowflake );
       
glUniform1i( glGetUniformLocation( _program->shader_program, "texture1" ), 0 );
       
glUniform3f( glGetUniformLocation( _program->shader_program, "fogColor" ), 0.25f, 0.25f, 0.25f );
       
glUniform1f( glGetUniformLocation( _program->shader_program, "fogStart" ), 1.0f );
       
glUniform1f( glGetUniformLocation( _program->shader_program, "fogEnd" ), 15.0f );
       
       
// Przesyłanie macierzy
       
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, rect_position );
       
       
glUniformMatrix4fv( glGetUniformLocation( _program->shader_program, "projection" ), 1, GL_FALSE, & projection[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( _program->shader_program, "view" ), 1, GL_FALSE, & view[ 0 ][ 0 ] );
       
glUniformMatrix4fv( glGetUniformLocation( _program->shader_program, "model" ), 1, GL_FALSE, & model[ 0 ][ 0 ] );
       
       
// Rysowanie punktów
       
glPointSize( 5.0f ); // Opcjonalne
       
glBindVertexArray( _VAO );
       
glDrawArrays( GL_POINTS, 0, falling_snowflakes_count ); // Rysowanie punktów
       
glBindVertexArray( 0 );
   
}
}
;

#endif
P-182068
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-08 08:20:07
Witam ponownie. Próbuję wygenerować płatki śniegu z tekstury. Stworzyłem vector z danymi wierzchołków i współrzędnych tekstur, zrobiłem glGenBuffer dla nich (vertices) i teraz muszę to jakoś przesłać do layoutów w shaderach. Nie wiem jak to zrobić. Pomoże ktoś ?


C/C++
SnowStorm( Program * program ) {
   
   
rect_position = glm::vec3( 0, 20, 0 );
   
rect_size = glm::vec3( 15, 5, 15 );
   
   
falling_snowflakes_count = 1000;
   
   
// for generate random float
   
generator = std::mt19937( rd() );
   
   
// create a FallingSnowflakes
   
for( short i = 0; i < falling_snowflakes_count; i++ ) {
       
       
falling_snowflakes.push_back( new FallingSnowflake() );
       
       
glm::vec3 pos = generateFallingSnowFlakePosition();
       
       
falling_snowflakes_positions.push_back( pos.x );
       
falling_snowflakes_positions.push_back( pos.y );
       
falling_snowflakes_positions.push_back( pos.z );
   
}
   
   
// create a vertices & texCoords
   
std::vector < float > snowflake_vertices = {
       
- 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,
       
0.1f, 0.1f, 0.0f, 1.0f, 1.0f
   
};
   
   
// create VAO/
   
glGenVertexArrays( 1, & _VAO ); // VAO
   
glBindVertexArray( _VAO ); // VAO
   
glGenBuffers( 1, & _positions ); // ... positions
   
glGenBuffers( 1, & _vertices ); // ... vertices & texCoords
   
    // POSITIONS OF SNOWFLAKES
   
glBindBuffer( GL_ARRAY_BUFFER, _positions );
   
glBufferData( GL_ARRAY_BUFFER, falling_snowflakes_positions.size() * sizeof( float ), falling_snowflakes_positions.data(), GL_STATIC_DRAW );
   
   
// position attribute (layout 0 in shader)
   
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 );
   
glEnableVertexAttribArray( 0 );
   
   
////////////////////////////////////////////////
    // TU CHYBA ŹLE PRZYPISUJE WIERZCHOŁKI I WSPÓŁRZĘDNE TEKSTURY ...
   
glBindBuffer( GL_ARRAY_BUFFER, _vertices );
   
glBufferData( GL_ARRAY_BUFFER, snowflake_vertices.size() * sizeof( float ), snowflake_vertices.data(), GL_STATIC_DRAW );
   
// vertices attribute (layout 1 in shader)
    // ???
   
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 );
   
glEnableVertexAttribArray( 0 );
   
   
// texCoords attribute (layout 2 in shader)
    // ???
   
glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * )( 3 * sizeof( float ) ) );
   
glEnableVertexAttribArray( 0 );
   
   
glBindVertexArray( 0 ); // VAO
   
   
loadTextureOfSnowflake( "textures/snowflake.png" );
   
   
_program = program;
   
}
P-182118
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-09 12:52:21
Chyba udało mi się trochę uporządkować kod. Ale nadal nie działa. Nie renderuje ani opadających płatków śniegu, ani tym bardziej opadających prostokątów.

Video z programu ... :
https://www.youtube.com/watch?v=KvaZpBbEdk4

Screenshoty:

C/C++
class FallingSnowflake {
public:
   
float speed = 0.1f;
};

class SnowStorm {
public:
   
// rect for generate new fallSnowflakes
   
glm::vec3 rect_position;
   
glm::vec3 rect_size;
   
short falling_snowflakes_count;
   
   
// generator
   
std::random_device rd;
   
std::mt19937 generator;
   
   
// FallingSnowflakes
   
std::vector < FallingSnowflake * > falling_snowflakes;
   
std::vector < float > falling_snowflakes_positions; // positions of
   
    // VAO/VBO
   
unsigned int _VAO; // VERTEX ARRAY OBJECTS
   
unsigned int _positions; // positions
   
unsigned int _vertices; // vertices & texCoords
   
    // texture
   
int _width, _height, _nrChannels;
   
unsigned int _texture_snowflake;
   
   
// shader program
   
Program * _program;
   
   
SnowStorm( Program * program ) {
       
       
rect_position = glm::vec3( 0, 20, 0 );
       
rect_size = glm::vec3( 15, 5, 15 );
       
       
falling_snowflakes_count = 1000;
       
       
// for generate random float
       
generator = std::mt19937( rd() );
       
       
// FallingSnowflakes positions
       
for( short i = 0; i < falling_snowflakes_count; i++ ) {
           
           
falling_snowflakes.push_back( new FallingSnowflake() );
           
           
glm::vec3 pos = generateFallingSnowFlakePosition();
           
           
falling_snowflakes_positions.push_back( pos.x );
           
falling_snowflakes_positions.push_back( pos.y );
           
falling_snowflakes_positions.push_back( pos.z );
       
}
       
       
// vertices & texCoords
       
std::vector < float > snowflake_vertices = {
           
- 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,
           
0.1f, 0.1f, 0.0f, 1.0f, 1.0f
       
};
       
       
// create VAO
       
glGenVertexArrays( 1, & _VAO ); // VAO
       
glBindVertexArray( _VAO ); // VAO
       
        // POSITIONS OF SNOWFLAKES
       
glGenBuffers( 1, & _positions );
       
glBindBuffer( GL_ARRAY_BUFFER, _positions );
       
glBufferData( GL_ARRAY_BUFFER, falling_snowflakes_positions.size() * sizeof( float ), falling_snowflakes_positions.data(), GL_STATIC_DRAW );
       
       
// position attribute (layout 0 in shader)
       
glEnableVertexAttribArray( 0 );
       
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 );
       
       
////////////////////////////////////////////////
        // tu chyba źle przypisuję wierzchołki i współrzędne tekstury płatka
       
glGenBuffers( 1, & _vertices );
       
glBindBuffer( GL_ARRAY_BUFFER, _vertices );
       
glBufferData( GL_ARRAY_BUFFER, snowflake_vertices.size() * sizeof( float ), snowflake_vertices.data(), GL_STATIC_DRAW );
       
       
// vertices attribute (layout 1 in shader)
       
glEnableVertexAttribArray( 1 );
       
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof( float ),( void * ) 0 );
       
       
// texCoords attribute (layout 2 in shader)
       
glEnableVertexAttribArray( 2 );
       
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof( float ),( void * )( 3 * sizeof( float ) ) );
       
       
// close VAO
       
glBindVertexArray( 0 );
       
       
loadTextureOfSnowflake( "textures/snowflake.png" );
       
       
_program = program;
       
   
}
   
   
~SnowStorm() {
       
glDeleteVertexArrays( 1, & _VAO );
       
glDeleteBuffers( 1, & _positions );
       
glDeleteBuffers( 1, & _vertices );
       
glDeleteTextures( 1, & _texture_snowflake );
       
       
for( auto & snow: falling_snowflakes ) {
           
delete snow;
       
}
    }
}
;
P-182119
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-10 07:32:16
jak ktoś potrafi wygenerować deszcz lub opadający popiół to też może być :P
P-182121
tBane
Temat założony przez niniejszego użytkownika
» 2025-02-10 08:32:51
Mam rozwiązanie ale słabe tzn. zamiast traktować cząsteczki jako zbiór pozycji mogę je przetwarzać jako osobne obiekty. Tylko to rozwiązanie znacznie spowolni działanie programu.
P-182122
« 1 » 2
  Strona 1 z 2 Następna strona