我正在 OpenGL 中开发 GUI。我正在使用此图像来纹理我的按钮:
你看不太清楚,但它周围有一个浅色边框(2 像素宽)。
我想要实现的是拥有可很好调整大小的按钮,使其边框保持不变。根据这里给我的提示,在 StackOverflow 上我决定使用 9-cell-pattern,所以我将四边形分成 9 个部分,如下所示:
我真的很喜欢我实现的关于边界的效果,但问题在于位于中心的四边形(第 9 个):
我想像我一样重复或包裹纹理,但忽略边框。
所以我的问题是 - 有什么方法可以只用我现在使用的一种纹理来做到这一点吗?或者我应该创建第二个纹理,它会减少一个边框宽度,并用这个纹理在中间渲染这个四边形?
我也不知道是否有必要,但我把我的代码片段放在这里:
这是我用来平铺/包裹纹理的代码:
switch(m_bTiling)
{
case true:
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_REPEAT );
break;
case false:
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP );
break;
}
下面是绘制四边形的代码:
// Top left quad [1]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(0.0f, 1.0-maxTexCoordBorderY);
glVertex2i(pos.x, pos.y + m_borderWidth);
// Top left
glTexCoord2f(0.0f, 1.0);
glVertex2i(pos.x, pos.y);
// Top right
glTexCoord2f(maxTexCoordBorderX, 1.0);
glVertex2i(pos.x + m_borderWidth, pos.y);
// Bottom right
glTexCoord2f(maxTexCoordBorderX, 1.0-maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);
glEnd();
// Top middle quad [2]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(maxTexCoordBorderX, 1.0 - maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);
// Top left
glTexCoord2f(maxTexCoordBorderX, 1.0);
glVertex2i(pos.x + m_borderWidth, pos.y);
// Top right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 1.0);
glVertex2i(pos.x + width - m_borderWidth, pos.y);
// Bottom right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 1.0 - maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth);
glEnd();
// Top right quad [3]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(1.0 - maxTexCoordBorderX, 1.0 - maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth);
// Top left
glTexCoord2f(1.0 - maxTexCoordBorderX, 1.0);
glVertex2i(pos.x + width - m_borderWidth, pos.y);
// Top right
glTexCoord2f(1.0, 1.0);
glVertex2i(pos.x + width, pos.y);
// Bottom right
glTexCoord2f(1.0, 1.0 - maxTexCoordBorderY);
glVertex2i(pos.x + width, pos.y + m_borderWidth);
glEnd();
// Middle left quad [4]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(0.0, maxTexCoordBorderY);
glVertex2i(pos.x, pos.y + height - m_borderWidth);
// Top left
glTexCoord2f(0.0, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x, pos.y + m_borderWidth);
// Top right
glTexCoord2f(maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);
// Bottom right
glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
glEnd();
// Middle right quad [5]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth);
// Top left
glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth);
// Top right
glTexCoord2f(1.0, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x + width, pos.y + m_borderWidth);
// Bottom right
glTexCoord2f(1.0, maxTexCoordBorderY);
glVertex2i(pos.x + width, pos.y + height - m_borderWidth);
glEnd();
// Bottom left quad [6]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(0.0, 0.0);
glVertex2i(pos.x, pos.y + height);
// Top left
glTexCoord2f(0.0, maxTexCoordBorderY);
glVertex2i(pos.x, pos.y + height - m_borderWidth);
// Top right
glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
// Bottom right
glTexCoord2f(maxTexCoordBorderX, 0.0);
glVertex2i(pos.x + m_borderWidth, pos.y + height);
glEnd();
// Bottom middle quad [7]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(maxTexCoordBorderX, 0.0);
glVertex2i(pos.x + m_borderWidth, pos.y + height);
// Top left
glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
// Top right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth);
// Bottom right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 0.0);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height);
glEnd();
// Bottom right quad [8]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(1.0 - maxTexCoordBorderX, 0.0);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height);
// Top left
glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth);
// Top right
glTexCoord2f(1.0, maxTexCoordBorderY);
glVertex2i(pos.x + width, pos.y + height - m_borderWidth);
// Bottom right
glTexCoord2f(1.0, 0.0);
glVertex2i(pos.x + width, pos.y + height);
glEnd();
// Middle middle quad [9]
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
// Top left
glTexCoord2f(maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);
// Top right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth);
// Bottom right
glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordBorderY);
glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth);
glEnd();
最佳答案
嗯 - 我明白你的问题了。您正在为“中间中间”四边形使用 maxTexCoordBorderX(和 Y)的常量值。您需要在尺寸变化时重新计算中心四边形的 UV 坐标(例如:宽度/(currWidth - 2 * borderWidth)),然后您可以将该纹理设置为始终重复,但由于您将纹理坐标修改为 ui 元素调整大小,中心部分永远不会重复。
当然 - 如果您打算在将来的某个时间点使用 VBO 或更高性能的东西,您可以简单地定义两个片段着色器(每个都有自己的 sampler2D 对象;一个重复,另一个拉伸(stretch))为每个平铺模式并使用“重复”着色器渲染所有角四边形和中间中间四边形,并使用拉伸(stretch)着色器渲染所有边缘四边形。这不需要重新计算并且应该非常快。
注意:您在这里绘制了多个四边形,这不是一个好主意。我建议使用具有共享顶点的索引网格。这将最大限度地减少股四头肌边缘出现“撕裂”的可能性。
关于user-interface - 仅调整纹理的一部分,OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13861858/