Искажение перспективы
У меня такая странная проблема, и я надеюсь, что кто-то сможет прояснить это для меня, чтобы я мог понять, что неправильно и действовать соответственно. В OpenGL (фиксированная функция) я рисую трубку с внутренними гранями в орфографической проекции.
На изображении ниже показан результат. Он состоит из 4-х колец вершин, которые образуют треугольники, используя указательный рисунок, показанный слева. Для вашего удобства я пронумеровал вершины на трубе. Справа используется используемая текстура:
![введите описание изображения здесь]()
Как вы можете видеть, текстура сильно искажается. Поскольку я изначально создал трубку с двумя кольцами вершин, я думал, что увеличение количества колец исправит искажение, но не будет радости. Также glHint не влияет на эту конкретную проблему.
Координаты текстуры выглядят нормально. Кроме того, шаблон проверки выглядит правильно, но я думаю, что искажение просто не видно в этом очень конкретном шаблоне.
Пожалуйста, игнорируйте скрещенные линии, поскольку один из них - несуществующий край; Я передал каркас через GL_LINE_LOOP.
Ответы
Ответ 1
Этот особый эффект вызван тем, как координаты текстуры интерполируются в треугольнике. Случается, что одно направление становится основным компонентом, тогда как другое искажено. Ваш образец очень сильно склонен к этому. Это также является проблемой с перспективными проекциями и текстурами на полах или стенах. То, что вам нужно, так называемое "перспективное правильное текстурирование" PCT. Там glHint
для этого, но я думаю, вы уже пробовали это.
Честно говоря, единственный способ избежать этого - это подразделить и применить корректуру перспективы. Но, к счастью, это достаточно просто для геотермии на основе четырехстороннего подхода (например, для вас). При разбиении краев интерполируют координаты текстуры в центрах разбиения по всем 4 ребрам и используют среднее значение из 4 из них. Интерполирование координаты текстуры только вдоль одного края - именно то, чего вы хотите избежать.
Если вы хотите сохранить данные геометрии нетронутыми, вы можете реализовать PCT в шейдере фрагментов.
Ответ 2
Попробуйте следующее подразделение:
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
.
Ответ 3
Почему вы используете для этого орфографическую проекцию? Если вы используете перспективную проекцию, OpenGL будет корректировать отображение текстур для вас.