具有恒定屏幕宽度

时间:2016-06-10 16:45:41

标签: opengl-es 3d line vertex-shader

我尝试使用恒定屏幕宽度绘制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!

我得到的是:

Screwed textured quad

上面的图片有uInflate.x = 0,所以它没有圆顶...

我想要的是一个带有居中红线的四边形,渐渐变为绿色。 这是因为我改变屏幕空间中的x和y坐标而不触及z和w组件的方式会产生不再共面的三角形吗?我很难想象这个......

更新
三角形在眼睛空间中是共面的,但它们的大小完全不同(在眼睛空间中)。在屏幕上看起来像四边形不再是四边形的四边形。我猜这是主要问题(因为透视正确插值??)。问题仍然存在:如何绘制具有恒定(或受控)屏幕宽度的3D纹理线条。使用3D我的意思是使用其他3D内容进行深度测试的线条。

0 个答案:

没有答案