user-interface - 仅调整纹理的一部分,OpenGL

标签 user-interface opengl graphics 2d textures

我正在 OpenGL 中开发 GUI。我正在使用此图像来纹理我的按钮: enter image description here

你看不太清楚,但它周围有一个浅色边框(2 像素宽)。

我想要实现的是拥有可很好调整大小的按钮,使其边框保持不变。根据这里给我的提示,在 StackOverflow 上我决定使用 9-cell-pattern,所以我将四边形分成 9 个部分,如下所示:

enter image description here

我真的很喜欢我实现的关于边界的效果,但问题在于位于中心的四边形(第 9 个):

enter image description here

我想像我一样重复或包裹纹理,但忽略边框。

所以我的问题是 - 有什么方法可以只用我现在使用的一种纹理来做到这一点吗?或者我应该创建第二个纹理,它会减少一个边框宽度,并用这个纹理在中间渲染这个四边形?

我也不知道是否有必要,但我把我的代码片段放在这里:

这是我用来平铺/包裹纹理的代码:

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/

相关文章:

C++ OpenGL 如何从四元数获取旋转 x,y,z

c++ - 在 OpenGL 上画圆

c++ - OpenGL 法线未出现在三角形中

c# - 如何使用 WinAPI 快速逐像素处理图像?

math - 像 Mathematica 这样的程序是如何绘制图形的?我该如何制作这样的程序?

java - 实现双缓冲?

python - 高分辨率屏幕上的 PyQt GUI 大小

java - 具有多个Windows设计的MVC

C++ 或 Python(也许是其他)为 C 中的控制台应用程序创建 GUI

google-chrome - Casperjs/PhantomJs 与 Selenium