2012-12-13 171 views
3

我正在使用OpenGL的GUI。我正在使用此图像来纹理我的按钮: enter image description here调整纹理的一部分,OpenGL

您看不到它,但它周围有一个轻的边框(2像素宽度)。

我想要实现的是具有很好的可调整大小的按钮,它保持边界不变。据这里给我暗示,在计算器上我决定使用9芯模式,所以我分了我的四成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(); 
+0

请注意,由于内部的颜色渐变,您的纹理不容易进行平铺。你可以尝试从近似(x = 2,y = 20,w = 18,h = 18)中选取一个四边形,并将其平铺以获得更好的效果 – Constantin

回答

0

如果你拉伸边缘/中心,你会被罚款,但因为你是瓷砖,你将不得不创建第二个与中心部分的纹理。

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

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

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

+0

感谢Robert提供的答案,但是通过拉伸边缘/中心?你的意思是使用GL_CLAMP而不是GL_REPEAT? –

+0

不具体,您只需将中央四边形的纹理坐标定义为角块内侧的相同纹理坐标。这样,纹理的中心在中心四边形上延伸出来。 –

+0

复制纹理很浪费,重新计算纹理坐标更容易 - 请注意,使用两个片段着色器对两个采样器进行相同纹理操作也可以更有效地完成此操作,请参阅上面的答案。 – Ani

1

嗯 - 我看到你的问题。你正在使用一个恒定值的maxTexCoordBorderX(和Y)作为你的“中间中间”四元组。您需要重新计算中心四边形的UV坐标(如宽度/(currWidth - 2 * borderWidth)),然后您可以将该纹理设置为始终重复,但由于您将纹理坐标修改为ui元素调整大小,中心部分不会重复。当然,如果你打算在将来的某个时间点使用VBO或更高性能的东西,你可以简单地定义两个片段着色器(每个都有自己的sampler2D对象;一个重复,另一个重复)为每个拼贴模式,并使用“重复”着色器和使用拉伸着色器的所有边四边形呈现所有角四边形和中间四边形四边形。这不需要重新计算,应该非常快。

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

+0

谢谢Ananthonline的答案。我还有一个问题 - 我完全不知道这个现代的OpenGL,所以我不得不阅读关于VBOs和休息,但是有可能只用'现代'代替这个绘图四边形的代码,或者我可以必须改变所有的设置,等等?还是比这个旧版本更难? –

+0

你可以做一个简单的替换 - 而不是两个着色器,使用一个着色器来控制采样器的使用(重复或拉伸)并在绘制每个四边形之前进行适当的设置。在即时模式绘图中使用两个着色器的问题是,您在绘制单个四边形时会多次进行这种更改,而更改状态通常会影响性能。理想情况下,您应该收集具有相同状态的所有状态,并在可能的情况下批量渲染它们(在设置该状态之后)。这里(http://www.lighthouse3d.com/opengl/glsl/)是一个GLSL教程,可以帮助你开始。 – Ani