不透明的OpenGL纹理具有透明边框 [英] Opaque OpenGL textures have transparent border

查看:120
本文介绍了不透明的OpenGL纹理具有透明边框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题涉及使用OpenGL渲染文本-将文本渲染为纹理,然后绘制到四边形上.问题在于纹理边缘上的像素被绘制为部分透明.纹理的内部很好.

My problem concerns rendering text with OpenGL -- the text is rendered into a texture, and then drawn onto a quad. The trouble is that the pixels on the edge of the texture are drawn partially transparent. The interior of the texture is fine.

我正在使用NEAREST(非)插值计算纹理坐标以击中纹理像素的中心,将纹理环绕设置为CLAMP_TO_EDGE,并设置投影矩阵以将我的顶点放置在视口像素的中心.仍然看到问题.

I'm calculating the texture coordinates to hit the center of my texels, using NEAREST (non-)interpolation, setting the texture wrapping to CLAMP_TO_EDGE, and setting the projection matrix to place my vertices at the center of the viewport pixels. Still seeing the issue.

我正在使用其纹理实用程序来处理VTK.这些是用于加载纹理的GL调用,具体取决于调试器的逐步执行:

I'm working on VTK with their texture utilities. These are the GL calls that are used to load the texture, as determined by stepping through with a debugger:

glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Create and bind pixel buffer object here (not shown, lots of indirection in VTK)...
glTexImage2D( GL_TEXTURE_2D, 0 , GL_RGBA, xsize, ysize, 0, format, GL_UNSIGNED_BYTE, 0);
// Unbind PBO -- also omitted
glBindTexture(GL_TEXTURE_2D, id);
glAlphaFunc (GL_GREATER, static_cast<GLclampf>(0));
glEnable (GL_ALPHA_TEST);
// I've also tried doing this here for premultiplied alpha, but it made no difference:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();

渲染代码:

  float p[2] = ...; // point to render text at

  int imgDims[2] = ...; // Actual dimensions of image
  float width = ...; // Width of texture in image
  float height = ...; // Height of texture in image

  // Prepare the quad
  float xmin = p[0];
  float xmax = xmin + width - 1;
  float ymin = p[1];
  float ymax = ymin + height - 1;
  float quad[] = { xmin, ymin,
                   xmax, ymin,
                   xmax, ymax,
                   xmin, ymax };

  // Calculate the texture coordinates.
  float smin = 1.0f / (2.0f * (imgDims[0]));
  float smax = (2.0 * width - 1.0f) / (2.0f * imgDims[0]);
  float tmin = 1.0f / (2.0f * imgDims[1]);
  float tmax = (2.0f * height - 1.0f) / (2.0f * imgDims[1]);

  float texCoord[] = { smin, tmin,
                       smax, tmin,
                       smax, tmax,
                       smin, tmax };

  // Set projection matrix to map object coords to pixel centers
  // (modelview is identity)
  GLint vp[4];
  glGetIntegerv(GL_VIEWPORT, vp);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  float offset = 0.5;
  glOrtho(offset, vp[2] + offset,
          offset, vp[3] + offset,
          -1, 1);

  // Disable polygon smoothing. Why not, I've tried everything else?
  glDisable(GL_POLYGON_SMOOTH);

  // Draw the quad
  glColor4ub(255, 255, 255, 255);
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glVertexPointer(2, GL_FLOAT, 0, points);
  glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
  glDrawArrays(GL_QUADS, 0, 4);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  glDisableClientState(GL_VERTEX_ARRAY);

  // Restore projection matrix
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();

出于调试目的,我用红色覆盖了最外面的纹理像素,并用绿色覆盖了下一个纹理像素的内层(否则很难看到大部分是白色的文本图像中发生了什么).

For debugging purposes, I've overwritten the outermost texels with red, and the next inner layer of texels with green (otherwise it's hard to see what's going on in the mostly-white text image).

我已经使用gDEBugger在内存中检查了纹理,它看起来像预期的那样-纹理区域周围的鲜红色和绿色边框(多余的空白被填充以使其大小为2的幂).供参考:

I've inspected the texture in-memory using gDEBugger, and it looks as expected -- bright red and green borders around the texture area (the extra empty space is padding to make its size a power of two). For reference:

这是最终渲染图像的外观(放大20倍-黑色像素是在调试边界下渲染的文本的剩余部分).淡红色边框,但内部边框仍为绿色粗体:

Here's what the final rendered image looks like (magnified 20x -- the black pixels are remnants of the text that was rendered under the debugging borders). Pale red border, but still a bold green inner border:

因此,受影响的只是像素的外边缘.我不确定是颜色混合还是alpha混合使事情搞砸了,我很茫然.我注意到角落像素的颜色是边缘像素的两倍,也许这很重要……也许有人可以发现错误?

So it is just the outer edge of pixels that is affected. I'm not sure if it's color-blending or alpha-blending that's screwing things up, I'm at a loss. I've noticed that the corner pixels are twice as pale as the edge pixels, perhaps that's significant... Maybe someone here can spot the error?

推荐答案

好的,最近几天我一直在研究它.几乎没有任何想法是行不通的.唯一有效的方法是承认此完美像素"的存在并尝试欺骗它.不好,我无法为你的答案Cosmic Bacon投票.但是,即使看起来不错,您的答案也可能会破坏游戏之类的特殊程序中的所有内容.我的答案-改善了您的答案.

Okay, I've worked on it for the last few days. There were few ideas that didn't work at all. The only one that worked is to admit that this "Perfect Pixel" exists and try to trick it. Bad That I can't vote up for your answer Cosmic Bacon. But your answer, even if it looks good -- will a little bit ruin everything in a special programs like Games. My answer -- is improved yours.

这是解决方案:

第1步:制作一种可以绘制所需纹理的方法,并且仅将其用于绘制.并将0.5f添加到每个坐标.看:

Step1: Make a method that draws texture that you need and use only it for drawing. And Add 0.5f to every coordinate. Look:

public void render(Texture tex,float x1,float y1,float x2,float y2)
{
    tex.bind();
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0,0);
    GL11.glVertex2f(x1+0.5f,y1+0.5f);
    GL11.glTexCoord2f(1,0);
    GL11.glVertex2f(x2+0.5f,y1+0.5f);
    GL11.glTexCoord2f(1,1);
    GL11.glVertex2f(x2+0.5f,y2+0.5f);
    GL11.glTexCoord2f(0,1);
    GL11.glVertex2f(x1+0.5f,y2+0.5f);
    GL11.glEnd();
}

第2步:如果您要使用"glTranslatef(somethin1,somethin2,0)",最好的方法是克服"Translatef"并且不允许相机移动小数距离.原因是如果相机继续运行的机会很小,例如0.3-迟早您会再次看到此问题(我想是多次).接下来的代码使摄影机跟随具有X和Y的对象.摄影机将永远不会从视线范围内松开该对象:

Step2: If you're going to use "glTranslatef(somethin1,somethin2,0)" it will be nice to make a method that overcomes "Translatef" and doesn't let camera to move on fractional distance. Cause if there will be a little chance that Camera moves on, let's say, 0.3 -- Sooner or later you'll see this issue again(multiple times, i suppose). Next code makes camera follow the Object that has X and Y. And Camera will never loose the object from it's sight:

public void LookFollow(Block AF)
{
    float some=5;//changing me will cause camera to move faster/slower
    float mx=0,my=0;

    //Right-Left
    if(LookCorX!=AF.getX())
    {
        if(AF.getX()>LookCorX)
        {
            if(AF.getX()<LookCorX+2)
                mx=AF.getX()-LookCorX;
            if(AF.getX()>LookCorX+2)
                mx=(AF.getX()-LookCorX)/some;
        }
        if(AF.getX()<LookCorX)
        {
            if(2+AF.getX()>LookCorX)
                mx=AF.getX()-LookCorX;
            if(2+AF.getX()<LookCorX)
                mx=(AF.getX()-LookCorX)/some;
        }
    }

    //Up-Down
    if(LookCorY!=AF.getY())
    {
        if(AF.getY()>LookCorY)
        {
            if(AF.getY()<LookCorY+2)
                my=AF.getY()-LookCorY;
            if(AF.getY()>LookCorY+2)
                my=(AF.getY()-LookCorY)/some;
        }
        if(AF.getY()<LookCorY)
        {
            if(2+AF.getY()>LookCorY)
                my=AF.getY()-LookCorY;
            if(2+AF.getY()<LookCorY)
                my=(AF.getY()-LookCorY)/some;
        }
    }

    //Evading "Perfect Pixel"
    mx=(int)mx;
    my=(int)my;

    //Moving Camera
    GL11.glTranslatef(-mx,-my,0);

    //Saving up Position of camera.
    LookCorX+=mx;
    LookCorY+=my;
}
float LookCorX=300,LookCorY=200; //camera's starting position

结果-我们收到的摄像机运动得更加锐利,导致步长不能小于1像素,有时,有必要减小步长,但是纹理看起来还可以,而且- -伟大的进步!

As the result -- we receive a camera that moves a little sharper, cause steps can't be less than 1 pixel, and sometimes, it's necessary to make a smaller step, but textures are looking okay, and, it's -- a Great Progress!

很抱歉有一个大答案.我仍在研究好的解决方案.一旦我发现更好和更短的东西-我会清除掉.

Sorry for a real Big Answer. I'm still working on a Good Solution. Once I'll find something better and shorter -- this will be erased by me.

这篇关于不透明的OpenGL纹理具有透明边框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆