宽度不均匀时纹理缩放错误

问题描述 投票:1回答:1

我正在尝试使多个纹理在GLFW窗口中逐像素出现。我的工作方式是共享着色器,该着色器采用统一的矩阵来缩放和变换纹理。但是,我的缩放比例似乎并不理想,因为纹理似乎已损坏(?)。

uneven

这是将过滤器设置为GL_NEAREST时的情况。设置为GL_LINEAR时,它会变得模糊,我也不想要。这使我怀疑缩放比例不正确,加之glGetError()返回GL_NO_ERROR的事实。不过,这没有任何意义,因为我将其缩放为相对于屏幕像素和位图像素来说是“完美像素” ...(请参见下面的代码)

通过广泛的研究和测试,我发现了所有可能的原因:当位图的宽度不均匀时,就会发生损坏。当我添加代码以填充不均匀的位图时...

even

腐败消失,纹理完美呈现! (经过以上测试)

为什么会这样,我该如何解决?

纹理创建代码(摘录):

...
float vertices[] = {
    // positions   // texture coords
    1.0,   1.0,  1.0f, 1.0f, // top right
    1.0,  -1.0,  1.0f, 0.0f, // bottom right
    -1.0, -1.0,  0.0f, 0.0f, // bottom left
    -1.0,  1.0,  0.0f, 1.0f  // top left 
};

unsigned int indices[] = {
    0, 1, 3,
    1, 2, 3
};

// `VA`, `VB`, `EB`, and `TX` are class variables
glGenVertexArrays(1, &VA);
glGenBuffers(1, &VB);
glGenBuffers(1, &EB);
glGenTextures(1, &TX);

glBindTexture(GL_TEXTURE_2D, TX);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

// Sharp, easier to tell when texture is rendering incorrectly
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Blurry
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glBindVertexArray(VA);

glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EB);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

constexpr int stride = 4 * sizeof(float);

// position attribute
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(float)));
glEnableVertexAttribArray(1);

// `shader` is a shader program for the below shaders
glUseProgram(shader);
glUniform1i(glGetUniformLocation(shader, "Tex"), 0);
...

纹理加载代码,每个纹理调用一次(摘录):

...
unsigned char *bitmap = loadImage(&width, &height,...);
glBindTexture(GL_TEXTURE_2D, TX);
// Before you ask: yes, the image is in RBGA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
...

纹理渲染代码,称为每一帧(再次摘录:: >>]]

...
glm::mat4 model(1.0f);

// Probally not relevent
const float xPos = (x + width / 2) / windowWidth * 2 - 1;
const float yPos = ((y + height / 2) / windowHeight * 2 - 1) * -1;
model = glm::translate(model, glm::vec3(xPos, yPos, 0.0f));

model = glm::scale(model, glm::vec3((float)width / windowWidth, (float)height / windowHeight, 0.0f));

// `modelLocation` was previously set to glGetUniformLocation(shader, "model")
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, glm::value_ptr(model));

glBindVertexArray(VA);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EB);
glBindTexture(GL_TEXTURE_2D, TX);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
...

顶点着色器:

#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 model;

void main() {
    gl_Position = model * vec4(aPos, 0.0, 1.0);
    TexCoord = aTexCoord;
}

片段着色器:

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D Tex;

void main() {
    FragColor = texture(Tex, TexCoord);
}

我正在尝试使多个纹理在GLFW窗口中逐像素出现。我的工作方式是共享着色器,该着色器采用统一的矩阵来缩放和变换纹理。但是,...

c++ opengl textures scaling
1个回答
1
投票

[需要像素精确的纹理映射时,不足以缩放m xntexels大纹理,以便将其映射到屏幕上的m x n像素大矩形。您还必须确保在子像素级别上映射正确无误-即将纹理像素中心映射到相应的像素中心。在您的情况下,您可以使用整个[0,1]范围作为tex坐标(这很好),因此必须映射几何图形,以使顶点最终位于像素corners

上(这样就可以直接映射相应的texel角) 1:1)。
© www.soinside.com 2019 - 2024. All rights reserved.