我对OpenGL和3D图形一般都是新手,这是我第一次远离教程自己做点什么。我想创建广告牌纹理,以便这些纹理始终面向相机。 (我打算将它们用作光源的位置指示器等。)
经过一番研究,我发现这个网站为我的问题提供了一个相当简单的解决方案。
我按照他们的步骤,一切都按预期工作,除了一件事。我的缩放参数被忽略,我用来绘制纹理的四边形没有被缩放。
这是我非常简单的着色器代码。
#version 400 core
in vec3 position;
in vec2 textureCoordinates;
out vec2 pass_textureCoordinates;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
void main(void){
mat4 modelView = viewMatrix * transformationMatrix;
modelView[0][0] = 1;
modelView[0][1] = 0;
modelView[0][2] = 0;
modelView[1][0] = 0;
modelView[1][1] = 1;
modelView[1][2] = 0;
modelView[2][0] = 0;
modelView[2][1] = 0;
modelView[2][2] = 1;
gl_Position = projectionMatrix * modelView * vec4(position,1.0);
pass_textureCoordinates = textureCoordinates;
}
这是生成我的vieMatrix和transformationMatrix
的代码 public static Matrix4f createTransformationMatrix(BillboardEntity billboardEntity) {
Vector3f translation = billboardEntity.getTranslation();
float rx = billboardEntity.getRotationX();
float ry = billboardEntity.getRotationY();
float rz = billboardEntity.getRotationZ();
float scale = billboardEntity.getScale();
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
Matrix4f.translate(translation, matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(ry), new Vector3f(0,1,0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(rz), new Vector3f(0,0,1), matrix, matrix);
Matrix4f.scale(new Vector3f(scale, scale, scale), matrix, matrix);
return matrix;
}
public static Matrix4f createViewMatrix(Camera camera) {
Matrix4f viewMatrix = new Matrix4f();
viewMatrix.setIdentity();
Matrix4f.rotate((float) Math.toRadians(camera.getPitch()), new Vector3f(1, 0, 0), viewMatrix,
viewMatrix);
Matrix4f.rotate((float) Math.toRadians(camera.getYaw()), new Vector3f(0, 1, 0), viewMatrix,
viewMatrix);
Vector3f cameraPos = camera.getPosition();
Vector3f negativeCameraPos = new Vector3f(-cameraPos.x, -cameraPos.y, -cameraPos.z);
Matrix4f.translate(negativeCameraPos, viewMatrix, viewMatrix);
return viewMatrix;
}
我应该提一下,我在我的项目中使用Java和LWJGL。知道为何忽略规模吗?另外,这是制作广告牌纹理的好方法吗?
答案 0 :(得分:0)
我在 Google 上找到了这篇文章,所以我想分享我的解决方案(如果你不介意的话)。
如果您将 4x4 变换矩阵的左上角 3x3 部分设置为“恒等”矩阵(对角线上的所有“1”),您会核对旋转和缩放,因为它们都被存储
要修复它,在此特定示例中,您可以使用:
void main(){
mat4 modelView = viewMatrix * transformationMatrix;
modelView[0][0] = length(vec3(transformationMatrix[0]));
modelView[0][1] = 0;
modelView[0][2] = 0;
modelView[1][0] = 0;
modelView[1][1] = length(vec3(transformationMatrix[1]));
modelView[1][2] = 0;
modelView[2][0] = 0;
modelView[2][1] = 0;
modelView[2][2] = 1;
gl_Position = projectionMatrix * modelView * vec4(position,1.0);
pass_textureCoordinates = textureCoordinates;
}
它将保留来自变换(或model
)矩阵的缩放信息。我对其进行了测试,它适用于 CPU 端的任何比例设置(在 .cpp 中)。
但是,您应该知道 length
通常是一个昂贵的过程。例如,在 GLM 中,它使用 sqrt(dot(v, v))
,如果您不知道,sqrt
非常昂贵,特别是如果您希望场景中有许多广告牌(草、云、粒子等)。因此,您可以做的是使用处理缩放的制服,这要便宜得多:
uniform bool uIsSpherical;
uniform vec2 uSpriteScale; // Using a uniform instead
void main(){
...
modelView[0][0] = uSpriteScale.x;
modelView[0][1] = 0;
modelView[0][2] = 0;
if (uIsSpherical)
{
modelView[1][0] = 0;
modelView[1][1] = uSpriteScale.y;
modelView[1][2] = 0;
}
else
{
modelView[1][1] *= uSpriteScale.y;
}
modelView[2][0] = 0;
modelView[2][1] = 0;
modelView[2][2] = 1;
...
}
第二列 (if
) 的 modelView[1][...]
条件是针对圆柱形广告牌,适用于远处的树木或其他类型的冒名顶替者,因为您不希望它们向后倾斜如果你从上面看到它们,比如从飞机上或其他东西。
现在,在着色器中制作广告牌的问题在于,在 CPU 端,在阴影渲染过程中,您仍在使用固定的变换矩阵。所以阴影不会跟随旋转的四边形,它仍然会“看到”它是静止的。有人告诉我,对此的“解决方案”是使用阴影广告牌着色器,并在那里进行相同的计算。显然,存储或缓存结果是不值得的,因为 GPU 再次执行相同的操作比执行内存提取要快得多,因为内存针对吞吐量而不是延迟进行了优化。但我还没有测试它。请记住,默认情况下,阴影不会随着广告牌旋转。