OpenGL精灵半像素位置偏移

时间:2014-10-15 07:03:53

标签: c++ opengl

最近我注意到即使我创建了宽度和高度都没有小数部分的像素的纹理,它们看起来有点模糊。经过几个小时的调试后我发现,问题在于抵消。 如果我提供没有小数部分的偏移量,我得到这个: enter image description here

但是如果我用小数部分添加偏移量,我得到: enter image description here

请以完整尺寸查看这些图片,否则您将无法发现问题:)

我有这种设置纹理的方法:

bool WindowsGraphicsManager::setTexture(
    UINT32& id, UINT8* image, UINT32 width, UINT32 height,
    bool wrapURepeat, bool wrapVRepeat, bool useMipmaps, int textureType)
{
    glGenTextures(1, &id);
    bindTexture(id);
    int type = GL_RGBA;
    if (textureType == Texture::MONO) {
        type = GL_ALPHA;
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    }
    glTexImage2D(
        GL_TEXTURE_2D, 0, type,
        width, height, 0, type,
        GL_UNSIGNED_BYTE, image);
    int minFilter = GL_LINEAR;
    if (useMipmaps) {
        glGenerateMipmap(GL_TEXTURE_2D);
        minFilter = GL_LINEAR_MIPMAP_LINEAR;
    }
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int wrap_u = wrapURepeat ?
        GL_REPEAT : GL_CLAMP_TO_EDGE;
    int wrap_v = wrapVRepeat ?
        GL_REPEAT : GL_CLAMP_TO_EDGE;
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_WRAP_S, wrap_u);
    glTexParameteri(GL_TEXTURE_2D,
        GL_TEXTURE_WRAP_T, wrap_v);
    return !checkGLError("Loading texture.");
}

我知道预计会有一点点模糊,但这看起来太多了,太过于显而易见了。 我能做些什么来解决这个问题,或者至少我应该在哪里寻找问题?着色器?矩阵?模型?质地?渲染设置?

2 个答案:

答案 0 :(得分:2)

它与你的实际纹理无关。只需确保在渲染前围绕坐标。你在这里看到的(以及奇怪的外观拉伸)是四舍五入的错误。

答案 1 :(得分:1)

如果您只是想以像素精确的方式将纹理复制到屏幕上,并且至少可以使用OpenGL 3.0,那么有一种更简单的方法:使用glBlitFramebuffer()。要使用它,您可以创建一个FBO,将其绑定为读取帧缓冲区,将纹理附加到它,然后复制。无需担心着色器,转换或任何东西。它也可能更有效率。

为此,请在初始化期间创建一次FBO:

GLuint fboId = 0;
glGenFramebuffers(1, &fboId);

然后,您可以随时在窗口的texId位置绘制ID为w,宽度为h和高度为(x, y)的纹理:

glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE2D, texId, 0);
glBlitFramebuffer(0, 0, w, h,
                  x, y, x + w, x + h,
                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

如果需要,可以通过对源矩形和目标矩形使用不同的大小来缩放此副本中的纹理。在这种情况下,请使用GL_LINEAR作为最后一个参数,而不是GL_NEAREST