OpenGL 纹理渲染与原始不匹配
OpenGL texture rendering does not match original
我正在尝试使用 OpenGL 渲染纹理。我用来测试的贴图是白底一堆黑色矩形,如下:
然而,在渲染时,纹理似乎被复制并多次叠加在自身之上:
我使用以下方式设置场景:
std::string vertexSource = ShaderLoader::load("vertexSource.vert");
const char* vsource = vertexSource.c_str();
std::string fragmentSource = ShaderLoader::load("fragmentSource.frag");
const char* fsource = fragmentSource.c_str();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vsource, NULL);
glCompileShader(vertexShader);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fsource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
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,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.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);
glVertexAttribPointer(1,2,GL_FLOAT, GL_FALSE, 2* sizeof(float), (void*)(sizeof(float)*12));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned char* data = stbi_load("image.png", &width, &height,&nrOfChannels, 0);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free((void *) data);
我的渲染代码是:
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, textureId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
我的顶点着色器是:
#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
out vec2 TextureCoordinate;
void main()
{
gl_Position = vec4( inVertex, 1 );
TextureCoordinate = inTexture;
}
我的片段着色器是:
#version 330 core
out vec4 FragColor;
in vec2 TextureCoordinate;
uniform sampler2D Texture;
void main() {
FragColor = texture(Texture,TextureCoordinate);
}
当一个3通道(GL_RGB
)的图像被加载到纹理对象时,GL_UNPACK_ALIGNMENT
需要设置为1。默认GL_UNPACK_ALIGNMENT
是4,所以每一行假定图像的对齐为 4 个字节。缓冲区中的像素大小为 3 个字节并且紧密排列,这会导致未对齐。
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // default
由于图片格式为PNG,很有可能图片有4个通道(GL_RGBA
)。在指定纹理图像之前评估 nrOfChannels
:
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, 0);
// [...]
unsigned int format = nrOfChannels == 4 ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
也可以强制 stbi_load
生成具有 4 个通道的图像,方法是将 4 显式传递给最后一个参数:
int reqChannels= 4;
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, reqChannels);
// [...]
glTexImage2D(GL_TEXTURE_2D, GL_RGBA, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
我正在尝试使用 OpenGL 渲染纹理。我用来测试的贴图是白底一堆黑色矩形,如下:
然而,在渲染时,纹理似乎被复制并多次叠加在自身之上:
我使用以下方式设置场景:
std::string vertexSource = ShaderLoader::load("vertexSource.vert");
const char* vsource = vertexSource.c_str();
std::string fragmentSource = ShaderLoader::load("fragmentSource.frag");
const char* fsource = fragmentSource.c_str();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vsource, NULL);
glCompileShader(vertexShader);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fsource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
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,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.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);
glVertexAttribPointer(1,2,GL_FLOAT, GL_FALSE, 2* sizeof(float), (void*)(sizeof(float)*12));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned char* data = stbi_load("image.png", &width, &height,&nrOfChannels, 0);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free((void *) data);
我的渲染代码是:
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, textureId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
我的顶点着色器是:
#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
out vec2 TextureCoordinate;
void main()
{
gl_Position = vec4( inVertex, 1 );
TextureCoordinate = inTexture;
}
我的片段着色器是:
#version 330 core
out vec4 FragColor;
in vec2 TextureCoordinate;
uniform sampler2D Texture;
void main() {
FragColor = texture(Texture,TextureCoordinate);
}
当一个3通道(GL_RGB
)的图像被加载到纹理对象时,GL_UNPACK_ALIGNMENT
需要设置为1。默认GL_UNPACK_ALIGNMENT
是4,所以每一行假定图像的对齐为 4 个字节。缓冲区中的像素大小为 3 个字节并且紧密排列,这会导致未对齐。
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // default
由于图片格式为PNG,很有可能图片有4个通道(GL_RGBA
)。在指定纹理图像之前评估 nrOfChannels
:
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, 0);
// [...]
unsigned int format = nrOfChannels == 4 ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
也可以强制 stbi_load
生成具有 4 个通道的图像,方法是将 4 显式传递给最后一个参数:
int reqChannels= 4;
unsigned char* data = stbi_load("image.png", &width, &height, &nrOfChannels, reqChannels);
// [...]
glTexImage2D(GL_TEXTURE_2D, GL_RGBA, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);