我有这个奇怪的问题,我希望有人可以为我清除这一点,这样我就可以理解错误并采取相应的行动。在OpenGL(固定功能)中,我正在渲染具有正面投影内部面的管。
下图显示了结果。它由4个顶点环组成,这些顶点使用左侧所示的索引模式形成三角形。为方便起见,我在管上编号顶点。右边是正在使用的纹理:
正如您所看到的,纹理严重扭曲。当我最初创建仅有2个顶点环的管时,我认为提高环的数量可以解决失真但没有快乐。此外,glHint似乎不会影响这个特定的问题。
纹理坐标似乎没问题。此外,检查器模式似乎正确渲染,但我想失真在那个非常特定的模式中是不可见的。
请忽略交叉线,因为其中一条是不存在的边缘;我通过GL_LINE_LOOP渲染了线框。
答案 0 :(得分:2)
这种特殊效果是由纹理坐标以三角形插值的方式引起的。会发生的是,一个方向成为主要组成部分,而另一个方向则是倾斜的。你的标本很容易发生这种情况。这也恰好是地板或墙壁上的透视投影和纹理的问题。您需要的是所谓的“透视正确纹理”PCT。这有一个glHint
,但我想,你已经尝试过了。
坦率地说,避免这种情况的唯一方法是通过细分和来应用透视校正。但幸运的是,对于基于四边形的地质测量(与您的一样),这很容易。当细分边缘时,沿着所有4个边缘在细分中心处插入纹理坐标,并使用其中4个的平均值。仅沿一条边插入纹理坐标正是您想要避免的。
如果要保持几何数据不变,可以在片段着色器中实现PCT。
答案 1 :(得分: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
。
答案 2 :(得分:0)
为什么要使用正交投影?如果您使用透视投影,OpenGL将为您校正纹理映射。