10

我遇到了这个奇怪的问题,我希望有人可以为我解决这个问题,这样我就可以了解问题所在并采取相应措施。在 OpenGL(固定功能)中,我在正交投影中渲染具有内面的管。

下图显示了结果。它由 4 个顶点环组成,这些顶点使用左侧显示的索引模式形成三角形。为方便起见,我对管上的顶点进行了编号。右边是正在使用的纹理:

在此处输入图像描述

如您所见,纹理被严重扭曲。当我最初创建只有 2 个顶点环的管时,我认为增加环的数量可以修复失真,但没有任何乐趣。glHint 似乎也不会影响这个特定的问题。

纹理坐标似乎没问题。此外,棋盘格图案似乎可以正确渲染,但我猜在那个非常具体的图案中失真是不可见的。

请忽略交叉线,因为其中之一是不存在的边缘;我通过 GL_LINE_LOOP 渲染了线框。

4

3 回答 3

2

这种特殊效果是由纹理坐标在三角形中插值的方式引起的。发生的情况是,一个方向成为主要组成部分,而另一个方向是倾斜的。你的标本恰好很容易出现这种情况。这也恰好是地板或墙壁上的透视投影和纹理的问题。您需要的是所谓的“透视正确纹理”PCT。有一个glHint为此,但我想,你已经尝试过。

坦率地说,避免这种情况的唯一方法是细分应用透视校正。但幸运的是,这对于基于四边形的 geoemtry(比如你的)来说很容易。细分边缘时,沿所有 4 个边缘在细分中心插入纹理坐标,并使用其中 4 个的平均值。仅沿一条边插入纹理坐标正是您想要避免的。

如果您想保持几何数据不变,您可以在片段着色器中实现 PCT。

于 2012-01-25T22:25:43.253 回答
0

尝试一些细分:

template< typename Vec >
void glVec2d( const Vec& vec )
{
    glVertex2f( static_cast<float>( vec.x() ) , static_cast<float>( vec.y() ) );
}

template< typename Vec >
void glTex2d( const Vec& vec )
{
    glTexCoord2f( static_cast<float>( vec.x() ) , static_cast<float>( vec.y() ) );
}

template< typename Vec > 
void glQuad
    (
    const Vec& A,
    const Vec& B,
    const Vec& C,
    const Vec& D,
    unsigned int divs = 2,
    const Vec& At = Vec(0,0),
    const Vec& Bt = Vec(1,0),
    const Vec& Ct = Vec(1,1),
    const Vec& Dt = Vec(0,1)
    )
{
    // base case
    if( divs == 0 )
    {
        glTex2d( At );
        glVec2d( A );

        glTex2d( Bt );
        glVec2d( B );

        glTex2d( Ct );
        glVec2d( C );

        glTex2d( Dt );
        glVec2d( D );

        return;
    }

    Vec AB = (A+B) * 0.5;
    Vec BC = (B+C) * 0.5;
    Vec CD = (C+D) * 0.5;
    Vec AD = (A+D) * 0.5;
    Vec ABCD = (AB+CD) * 0.5;

    Vec ABt = (At+Bt) * 0.5;
    Vec BCt = (Bt+Ct) * 0.5;
    Vec CDt = (Ct+Dt) * 0.5;
    Vec ADt = (At+Dt) * 0.5;
    Vec ABCDt = (ABt+CDt) * 0.5;

    // subdivided point layout
    // D   CD   C
    // 
    // AD ABCD BC 
    //
    // A   AB   B

    // subdivide
    glQuad2d( A, AB, ABCD, AD, divs - 1, At, ABt, ABCDt, ADt );
    glQuad2d( AB, B, BC, ABCD, divs - 1, ABt, Bt, BCt, ABCDt );
    glQuad2d( ABCD, BC, C, CD, divs - 1, ABCDt, BCt, Ct, CDt );
    glQuad2d( AD, ABCD, CD, D, divs - 1, ADt, ABCDt, CDt, Dt );
}

我通常Eigen::Vector2f用于Vec.

于 2012-01-25T21:45:56.443 回答
0

你为什么要为此使用正交投影?如果您使用透视投影,OpenGL 会为您校正纹理映射。

于 2012-01-25T22:34:06.580 回答