【问题标题】:Match texture coordinates to primitive size将纹理坐标与图元大小匹配
【发布时间】:2012-05-25 18:53:10
【问题描述】:

我正在研究字体生成解决方案并面临纹理问题。我正在动态创建纹理图集,然后通过它们的纹理坐标映射每个字母。

这是映射“t”字母的结果:(生成的纹理在顶部,我绘制的在底部)

似乎问题在于图元和纹理区域的大小不匹配,这就是 openGL 尝试调整它大小的原因。加载/渲染纹理时,我在 Min 和 Mag 上都使用 GL_NEAREST

这是渲染代码:

glBegin(GL_TRIANGLE_STRIP);

float twidth = 7.f / 512.f;
float theight = 11.f / 512.f;

float width = 7.f;
float height = 11.f;

float w = width / 2.f;
float h = height / 2.f;

float x = 100;
float y = 100;

float tx = 135.f / 512.f;
float ty = 0;

glTexCoord2f(tx, ty);
glVertex2f(x - w, y-h);

glTexCoord2f(tx + twidth, ty);
glVertex2f(x + w, y-h);

glTexCoord2f(tx, ty + theight);
glVertex2f(x - w, y+h);

glTexCoord2f(tx + twidth, ty + theight);
glVertex2f(x + w, y+h);

glEnd();

这里是初始化代码:

glViewport(0,0,width,height);       

glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);   

// Set up the GL state.
glClearColor(1, 1, 1, 1);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);


//glDisable(GL_BLEND);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(0, width, height, 0, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

纹理加载代码:

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 512, 512,
        0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, &texBinary[0]);

【问题讨论】:

  • 你能澄清一下问题是什么吗?我不确定我应该从这张图片中拿走什么。
  • 看看图片底部的't'字母和顶部的't'字母

标签: opengl-es opengl-es-2.0 textures texture-mapping


【解决方案1】:

您的问题源于一个常见的误解,即 OpenGL 如何处理纹理坐标。

纹理坐标 0 和 1 不在像素中心!

纹理实际上是多维采样器,纹理数据为采样器插值提供了支持。现在,这种采样的工作方式对纹理坐标映射施加了一些限制。一个边界条件是,支撑点应该沿维度等距。现在请记住,OpenGL 支持纹理包装。

您的图像基本上是一个光栅,一个样方网格,称为像素。假设你连续有 8 个像素

   |0|1|2|3|4|5|6|7|

纹理坐标为

   |0|1|2|3|4|5|6|7|
   ^               ^
  0.0             1.0

这是众所周知的栅栏柱问题。您的像素中心实际上位于纹理坐标处

(0/8 + 1/8)/2, (1/8 + 2/8)/2, …, (7/8 + 8/8)/2

或更一般地

(2i + 1)/2N

但是,在文本渲染的情况下,您很少需要过滤纹理;如果您缩小光栅化字形,结果会看起来很弱,放大光栅化字形会松散或出现锯齿。

如果您想使用固定功能管道,纹理矩形非常适合这种情况。在要求使用着色器(3 及以上)的更高版本的 OpenGL 中,有一个特殊的纹理采样函数,它接受绝对纹理像素索引而不是采样器插值坐标。它们中的任何一个都非常适合这项任务。

如果你使用 Vector TexturesDistance Maps,那么你对 glyps 的采样方式就完全不同了。

【讨论】:

  • 快速更正——fencepost问题的通用解决方案是(2i + 1) / (2N)
  • @RafaelSanches:向纹理坐标添加偏移。根据给定的公式计算偏移的确切值。我严格反对在 StackOverflow 答案中将这样的内容放入代码中,以阻止盲目的复制和粘贴,而不花一些精力去思考那里写的内容。
  • 如果您知道答案,那将非常有价值,因为有些人对 Opengl API 不满意,而且这个问题似乎经常发生。
  • @RafaelSanches:您希望它成为客户端,并将调整烘焙到顶点属性中吗?或者更确切地说,在顶点着色器中,基于原始顶点位置?还是在片段着色器中?不将一些代码写入此类问题的答案的原因之一是,有很多方法,最终可以这样做。如果您只查看纹理坐标,您所要做的就是(字面意思)复制公式并将它们粘贴到源代码的一部分中,其中纹理坐标被放入顶点属性中。
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-03-25
  • 2013-04-21
相关资源
最近更新 更多