3

我正在使用 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();
4

2 回答 2

1

好吧 - 我看到了你的问题。您正在为“中间中间”四边形使用 maxTexCoordBorderX(和 Y)的常量值。您需要随着尺寸的变化重新计算中心四边形的 UV 坐标(例如:width / (currWidth - 2 * borderWidth)),然后您可以将该纹理设置为始终重复,但是由于您将纹理坐标修改为 ui 元素调整大小,中心部分永远不会重复。

当然 - 如果您打算在未来某个时间点使用 VBO 或更高性能的东西,您可以简单地为每个片段定义两个片段着色器(每个都有自己的sampler2D对象;一个重复,另一个拉伸)平铺模式并使用“重复”着色器渲染所有角四边形和中间中间四边形,使用拉伸着色器渲染所有边缘四边形。这不需要重新计算并且应该非常快。

注意:您在这里绘制多个四边形,这不是一个好主意。我建议使用具有共享顶点的索引网格。这将最大限度地减少四边形边缘“撕裂”的可能性。

于 2012-12-13T15:24:09.530 回答
0

如果你拉伸边缘/中心,你会没事的,但由于你是平铺的,你将不得不创建一个只有中心部分的第二个纹理。

请注意,如果您有边框的大小,这可以通过编程方式完成。您将中心的内容复制到一个新的二维数组中,然后将其上传到另一个纹理。

另一种解决方案(正如我在评论中所说)是将中间中间四边形的纹理坐标设置为与角的内部顶点相同的坐标。这样,中心四边形的纹理就被拉伸了。请注意,除非整个东西都包含在右上角的四边形中,否则这会在右上角的光亮上产生一些奇怪的拉伸。如果您想使用重复解决方案,您仍然会遇到问题。

如果您仍想重复中心部分并且不介意将整个渲染管道移动到未弃用的 OpenGL,那么 ananthonline 的答案会更好。如果您不想/不能将渲染代码移动到更现代的 OpenGL,那么纹理副本几乎是唯一的解决方案。

于 2012-12-13T14:34:08.163 回答