如何使广告牌球形(How to make a billboard spherical)

2019-10-29 13:47发布

在此之后turorial 这里

我已成功地创建的圆柱形广告牌(它利用几何着色器这需要点并产生四边形)。 问题是,当我移动相机,使它比广告牌高(使用gluLookat)广告牌不旋转,真正面对镜头(好像它是一个圆柱形的广告牌)。

如何使之变成球形?

如果有人有兴趣,这里略作修改几何着色器的代码:

#version 330
//based on a great tutorial at http://ogldev.atspace.co.uk/www/tutorial27/tutorial27.html

layout (points) in;
layout (triangle_strip) out;
layout (max_vertices = 4) out;

uniform mat4 mvp;
uniform vec3 cameraPos;

out vec2 texCoord;

void main(){
    vec3 pos = gl_in[0].gl_Position.xyz;
    pos /= gl_in[0].gl_Position.w; //normalized device coordinates
    vec3 toCamera = normalize(cameraPos - pos);
    vec3 up = vec3(0,1,0);
    vec3 right = normalize(cross(up, toCamera)); //right-handed coordinate system
    //vec3 right = cross(toCamera, up); //left-handed coordinate system

    pos -= (right*0.5);
    gl_Position = mvp*vec4(pos,1.0);
    texCoord = vec2(0,0);
    EmitVertex();

    pos.y += 1.0;   
    gl_Position = mvp*vec4(pos,1.0);
    texCoord = vec2(0,1);
    EmitVertex();

    pos.y -= 1.0;   
    pos += right;
    gl_Position = mvp*vec4(pos,1.0);
    texCoord = vec2(1,0);
    EmitVertex();

    pos.y += 1.0;       
    gl_Position = mvp*vec4(pos,1.0);
    texCoord = vec2(1,1);
    EmitVertex();
}

编辑:正如我之前所说,我已经试过3,3-子矩阵设置身份的方法。 我可能解释的行为不对,但这种GIF应该做的更好:

在上面的照片时,相机与使用身份子矩阵的方法的广告牌(红色)旋转。 该广告牌,但是,不应该通过表面(白色)移动,应该保持它的位置正确,永远是在表面上,这不会发生的一侧。

Answer 1:

创建广告牌的选择是抛出几何着色器,距离手工做这样的:

Vector3 DiffCamera = Billboard.position - Camera.position;
Vector3 UpVector   = new Vector3(0.0f, 1.0f, 0.0f);

Vector3 CrossA     = DiffCamera.cross(UpVector).normalize(); // (Step A)
Vector3 CrossB     = DiffCamera.cross(CrossA).normalize();   // (Step B)

// now you can use CrossA and CrossB and the billboard position to calculate the positions of the edges of the billboard-rectangle

// like this
Vector3 Pos1 = Billboard.position + CrossA + CrossB;
Vector3 Pos2 = Billboard.position - CrossA + CrossB;
Vector3 Pos3 = Billboard.position + CrossA - CrossB;
Vector3 Pos4 = Billboard.position - CrossA - CrossB;

我们在步骤A中计算出的交叉乘积,因为我们希望广告牌的水平排列方向。

在步骤B,我们这样做的垂直方向。

对于场景中的每个billbaord做到这一点。

或几何着色器(只是一种尝试)更好

vec3 pos = gl_in[0].gl_Position.xyz;
pos /= gl_in[0].gl_Position.w; //normalized device coordinates
vec3 toCamera = normalize(cameraPos - pos);
vec3 up = vec3(0,1,0);
vec3 CrossA = normalize(cross(up, toCamera));
vec3 CrossB = normalize(cross(CrossA, toCamera));

// set coordinates of the 4 points


Answer 2:

只是重置模型视图矩阵身份的左上角3×3子部分,留下第4列和行,因为它是,即:

1 0 0 …
0 1 0 …
0 0 1 …
… … … …

下面的广告牌UPDATE世界空间轴

关键洞察高效地实现对准广告牌是为了实现他们的视觉空间是如何工作的。 通过定义在视觉空间广告牌的法向矢量是Z =(0,0,1)。 这样,只有一个自由参数,围绕该轴线的广告牌即旋转。 在视图对准的广告牌广告牌向右和向上的轴仅被迫成为视图X和Y这就是设定模型视图矩阵确实左上方的3×3的。

现在,当我们想要的广告牌对齐到场景中的某个轴仍然面对观众,我们可以改变的唯一参数是广告牌旋转。 为此,我们做到以下几点:

在世界空间中,我们选择一个轴应该是广告牌的上轴。 请注意,如果视轴平行于广告牌向上轴线以下步骤成为单数,即广告牌的转动是未定义的。 你必须以某种方式来解决这个问题,那我离开这里未定义。

这选定轴我们带入视野空间。 现在,一个轴是同一种东西像一个正常的,即一个方向,所以我们把它以同样的方式,因为我们做与法线。 我们通过模型视图矩阵,你与法线的逆变换转它; 注意,由于我们定义在世界空间轴,我们需要实际使用的世界反置查看转换矩阵即可。

广告牌的转化的长轴现在处于视觉空间。 下一步骤是将其正交于观察方向。 为此,您使用格拉姆 - 施密特方法。 现在我们得到了Z和广告牌的Y列变换。 依然是X列,这是我们通过采取Z的积与Y列中获取。



Answer 3:

如果有人想知道我是如何解决这个。
我有我的基础上Quonux的答案的解决方案,它唯一的问题是,当相机处于正上方的广告牌会非常快的旋转(当up向量几乎平行于摄像机的注视向量)。 这种奇怪的行为是使用交叉产品,找到的结果right向量:当相机悬停在广告牌的顶部,叉积改变它的标志,也是如此的right矢量的方向。 这解释了出现这种情况的旋转。
因此,所有我需要的是找到一个right使用一些其他的方式载体。 因为我知道相机的旋转角度(水平和垂直),我决定用它来找到一个right载体:

rotatedRight = Vector4.Transform(unRotatedRight, Matrix4.CreateRotationY((-alpha)));

和几何着色器:

...
uniform vec3 rotRight;
uniform vec3 cameraPos;

out vec2 texCoord;

void main(){

vec3 pos = gl_in[0].gl_Position.xyz;
pos /= gl_in[0].gl_Position.w; //normalized device coordinates
vec3 toCamera = normalize(cameraPos - pos);

vec3 CrossA = rotRight;
... (Continues as Quonux's code)


文章来源: How to make a billboard spherical