顶点着色器不适用于克隆对象

时间:2018-11-10 18:45:51

标签: opengl glsl vertex-shader opengl-3

我正在使用OpenGL创建一个球体(近似值):

我正在“扩大”三角形以创建一个八个球体:

enter image description here

enter image description here

然后我要绘制该八分圆图四次,每次将模型变换的角度旋转90°,以实现半球:

enter image description here

与图形调用有关的代码:

for (int i = 0; i < 4; i++) {
    model_trans = glm::rotate(model_trans, glm::radians(i * 90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(model_trans));
    glDrawElementsBaseVertex(GL_TRIANGLES, sizeof(sphere_indices) / sizeof(sphere_indices[0]),
                             GL_UNSIGNED_INT, 0, (sizeof(grid_vertices)) / (ATTR_COUNT * sizeof(GLfloat)));
}

我的目标是根据每个顶点在XY平面上的投影角度为每个顶点着色。由于我正在对值进行归一化,因此得到的投影的行为应类似于三角圆,x值是与x轴正端的角度的余弦值。而且因为余弦是一个连续函数,所以我的球面也应该具有连续的颜色。但是,事实并非如此:

enter image description here

此问题是由克隆对象引起的吗?这是我唯一能想到的,但不要紧,因为顶点着色器仅接收单独的顶点。说到这,这是我的顶点着色器:

#version 150 core

in vec3 position;
/* flat : the color will be sourced from the provoking vertex. */
flat out vec3 Color;

/* transformation matrices */
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {

    gl_Position = projection * view * model * vec4(position, 1.0);

    vec3 vector_proj = vec3(position.x, position.y, 0.0);
    normalize(vector_proj);
    /* Addition and division only for mapping range [-1, +1] to [0, 1] */
    float cosine = (vector_proj.x + 1) / 2;
    Color = vec3(cosine);
}

1 个答案:

答案 0 :(得分:1)

您要根据顶点位置的世界坐标来计算与顶点关联的颜色。

position是模型坐标,而不是世界坐标。在计算position之前,必须将模型矩阵应用于vector_proj才能从模型空间转换为世界空间:

vec4 world_pos = model * vec4(position, 1.0);

vec3 vector_proj = vec3( world_pos.xy, 0.0 );

normalize的参数不是输入输出参数。它是一个输入参数,归一化结果从函数返回:

vector_proj = normalize(vector_proj);    

您可以简化代码,如下所示:

void main()
{
    vec4 world_pos = model * vec4(position, 1.0);
    gl_Position = projection * view * world_pos;

    vec2 vector_proj = normalize(world_pos.xy);

    /* Addition and division only for mapping range [-1, +1] to [0, 1] */
    float cosine = (vector_proj.x + 1) / 2;
    Color = vec3(cosine);
}