使用 GLSL 直接在着色器中从位置计算平移矩阵
Compute translation mattrix from position directly in shader with GLSL
我正在研究 C++ OpengL 程序和 GLSL 顶点和片段着色器。
我正在创建同一对象的多个实例。我只需要在实例之间更改对象位置。
这是我所做的:我正在使用一个统一变量,它是一个变换矩阵数组。每个矩阵代表一个对象实例。
MVP 也是一个变换矩阵,但 MVP 由相机位置、方向和属性设置。
这是我的顶点着色器:
#version 330 core
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
uniform mat4 object_positions[20];
out vec3 fragment_color;
uniform mat4 MVP;
void main()
{
gl_Position = object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0);
fragment_color = vertex_color;
}
这是我在 C++ 程序中设置对象位置所要做的:
glm::mat4 object_positions[20];
object_positions[0] = glm::translate(glm::mat4(1), glm::vec3(0.4f,0.2f,0.0f));
object_positions[1] = glm::translate(glm::mat4(1), glm::vec3(0.5f,1.4f,0.0f));
...
object_positions[19] = glm::translate(glm::mat4(1), glm::vec3(-10.6f,0.2f,0.0f));
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions");
...
glUniformMatrix4fv(object_positions_id, 7, GL_FALSE, glm::value_ptr(object_positions[0]));
您看到的作为 glm::translate 第二个参数的 vec3 包含每个对象位置。
此时一切正常。
我想做的是在着色器中计算 glm::translte。事实上,我想要的是为每个位置发送一个 vec3 而不是 mat4。我希望 GPU 计算变换矩阵而不是 CPU。我尝试的所有方法都不起作用。
谢谢
对于 OpenGL 变换矩阵只是 16 个条目的一维数组(说到 4X4 矩阵)。在此矩阵中,第 13、14、15 个条目定义了您的翻译组件。因此,如果您以行主要形式存储矩阵,第 4 行第 0、1 和 2 项应该是您发送到着色器的向量 x、y、z 分量。您可以通过这种方式在着色器中构建平移矩阵。请确定如果你有行主矩阵然后转换顶点你预乘矩阵以查看转换效果。
gl_Position = Translation Matrix * gl_Vertex;
如果您的矩阵是列主矩阵,您将 post 相乘。
一个 4*4 矩阵如下所示:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 0 4 8 12 ]
[ Xy Yy Zy Ty ] [ 1 5 9 13 ]
[ Xz Yz Zz Tz ] [ 2 6 10 14 ]
[ 0 0 0 1 ] [ 3 7 11 15 ]
在 GLSL 中,mat4 m;
的列地址如下:
vec4 c0 = m[0].xyzw;
vec4 c1 = m[1].xyzw;
vec4 c2 = m[2].xyzw;
vec4 c3 = m[3].xyzw;
你可以像这样在顶点着色器中设置一个mat4
:
#version 330 core
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
out vec3 fragment_color;
uniform mat4 MVP;
uniform vec3 object_positions[20];
void main()
{
mat4 posMat = mat4(
vec4( 1.0, 0.0, 0.0, 0.0),
vec4( 0.0, 1.0, 0.0, 0.0),
vec4( 0.0, 0.0, 1.0, 0.0),
vec4( object_positions[gl_InstanceID], 1.0) );
gl_Position = MVP * posMat * vec4(vertex_position,1.0);
fragment_color = vertex_color;
}
但是如果你只想通过一个offset来操纵顶点位置,那么你不需要转换矩阵。您可以简单地将 offset 添加到顶点位置(前提是 offset 是笛卡尔坐标而不是齐次坐标,如您的情况):
void main()
{
gl_Position = MVP * vec4(object_positions[gl_InstanceID] + vertex_position, 1.0);
fragment_color = vertex_color;
}
你必须像这样设置制服:
glm::vec3 object_positions[20];
object_positions[0] = glm::vec3(0.4f,0.2f,0.0f);
object_positions[1] = glm::vec3(0.5f,1.4f,0.0f);
...
object_positions[19] = glm::vec3(-10.6f,0.2f,0.0f);
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions");
...
glUniform3fv(object_positions_id, 20, glm::value_ptr(object_positions[0]));
进一步查看:
你绝对不能做 object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0);
(即使 object_positions 是矩阵),因为那会在应用投影矩阵之后进行平移。
如果您不对实例进行任何轮换,则没有理由不这样做
gl_Position = MVP * vec4(vertex_position + object_positions[gl_InstanceID],1.0);
我正在研究 C++ OpengL 程序和 GLSL 顶点和片段着色器。
我正在创建同一对象的多个实例。我只需要在实例之间更改对象位置。
这是我所做的:我正在使用一个统一变量,它是一个变换矩阵数组。每个矩阵代表一个对象实例。
MVP 也是一个变换矩阵,但 MVP 由相机位置、方向和属性设置。
这是我的顶点着色器:
#version 330 core
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
uniform mat4 object_positions[20];
out vec3 fragment_color;
uniform mat4 MVP;
void main()
{
gl_Position = object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0);
fragment_color = vertex_color;
}
这是我在 C++ 程序中设置对象位置所要做的:
glm::mat4 object_positions[20];
object_positions[0] = glm::translate(glm::mat4(1), glm::vec3(0.4f,0.2f,0.0f));
object_positions[1] = glm::translate(glm::mat4(1), glm::vec3(0.5f,1.4f,0.0f));
...
object_positions[19] = glm::translate(glm::mat4(1), glm::vec3(-10.6f,0.2f,0.0f));
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions");
...
glUniformMatrix4fv(object_positions_id, 7, GL_FALSE, glm::value_ptr(object_positions[0]));
您看到的作为 glm::translate 第二个参数的 vec3 包含每个对象位置。 此时一切正常。
我想做的是在着色器中计算 glm::translte。事实上,我想要的是为每个位置发送一个 vec3 而不是 mat4。我希望 GPU 计算变换矩阵而不是 CPU。我尝试的所有方法都不起作用。
谢谢
对于 OpenGL 变换矩阵只是 16 个条目的一维数组(说到 4X4 矩阵)。在此矩阵中,第 13、14、15 个条目定义了您的翻译组件。因此,如果您以行主要形式存储矩阵,第 4 行第 0、1 和 2 项应该是您发送到着色器的向量 x、y、z 分量。您可以通过这种方式在着色器中构建平移矩阵。请确定如果你有行主矩阵然后转换顶点你预乘矩阵以查看转换效果。
gl_Position = Translation Matrix * gl_Vertex;
如果您的矩阵是列主矩阵,您将 post 相乘。
一个 4*4 矩阵如下所示:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 0 4 8 12 ]
[ Xy Yy Zy Ty ] [ 1 5 9 13 ]
[ Xz Yz Zz Tz ] [ 2 6 10 14 ]
[ 0 0 0 1 ] [ 3 7 11 15 ]
在 GLSL 中,mat4 m;
的列地址如下:
vec4 c0 = m[0].xyzw;
vec4 c1 = m[1].xyzw;
vec4 c2 = m[2].xyzw;
vec4 c3 = m[3].xyzw;
你可以像这样在顶点着色器中设置一个mat4
:
#version 330 core
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
out vec3 fragment_color;
uniform mat4 MVP;
uniform vec3 object_positions[20];
void main()
{
mat4 posMat = mat4(
vec4( 1.0, 0.0, 0.0, 0.0),
vec4( 0.0, 1.0, 0.0, 0.0),
vec4( 0.0, 0.0, 1.0, 0.0),
vec4( object_positions[gl_InstanceID], 1.0) );
gl_Position = MVP * posMat * vec4(vertex_position,1.0);
fragment_color = vertex_color;
}
但是如果你只想通过一个offset来操纵顶点位置,那么你不需要转换矩阵。您可以简单地将 offset 添加到顶点位置(前提是 offset 是笛卡尔坐标而不是齐次坐标,如您的情况):
void main()
{
gl_Position = MVP * vec4(object_positions[gl_InstanceID] + vertex_position, 1.0);
fragment_color = vertex_color;
}
你必须像这样设置制服:
glm::vec3 object_positions[20];
object_positions[0] = glm::vec3(0.4f,0.2f,0.0f);
object_positions[1] = glm::vec3(0.5f,1.4f,0.0f);
...
object_positions[19] = glm::vec3(-10.6f,0.2f,0.0f);
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions");
...
glUniform3fv(object_positions_id, 20, glm::value_ptr(object_positions[0]));
进一步查看:
你绝对不能做 object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0);
(即使 object_positions 是矩阵),因为那会在应用投影矩阵之后进行平移。
如果您不对实例进行任何轮换,则没有理由不这样做
gl_Position = MVP * vec4(vertex_position + object_positions[gl_InstanceID],1.0);