我遇到了OpenGL加载图像的问题,我已经尝试了几个图像,但颜色显示不正确,纹理显示偏移。
我是以下代码从Learnopengl.com加载图像的帮助下,SDL2,甚至去尽可能复制和粘贴代码后,几天的挫折,我想知道这是否有任何与OpenGL状态机或它纯粹是我缺乏经验。
我试图隔离我的图像加载代码到一个纹理管理器类。我想知道这是否是我的错。
Display Output
#include <iostream>
#include <Window/Window.hpp>
#include <Shaders/Shader.hpp>
#include <Managers/TextureManager.hpp>
int main(int argc, char* argv[]) {
Kaim::Window window("Game", 1080, 720);
Kaim::Shader shader("Assets/shaders/basic/vertex.glsl", "Assets/shaders/basic/fragment.glsl");
Kaim::Manager::TextureManager textureManager;
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
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);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
textureManager.LoadTexture("box", "Assets/images/Box.png");
while (window.IsOpen()) {
GLenum error = glGetError();
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
window.Close();
}
}
window.Update(0.2f, 0.3f, 0.3f, 1.0f);
shader.use();
textureManager.Bind("box");
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
window.Render();
}
std::cout << "Hello, World!" << std::endl;
return 0;
}
TextureManager.cpp
#include "TextureManager.hpp"
namespace Kaim { namespace Manager {
TextureManager::TextureManager() {
INFO("Texture Manager Created");
}
TextureManager::~TextureManager() {
INFO("Texture Manager Destroyed");
}
void TextureManager::LoadTexture(std::string name, std::string path) {
for(auto const& [key, val] : textures) {
if (val.path == path) {
WARNING("Texture with path %s already exists", path.c_str());
return;
}
if(key == name) {
WARNING("Texture with name %s already exists", name.c_str());
return;
}
}
SDL_Surface* surface = IMG_Load(path.c_str());
if (surface == NULL) {
ERROR("Failed to load image: %s", IMG_GetError());
return;
}
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// get number of channels in the SDL surface
GLint nOfColors = surface->format->BytesPerPixel;
unsigned int format;
if (nOfColors == 4) // contains an alpha channel
{
if (surface->format->Rmask == 0x000000ff)
format = GL_RGBA;
else
format = GL_BGRA;
} else if (nOfColors == 3) // no alpha channel
{
if (surface->format->Rmask == 0x000000ff)
format = GL_RGB;
else
format = GL_BGR;
} else {
ERROR("Image is not truecolor");
return;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
glGenerateMipmap(GL_TEXTURE_2D);
SDL_FreeSurface(surface);
Texture textureStruct;
textureStruct.id = texture;
textureStruct.path = path;
textures[name] = textureStruct;
}
void TextureManager::Bind(std::string path) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[path].id);
}
void TextureManager::Unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
}}
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
尝试从纹理管理器类显示OpenGL中的图像
编辑:我想我应该添加窗口类,因为这是我初始化一切的地方。
#include "Window.hpp"
namespace Kaim {
Window::Window(std::string title, int width, int height) {
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
this->width = width;
this->height = height;
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
if (window == NULL) {
ERROR("Failed to create window: %s", SDL_GetError());
open = false;
return;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
context = SDL_GL_CreateContext(window);
if (glewInit() != GLEW_OK) {
ERROR("OpenGL Could not Initalize");
open = false;
}
glewExperimental = GL_TRUE;
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, width, height);
open = true;
}
void Window::Update(float r, float g, float b, float a) {
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Window::Render() {
SDL_GL_SwapWindow(window);
}
SDL_Window* Window::GetWindow() {
return this->window;
}
bool Window::IsOpen() {
return this->open;
}
void Window::Close() {
this->open = false;
}
Window::~Window() {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(this->window);
IMG_Quit();
SDL_Quit();
}
}
1条答案
按热度按时间hujrc8aj1#
假设默认情况下图像的行对齐为4字节。如果加载RGB图像,则必须更改此设置,因为3个颜色通道只需要3个字节,并且图像的3 * 宽度可能无法被4整除。在指定图像之前(在
glTexImage2D
之前),使用glPixelStore
设置GL_UNPACK_ALIGNMENT
参数: