View OpengGL ES 2.0公告牌:这个数学怎么了?

View OpengGL ES 2.0公告牌:这个数学怎么了?,view,opengl-es-2.0,projection,View,Opengl Es 2.0,Projection,下面粘贴的是我在网上发现的两种方法的伪代码,它们可以为场景中的3d对象生成公告牌变换矩阵。编辑:请注意,这是针对一个可能有4个以上顶点的对象-我正在尝试计算3d对象的完整公告牌变换矩阵,而不是面向摄影机公告牌的单个四边形 此变换旨在使广告牌上的对象朝向摄影机,同时保持直立 这两种方法都不起作用,在大多数情况下,我的场景中没有显示任何内容,即坐标已变换到视图之外 有人能确定着色器代码行中的计算或矩阵乘法顺序是否存在缺陷吗?我非常感谢你的建议 // Vectors: // // bbPos B

下面粘贴的是我在网上发现的两种方法的伪代码,它们可以为场景中的3d对象生成公告牌变换矩阵。编辑:请注意,这是针对一个可能有4个以上顶点的对象-我正在尝试计算3d对象的完整公告牌变换矩阵,而不是面向摄影机公告牌的单个四边形

此变换旨在使广告牌上的对象朝向摄影机,同时保持直立

这两种方法都不起作用,在大多数情况下,我的场景中没有显示任何内容,即坐标已变换到视图之外

有人能确定着色器代码行中的计算或矩阵乘法顺序是否存在缺陷吗?我非常感谢你的建议

// Vectors:
//
// bbPos    Billboard position.
// bbUp     Billboard up vector.
// bbRight  Billboard right vector.
//
// camPos   Camera position.
// camUp    Camera up vector.
// camRight Camera right vector.

// Approach 1:
vec3 bbLook = bbPos - camPos;
bbLook.normalize();

vec3 bbRight = cross(camUp, bbLook);
bbRight.normalize();

vec3 bbUp = cross(bbLook, bbRight);
bbUp.normalize();

mx4 a_billboard = (     bbRight.x,  bbRight.y,  bbRight.z,  0.0f,
                bbUp.x,     bbUp.y,     bbUp.z,     0.0f,
                bbLook.x,   bbLook.y,   bbLook.z,   0.0f,
                bbPos.x,    bbPos.y,    bbPos.z,    1.0f);

// Approach 2:
vec3 bbLook = camPos - bbPos;
bbLook.normalize();

vec3 bbRight = cross(camUp, bbLook);
bbRight.normalize();

vec3 bbUp = cross(bbLook, bbRight);
bbUp.normalize();

mx4 a_billboard = ( bbRight.x,  bbUp.x,     bbLook.x,   bbPos.x,
            bbRight.y,  bbUp.y,     bbLook.y,   bbPos.y,
            bbRight.z,  bbUp.z,     bbLook.z,   bbPos.z,
            0.0f,       0.0f,       0.0f,       1.0f);
在顶点着色器中,以下代码组合了投影、wvview*世界、模型和公告牌矩阵:

    gl_Position = p * a_billboard * wv * m * vec4(a_position.xyz, 1.0);

干杯,第一个缺陷是修改了bbUp向量。如果你改变它,它需要保持固定,你希望它如何保持直立?。您可以使用:

vec3 bbUp = vec3(0, 1, 0); // up
以及:

或:

在这两种情况下,bbLook向量都需要重新计算为bbUp和bbRight的叉积。这就是你数学的问题所在

另一个错误是,使用矩阵渲染广告牌是无效的,因为每个广告牌都需要一个这样的矩阵。最好将广告牌中心位置存储在顶点属性数组中,并使用纹理坐标计算广告牌顶点,这意味着广告牌中心位置使用不同的texcoords重复4次。例如:

float[] billboard = {x, y, z, 0, 0, x, y, z, 1, 0, x, y, z, 1, 1, x, y, z, 0, 1};
这使您能够使用顶点着色器一次绘制多个广告牌,例如:

attribute vec3 vCenter;
attribute vec2 texCoord;

uniform matrix4 mvp;

uniform vec3 bbUp, bbRight;

varying vec2 texCoordOut;

void main()
{
    vec3 corner = vCenter + (texCoord.x - .5) * 2.0 * bbRight +
                            (texCoord.y - .5) * 2.0 * bbUp;
    // this calculates corner position (texcoords need to be rescaled from [0 1] to [-1 1])

    gl_Position = mvp * corner;
    texCoordOut = texCoord;
    // write position, texcoords
}

这使得使用相同的上方向向量和右方向向量渲染多个广告牌成为可能。但是,您可以将上方向向量作为另一个顶点属性提供,以便每个广告牌都有自己的轴。您可以在这里查看一个小演示:

谢谢您的回复,我希望您能澄清一下。首先,您是否知道在vec3 bbUp=..之前我没有bbUp值。。。。线你建议我用bbUp x bbRight来计算bbLook,但实际上,既然我必须先计算bbLook,我就用bbLook x bbRight来代替。其次,您展示的纹理示例仅适用于我相信的4点广告牌,即四边形。这不是我想要达到的;我有一个完整的3d对象,我想面对摄像机,它由4个以上的顶点组成。首先,bbUp=vec30,1,0,你有了它。第二,你是对的,你可以通过广告牌和摄像机的位置差来计算bbLook。我的建议是,在计算bbRight之后,使用叉积更新bbLook。这是完全正确的。第三,哦,是的,一个物体。想想看,你需要的矩阵是一个简单的观察矩阵,位置是布告牌的位置,目标是摄像机的位置,上方向向量是你希望布告牌向上的方向,可以是0,1,0表示向上,也可以是camera.up表示屏幕空间向上。查一查……谢谢你的提示,我今晚会调查的。将这个新矩阵标记为“M_BB”,这是否意味着我需要我的着色器来进行世界视图投影计算:p*v*w*M_BB或p*v*M_BB*w?这应该是p*v*M_BB*w,其中v是视图,w是世界。运算符的关联性应该起作用,因此不需要括号。如果有任何问题,我建议尝试使用w作为单位矩阵。
float[] billboard = {x, y, z, 0, 0, x, y, z, 1, 0, x, y, z, 1, 1, x, y, z, 0, 1};
attribute vec3 vCenter;
attribute vec2 texCoord;

uniform matrix4 mvp;

uniform vec3 bbUp, bbRight;

varying vec2 texCoordOut;

void main()
{
    vec3 corner = vCenter + (texCoord.x - .5) * 2.0 * bbRight +
                            (texCoord.y - .5) * 2.0 * bbUp;
    // this calculates corner position (texcoords need to be rescaled from [0 1] to [-1 1])

    gl_Position = mvp * corner;
    texCoordOut = texCoord;
    // write position, texcoords
}