OpenGL texture rendering does not match original

允我心安 提交于 2021-02-05 09:16:26

问题


I am trying to render a texture with OpenGL. The texture I am using as a test is a bunch of black rectangles on a white background, as follows:

However, when rendering, the texture seem to be duplicated and overlayed multiple times on top of itself:

I set the scene up using:

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);

My render code is:

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);

My vertex shader is:

#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;
}

and my fragment shader is:

#version 330 core
out vec4 FragColor;

in vec2 TextureCoordinate;

uniform sampler2D Texture;

void main() {
    FragColor = texture(Texture,TextureCoordinate);
}

回答1:


When an image with 3 channels (GL_RGB) is loaded to a texture object, GL_UNPACK_ALIGNMENT needs to be set to 1. By default GL_UNPACK_ALIGNMENT is 4, so each line of an image is assumed to be aligned to 4 bytes. The pixels in the buffer have a size of 3 bytes and are tightly packed, this would cause a misalignment.

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

Since the image format is PNG, it is very likely that the image has 4 channels (GL_RGBA). Evaluate nrOfChannels before specifying the texture image:

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);

It is also possible to force stbi_load to generate an image with 4 channels, by explicitly pass 4 to the last parameter:

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);


来源:https://stackoverflow.com/questions/65759054/opengl-texture-rendering-does-not-match-original

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!