OpenGL 2D纹理无法正确显示c ++
Posted
技术标签:
【中文标题】OpenGL 2D纹理无法正确显示c ++【英文标题】:OpenGL 2D textures not displaying properly c++ 【发布时间】:2019-04-02 19:39:11 【问题描述】:我对 OpenGL 还很陌生,遇到了一个我似乎无法破解的问题。我正在尝试向三角形添加一个简单的 2D 纹理,该纹理似乎加载得很好,但它显示为颗粒状并以黑白显示。
质地
结果
这是我的相关代码:
main.cxx
#include <iostream>
#include "display.h"
#include "shader.h"
#include "texture.h"
#include "mesh.h"
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
int main()
Display display(800, 600, "project2");
Vertex vertices[] =
Vertex(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec2(0.0f, 0.0f)),
Vertex(glm::vec3(0.5f, -0.5f, 0.0f), glm::vec2(1.0f, 0.0f)),
Vertex(glm::vec3(0.0f, 0.5f, 0.0f), glm::vec2(0.5f, 1.0f)),
;
Mesh mesh(vertices, sizeof(vertices)/sizeof(vertices[0]));
Shader shader("./shaders/shader");
Texture texture("./textures/container.jpg");
while (!display.IsClosed())
display.ProcessInput();
display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
texture.Bind(0);
shader.Bind();
mesh.Draw();
display.Update();
return 0;
纹理.cxx
#include "texture.h"
Texture::Texture(const std::string &filePath)
int width, height, numComponents;
unsigned char* imageData = stbi_load(filePath.c_str(), &width, &height, &numComponents, 4);
if (!imageData)
std::cerr << "Failed to load texture: " << filePath << std::endl;
return;
stbi_set_flip_vertically_on_load(true);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(imageData);
Texture::~Texture()
glDeleteTextures(1, &texture);
void Texture::Bind(unsigned int unit)
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, texture);
片段着色器
#version 330 core
out vec4 FragColor;
uniform sampler2D diffuse;
in vec2 texCoord0;
void main()
FragColor = texture(diffuse, texCoord0);
顶点着色器
#version 330 core
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
out vec2 texCoord0;
void main()
gl_Position = vec4(position, 1.0);
texCoord0 = texCoord;
我之前在另一个项目中使用过纹理,我的代码看起来几乎相同,如果有人可以帮助我,将不胜感激。
【问题讨论】:
【参考方案1】:当一个具有 3 个颜色通道的 RGB 图像加载到纹理对象时,GL_UNPACK_ALIGNMENT
必须设置为 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, imageData);
GL_UNPACK_ALIGNMENT
指定内存中每个像素行开头的对齐要求。默认情况下,GL_UNPACK_ALIGNMENT
设置为 4。
这意味着图像的每一行的开头都假定与 4 的倍数的地址对齐。由于图像数据被紧密打包并且每个像素的大小为 3 字节,因此必须更改对齐方式。
要正确读取图像,stbi_load
的最后一个参数必须为 0(因为 jpg 格式提供 3 个颜色通道)或 3(强制 3 个颜色通道):
unsigned char* imageData = stbi_load(filePath.c_str(),
&width, &height, &numComponents, 0);
stbi_load
可以强制生成具有 4 个颜色通道的图像,方法是将 4 显式传递给最后一个参数:
见stb_image.h:
Basic usage (see HDR discussion below for HDR usage): int x,y,n; unsigned char *data = stbi_load(filename, &x, &y, &n, 0); // ... process data if not NULL ... // ... x = width, y = height, n = # 8-bit components per pixel ...
// ... replace '0' with '1'..'4' to force that many components per pixel
// ... but 'n' will always be the number that it would have been if you said 0 stbi_image_free(data)
在这种情况下,格式参数必须在加载图像时从GL_RGB
更改为GL_RGBA
:
unsigned char* imageData = stbi_load(filePath.c_str(),
&width, &height, &numComponents, 0);
// [...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, imageData);
【讨论】:
非常感谢Rabbid的帮助! stb_image 负载确实是导致问题的原因。将最后一个参数设置为 0 可以解决它:) @MostaphaRammo 可以,但你也可以将 4 与GL_RGBA
结合使用以上是关于OpenGL 2D纹理无法正确显示c ++的主要内容,如果未能解决你的问题,请参考以下文章