我尝试使用恒定屏幕宽度绘制3D纹理线条。 (OpenGL ES 2.0)
实际上我想要的是简单的"体积"具有最小保证(钳位)屏幕宽度的线条。因此,当他们离得很远时,不会变得太瘦。
关于如何到达那里的任何输入都将非常感激但我还希望对我现在面临的问题有一些反馈。很可能是对透视正确插值如何工作的误解......
所以我有一个这样的三角形条:
struct tVtx
{
vec3 mPos;
vec3 mDir;
vec2 mTexCoord;
};
auto vtxs = std::vector< tVtx >{
{ vec3{ -1,0,0 }, vec3{ 1,0,0 }, vec2{ -1, 1 } },
{ vec3{ -1,0,0 }, vec3{ 1,0,0 }, vec2{ -1, -1 } },
{ vec3{ -1,0,0 }, vec3{ 1,0,0 }, vec2{ 0, 1 } },
{ vec3{ -1,0,0 }, vec3{ 1,0,0 }, vec2{ 0, -1 } },
{ vec3{ 1,0,0 }, vec3{ 1,0,0 }, vec2{ 0, 1 } },
{ vec3{ 1,0,0 }, vec3{ 1,0,0 }, vec2{ 0, -1 } },
{ vec3{ 1,0,0 }, vec3{ 1,0,0 }, vec2{ 1, 1 } },
{ vec3{ 1,0,0 }, vec3{ 1,0,0 }, vec2{ 1, -1 } }
};
我将它改造成&#34; world&#34;像这样的空间:
pt1 = vec3{ -0.450794667, 0.454502404,-0.437951744 };
pt2 = vec3{ -0.248224616,0.682369053, -0.886776387 };
auto center = ( pt1 + pt2 ) * 0.5f;
auto right = normalize( pt2 - pt1 );
auto up = normalize( cross( vec3( 0,0,1 ), right ) );
auto forw = cross( right, up );
auto mtx = mat4{ vec4( right, 0.0 ), vec4( up, 0.0 ), vec4( forw, 0.0 ), vec4( center, 1.0f ) };
我的顶点着色器类似于:
attribute vec3 aPos;
attribute vec3 aDir;
attribute vec2 aTexCoord;
uniform mat4 uMVPMtx;
uniform vec2 uScreenExtent; // half size of screen
uniform vec2 uInflate; // amount of line "grow" in pixels
varying mediump vec2 vTexCoord;
void main()
{
vec4 clipPos1 = uMVPMtx * vec4( aPos, 1.0 );
// get a point on "direction" line, transform in screen and then get screen space direction vector
// don't know how to transform a direction vector from WORLD to SCREEN space, naive way does not work ( MVP * vec4( aDir, 0.0 ) )
vec4 clipPos2 = uMVPMtx * vec4( aPos + aDir * 1000.0, 1.0 );
vec2 ndc1 = vec2( clipPos1 ) / clipPos1.w;
vec2 ndc2 = vec2( clipPos2 ) / clipPos2.w;
vec2 sc1 = ndc1 * uScreenExtent;
vec2 sc2 = ndc2 * uScreenExtent;
vec2 dir = normalize( sc2 - sc1 ) * sign( clipPos1.w * clipPos2.w ); // reduce damage if points lie on opposite sides of origin
vec2 perp = vec2( -dir.y, dir.x );
vec2 sc = sc1 + dir * aTexCoord.x * uInflate.x + perp * aTexCoord.y * uInflate.y;
vTexCoord = aTexCoord;
// bring back to clip space
gl_Position = vec4( sc / uScreenExtent * clipPos1.w, clipPos1.zw );
}
片段着色器类似于:
varying mediump vec2 vTexCoord;
void main()
{
mediump float dist = clamp( length( vTexCoord ), 0.0, 1.0 );
gl_FragColor = vec4( mix( vec3( 1.0, 0.25, 0.25 ), vec3( 0.25, 1.0, 0.25 ), dist ), 1.0 );
}
注意aTexCoord从-1变为1!
我得到的是:
上面的图片有uInflate.x = 0,所以它没有圆顶...
我想要的是一个带有居中红线的四边形,渐渐变为绿色。 这是因为我改变屏幕空间中的x和y坐标而不触及z和w组件的方式会产生不再共面的三角形吗?我很难想象这个......
更新
三角形在眼睛空间中是共面的,但它们的大小完全不同(在眼睛空间中)。在屏幕上看起来像四边形不再是四边形的四边形。我猜这是主要问题(因为透视正确插值??)。问题仍然存在:如何绘制具有恒定(或受控)屏幕宽度的3D纹理线条。使用3D我的意思是使用其他3D内容进行深度测试的线条。