仅调整纹理的一部分,OpenGL

时间:2012-12-13 14:23:59

标签: 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();

2 个答案:

答案 0 :(得分:1)

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

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

注意:你在这里画了多个四边形,这不是一个好主意。我建议使用带共享顶点的索引网格。这样可以最大限度地减少四边形边缘“撕裂”的可能性。

答案 1 :(得分:0)

如果你伸展边缘/中心,你会很好,但是因为你正在平铺,你将不得不创建只有中心部分的第二个纹理。

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

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

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