Hello I am new to OpenGL and I am trying to learn it .
I am trying to create a way to load all the images which I plan to use in OpenGL and then render them all on the screen. It seems OpenGL seems to be very code repetitive in it's process of creating VAO,VBA, and EBOs.
I am a newbie at this , so please explain why this is only rendering one image? I thought the image object would be stored in the VAO.
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#include "ogl_shaders.h"
const int MAX_TEXTURES = 255;
GLuint vaos[MAX_TEXTURES] = {0};
GLuint s_textures[MAX_TEXTURES] = {0};
int x_pos[] = {0, 300, 600};
int y_pox[] = {0, 100, 50};
int w_size[] = {200,200, 200};
int h_wize[] = {200, 200, 200};
std::vector<std::string> g_image_paths = { "image.png", "image2.png", "image3.png" };
struct Vec2 {
float x;
float y;
};
Vec2 toNDC(int pixel_x, int pixel_y, int window_width, int window_height) {
Vec2 vec;
vec.x = (static_cast<float>(pixel_x) / window_width) * 2.0f - 1.0f;
vec.y = (static_cast<float>(pixel_y) / window_height) * 2.0f - 1.0f;
return vec;
}
// I assume the problem is here <<<
GLuint setupImageRectangle(int posX, int posY, int sizeX, int sizeY, GLuint shaderProgram, GLuint texture) {
// Convert position to NDC
Vec2 vec = toNDC(posX, posY, 800, 600);
float ndcPosX = vec.x;
float ndcPosY = vec.y;
// Convert size to NDC
float ndcSizeX = static_cast<float>(sizeX) / (800 / 2.0f);
float ndcSizeY = static_cast<float>(sizeY) / (600 / 2.0f);
// Vertex data for the rectangle
float vertices[] = {
ndcPosX, ndcPosY, 0.0f, 0.0f, // Bottom-left
ndcPosX + ndcSizeX, ndcPosY, 1.0f, 0.0f, // Bottom-right
ndcPosX + ndcSizeX, ndcPosY + ndcSizeY, 1.0f, 1.0f, // Top-right
ndcPosX, ndcPosY + ndcSizeY, 0.0f, 1.0f // Top-left
};
GLuint elements[] = {0, 1, 2, 2, 3, 0};
// Create and bind the VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Load the vertex data into a VBO
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Load the element data into an EBO
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
// Bind the texture to the rectangle
//glBindTexture(GL_TEXTURE_2D, texture);
return vao;
}
void CreateTexture(std::vector<std::string> image_path) {
for (int image = 0; image < image_path.size(); image++) {
// Generate a texture ID
glGenTextures(1, &s_textures[image]);
// Bind the texture ID
glBindTexture(GL_TEXTURE_2D, s_textures[image]);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load the image data
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true); // Flip image
unsigned char* data = stbi_load(image_path[image].c_str(), &width, &height, &nrChannels, STBI_rgb_alpha);
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Failed to load texture: " << image_path[image] << std::endl;
}
// Free the image data
stbi_image_free(data);
}
}
void helper_gl_bindTextures(GLuint vaos[], int size) {
for (int i = 0; i < size && vaos[i] != 0; i++){
glActiveTexture(GL_TEXTURE0 + i); // activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, s_textures[i]);
glBindVertexArray(vaos[i]);
std::cout << "image of vaos loaded " << i << std::endl;
}
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
int main()
{
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewInit();
// Compile and activate shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, nullptr);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, nullptr);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
CreateTexture(g_image_paths);
for (int idx = 0 ; idx < g_image_paths.size(); idx++){
vaos[idx] = setupImageRectangle(x_pos[idx], y_pox[idx], w_size[idx], h_wize[idx], shaderProgram, s_textures[idx]);
}
while(!glfwWindowShouldClose(window))
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw the texture on the screen
helper_gl_bindTextures(vaos, sizeof(vaos) / sizeof(vaos[0]));
// Swap buffers and poll window events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Cleanup and exit
for (int idx = 0 ; idx < sizeof(s_textures); idx++){
glDeleteTextures(1, &s_textures[idx]);
}
glfwTerminate();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire