OpenGL искажение перспективы - PullRequest
10 голосов
/ 26 января 2012

У меня возникла эта странная проблема, и я надеюсь, что кто-то сможет прояснить это для меня, чтобы я мог понять, что не так, и действовать соответственно.В OpenGL (с фиксированной функцией) я рендерил трубку с внутренними гранями в ортографической проекции.

На рисунке ниже показан результат.Он состоит из 4 колец вершин, которые образуют треугольники, используя шаблон индекса, показанный слева.Для вашего удобства я пронумеровал вершины на трубе.Справа находится используемая текстура:

enter image description here

Как видите, текстура сильно искажена.Поскольку я изначально создал трубу только с двумя кольцами вершин, я думал, что увеличение количества колец исправит искажение, но не доставит радости.Кроме того, glHint, похоже, не влияет на эту конкретную проблему.

С текстурными координатами все в порядке.Кроме того, шаблон проверки, похоже, отображается правильно, но я думаю, что искажение просто не видно в этом очень специфическом шаблоне.

Пожалуйста, игнорируйте перечеркнутые линии, поскольку одна из них является несуществующим краем;Я рендерил каркас через GL_LINE_LOOP.

Ответы [ 3 ]

2 голосов
/ 26 января 2012

Этот конкретный эффект вызван тем, как координаты текстуры интерполируются в треугольнике.Что происходит, так это то, что одно направление становится основным компонентом, тогда как другое искажено.Ваш экземпляр оказался очень склонным к этому.Это также может быть проблемой с перспективными проекциями и текстурами на полах или стенах.То, что вам нужно, это так называемое «перспективное правильное текстурирование» PCT.Для этого есть glHint, но я думаю, вы уже пробовали это.

Откровенно говоря, единственный способ избежать этого - это поделить и , применяя также коррекцию перспективы.Но, к счастью, это достаточно просто для четырехсторонней геоемтрии (как у вас).При разделении ребер интерполируйте координаты текстуры в центрах деления по всем четырем ребрам и используйте среднее значение из четырех из них.Вам следует избегать интерполяции координат текстуры только вдоль одного края.

Если вы хотите, чтобы ваши геометрические данные оставались нетронутыми, вы можете реализовать PCT в фрагментном шейдере.

0 голосов
/ 26 января 2012

Почему вы используете для этого ортографическую проекцию? Если бы вы использовали перспективную проекцию, OpenGL исправил бы для вас наложение текстуры.

0 голосов
/ 26 января 2012

Попробуйте подразделение:

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.

...