tBane Temat założony przez niniejszego użytkownika |
[GLFW GLAD] System Modeli » 2024-12-29 20:05:36 Witam. Zacząłem uczyć się OpenGL GLFW GLAD. Jestem na trzeciej lekcji https://learnopengl.com/Getting-started/Hello-Triangle. Nauczyłem się jak generować trójkąt, ale od razu wpadłem na pomysł, by ten trójkąt opakować w klasę. Nie do końca rozumiem jak działa VBO, EBO oraz VAO. Czy dobrze opakowałem trójkąt w klasę ? #include <glad/glad.h> #include <GLFW/glfw3.h>
#include <iostream>
const char * vertex_shader_source = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
const char * fragment_shader_source = R"(
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
)";
GLFWwindow * window; unsigned int vertex_shader; unsigned int fragment_shader; unsigned int shader_program;
class Model { public: unsigned int VAO; unsigned int VBO; unsigned int EBO; unsigned int program; Model() { } ~Model() { glDeleteVertexArrays( 1, & VAO ); glDeleteBuffers( 1, & VBO ); glDeleteBuffers( 1, & EBO ); } void Load() { float vertices[ ] = { 0.5f, 0.5f, 0.0f, 0.5f, - 0.5f, 0.0f, - 0.5f, - 0.5f, 0.0f, - 0.5f, 0.5f, 0.0f }; unsigned int indices[ ] = { 0, 1, 3, 1, 2, 3 }; glGenVertexArrays( 1, & VAO ); glGenBuffers( 1, & VBO ); glGenBuffers( 1, & EBO ); glBindVertexArray( VAO ); glBindBuffer( GL_ARRAY_BUFFER, VBO ); glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, EBO ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 ); glEnableVertexAttribArray( 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindVertexArray( 0 ); program = shader_program; } void draw() { glUseProgram( shader_program ); glBindVertexArray( VAO ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 ); } };
void window_set_size( int width, int height ) { glViewport( 0, 0, width, height ); }
void events() { if( glfwGetKey( window, GLFW_KEY_ESCAPE ) == GLFW_PRESS ) glfwSetWindowShouldClose( window, true ); }
void loadShaders() { vertex_shader = glCreateShader( GL_VERTEX_SHADER ); glShaderSource( vertex_shader, 1, & vertex_shader_source, NULL ); glCompileShader( vertex_shader ); fragment_shader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragment_shader, 1, & fragment_shader_source, NULL ); glCompileShader( fragment_shader ); }
void deleteShaders() { glDeleteShader( vertex_shader ); glDeleteShader( fragment_shader ); }
void loadPrograms() { shader_program = glCreateProgram(); glAttachShader( shader_program, vertex_shader ); glAttachShader( shader_program, fragment_shader ); glLinkProgram( shader_program ); }
void deletePrograms() { glDeleteProgram( shader_program ); }
int main() { glfwInit(); glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); window = glfwCreateWindow( 800, 600, "LearnOpenGL", NULL, NULL ); if( window == NULL ) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return - 1; } glfwMakeContextCurrent( window ); if( !gladLoadGLLoader(( GLADloadproc ) glfwGetProcAddress ) ) { std::cout << "Failed to initialize GLAD" << std::endl; return - 1; } loadShaders(); loadPrograms(); deleteShaders(); Model * model = new Model(); model->Load(); while( !glfwWindowShouldClose( window ) ) { events(); glClearColor( 0.2f, 0.3f, 0.3f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); model->draw(); glfwSwapBuffers( window ); glfwPollEvents(); } delete model; deletePrograms(); glfwTerminate(); return 0; }
|
|
DejaVu |
» 2024-12-30 09:26:08 ChatGPT 4o: Przejrzałem kod użytkownika z forum cpp0x.pl, który opakował rysowanie trójkąta w klasę `Model` z użyciem OpenGL, GLFW i GLAD. Ogólnie podejście jest poprawne, ale zauważyłem kilka kwestii, które warto poprawić:
1. **Konstruktor klasy `Model`:** Obecnie konstruktor jest pusty. Warto przenieść do niego inicjalizację VAO, VBO i EBO oraz kompilację shaderów, aby obiekt był gotowy do użycia zaraz po utworzeniu.
```cpp Model() { // Inicjalizacja VAO, VBO, EBO glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO);
// Kompilacja shaderów loadShaders(); loadPrograms(); } ```
2. **Metoda `Load`:** Nazwa sugeruje ładowanie danych, ale w rzeczywistości inicjalizuje bufory i ustawia atrybuty wierzchołków. Można rozważyć zmianę nazwy na bardziej opisową, np. `initializeBuffers()`.
```cpp void initializeBuffers() { // Kod inicjalizujący bufory } ```
3. **Zarządzanie shaderami:** Kompilacja shaderów odbywa się poza klasą `Model`. Warto przenieść tę funkcjonalność do klasy, aby była bardziej samodzielna.
```cpp class Model { private: unsigned int vertex_shader; unsigned int fragment_shader; unsigned int shader_program;
void loadShaders() { // Kod kompilujący shadery }
void loadPrograms() { // Kod linkujący program shaderów }
public: // Reszta kodu }; ```
4. **Czyszczenie zasobów:** W destruktorze usuwane są VAO, VBO i EBO. Należy również usunąć program shaderów, aby uniknąć wycieków pamięci.
```cpp ~Model() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteProgram(shader_program); } ```
5. **Użycie `glBindBuffer`:** Po ustawieniu wskaźnika atrybutu wierzchołka (`glVertexAttribPointer`) wywoływane jest `glBindBuffer(GL_ARRAY_BUFFER, 0)`. W kontekście użycia EBO w VAO, nie jest to konieczne i może prowadzić do nieoczekiwanych zachowań.
```cpp // Po glVertexAttribPointer // glBindBuffer(GL_ARRAY_BUFFER, 0); // Niepotrzebne ```
6. **Obsługa błędów:** Brakuje sprawdzania błędów podczas kompilacji shaderów i linkowania programu. Dodanie odpowiednich mechanizmów diagnostycznych ułatwi debugowanie.
```cpp void checkCompileErrors(unsigned int shader, std::string type) { // Kod sprawdzający błędy kompilacji i linkowania } ```
7. **Korzystanie z nowoczesnych funkcji C++:** Rozważ użycie kontenerów standardowych, takich jak `std::vector`, do przechowywania danych wierzchołków i indeksów, co zwiększy czytelność i bezpieczeństwo kodu.
```cpp std::vector<float> vertices = { // Wierzchołki };
std::vector<unsigned int> indices = { // Indeksy }; ```
Podsumowując, kod jest na dobrej drodze, ale wprowadzenie powyższych poprawek zwiększy jego czytelność, bezpieczeństwo i zgodność z dobrymi praktykami programistycznymi.
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-12-30 13:18:56 Ok. Poprawiłem kod i teraz wygląda tak: #include <glad/glad.h> #include <GLFW/glfw3.h>
#include <iostream>
const char * vertex_shader_source = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
const char * fragment_shader_source = R"(
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
)";
GLFWwindow * window; unsigned int vertex_shader; unsigned int fragment_shader; unsigned int shader_program;
class Model { public: unsigned int VAO; unsigned int VBO; unsigned int EBO; unsigned int program; Model() { glGenVertexArrays( 1, & VAO ); glGenBuffers( 1, & VBO ); glGenBuffers( 1, & EBO ); glBindVertexArray( VAO ); } ~Model() { glDeleteVertexArrays( 1, & VAO ); glDeleteBuffers( 1, & VBO ); glDeleteBuffers( 1, & EBO ); } void Load() { float vertices[ ] = { 0.5f, 0.5f, 0.0f, 0.5f, - 0.5f, 0.0f, - 0.5f, - 0.5f, 0.0f, - 0.5f, 0.5f, 0.0f }; unsigned int indices[ ] = { 0, 1, 3, 1, 2, 3 }; glBindBuffer( GL_ARRAY_BUFFER, VBO ); glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, EBO ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ),( void * ) 0 ); glEnableVertexAttribArray( 0 ); glBindVertexArray( 0 ); program = shader_program; } void draw() { glUseProgram( program ); glBindVertexArray( VAO ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 ); } };
void window_set_size( int width, int height ) { glViewport( 0, 0, width, height ); }
void events() { if( glfwGetKey( window, GLFW_KEY_ESCAPE ) == GLFW_PRESS ) glfwSetWindowShouldClose( window, true ); }
void loadShaders() { vertex_shader = glCreateShader( GL_VERTEX_SHADER ); glShaderSource( vertex_shader, 1, & vertex_shader_source, NULL ); glCompileShader( vertex_shader ); fragment_shader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragment_shader, 1, & fragment_shader_source, NULL ); glCompileShader( fragment_shader ); }
void deleteShaders() { glDeleteShader( vertex_shader ); glDeleteShader( fragment_shader ); }
void loadPrograms() { shader_program = glCreateProgram(); glAttachShader( shader_program, vertex_shader ); glAttachShader( shader_program, fragment_shader ); glLinkProgram( shader_program ); }
void deletePrograms() { glDeleteProgram( shader_program ); }
int main() { glfwInit(); glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); window = glfwCreateWindow( 800, 600, "LearnOpenGL", NULL, NULL ); if( window == NULL ) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return - 1; } glfwMakeContextCurrent( window ); if( !gladLoadGLLoader(( GLADloadproc ) glfwGetProcAddress ) ) { std::cout << "Failed to initialize GLAD" << std::endl; return - 1; } loadShaders(); loadPrograms(); Model * model = new Model(); model->Load(); while( !glfwWindowShouldClose( window ) ) { events(); glClearColor( 0.2f, 0.3f, 0.3f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); model->draw(); glfwSwapBuffers( window ); glfwPollEvents(); } delete model; deletePrograms(); deleteShaders(); glfwTerminate(); return 0; }
|
|
« 1 » |