2017-10-16 86 views
1

我在C++ OpengL程序和GLSL顶点和片段着色器上工作。从GLSL着色器直接位置计算转换mattrix

我正在创建同一个对象的几个实例。我只需要改变实例之间的对象位置。

这是我所做的:我正在使用一个统一的变量,这是一个变换矩阵的数组。每个矩阵代表一个对象实例。

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的第二个参数的VEC 3 :: translate包含每个对象的位置。 在这一点上,每件事情都很好。

我想要做的是在着色器中计算glm :: translte。我其实想要的是发送一个vec3而不是每个位置的mat4。我希望GPU能够计算转换矩阵而不是CPU。我试过的所有东西都不起作用。

由于

+0

不,它不工作。这是完全一样的结果。 object_positions在这种情况下应该是一个转换矩阵,而不是一个位置 – Bob5421

+1

为什么只需要添加偏移量时需要一个矩阵更简单快捷? –

+0

是的,这是一个好主意,但我应该把什么w? – Bob5421

回答

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); 
1

对于OpenGL的变换矩阵仅仅是一个16个条目(4X4矩阵说起)的二维阵列。在这个矩阵中,第13,14,15条定义了你的翻译组件。因此,如果要将矩阵存储在第4行第0行的主行中,则第1条和第2条应该是要发送到着色器的向量x,y,z分量。您可以用这种方式在着色器中构建翻译矩阵。请确定如果你有行主矩阵,然后转换您预先乘以矩阵的顶点以查看翻译的效果。

gl_Position = Translation Matrix * gl_Vertex; 

如果您的矩阵是列主要,您将张贴乘法。

3

一个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; 
} 


但是,如果您只想通过偏移量操作顶点位置,则不需要转换矩阵。你可以简单地添加偏移到顶点位置(提供的偏移是一个直角坐标,而不是齐次坐标,如你的情况):

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])); 


进一步参见:

+1

不等于'vec4(object_position [gl_InstanceID] + vertex_position,1.0)'posMat * vec4(vertex_position,1.0)'? – Jherico