2015-10-04 170 views
1

如何在片段着色器中使用不同的颜色输出?Qt/OpenGL着色器问题

说,我vshader看起来是这样的:

#version 330 

uniform mat4 mvpmatrix; 

layout(location=0) in vec4 position; 
layout(location=1) in vec2 texcoord; 

out vec2 out_texcoord; 

void main() 
{ 

    gl_Position = mvpmatrix * position;  

    out_texcoord = texcoord; 
} 

// fshader

#version 330 

uniform sampler2D texture; 
in vec2 out_texcoord; 
out vec4 out_color; 
out vec4 out_color2; 

void main() 
{   
    out_color = texture2D(texture, out_texcoord); 
    // out_color2 = vec3(1.0, 1.0, 1.0, 1.0); 
} 

访问他们像这样:

m_program->enableAttributeArray(0); // position 
m_program->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Data)); 

m_program->enableAttributeArray(1); // texture 
m_program->setAttributeBuffer(1, GL_FLOAT, sizeof(QVector3D), 2, sizeof(Data)); 

到目前为止,一切使用的默认输出片段着色器,这是一个纹理。但是如何访问不同的片段输出?我也必须使用布局吗?而且,它可能是一个愚蠢的问题......但是vshader/fshader的布局位置是相互绑定的吗?所以,如果我在AttributeArray(1)上启用我的缓冲区,我不得不使用两个着色器的布局位置1?

回答

2

可以绑定其他属性位置的色彩信息发送到您的片段着色器的任何时间,但让我告诉你一个诀窍:)

我用2属性的位置,一个代表顶点和其他的位置一个来表示顶点的颜色。

glBindAttribLocation(program_, 0, "vs_in_pos"); 
glBindAttribLocation(program_, 1, "vs_in_col"); 

这是我网的定义,其中顶点包含两个三维矢量:

Vertex vertices[] = { 
     {glm::vec3(-1, -1, 1), glm::vec3(1, 0, 0)}, 
     {glm::vec3(1, -1, 1), glm::vec3(1, 0, 0)}, 
     {glm::vec3(-1, 1, 1), glm::vec3(1, 0, 0)}, 
     {glm::vec3(1, 1, 1), glm::vec3(1, 0, 0)}, 
     {glm::vec3(-1, -1, -1), glm::vec3(0, 1, 0)}, 
     {glm::vec3(1, -1, -1), glm::vec3(0, 1, 0)}, 
     {glm::vec3(-1, 1, -1), glm::vec3(0, 1, 0)}, 
     {glm::vec3(1, 1, -1), glm::vec3(0, 1, 0)}, 
    }; 
    GLushort indices[] = { 
     // Front 
     0, 1, 2, 2, 1, 3, 
     // Back 
     4, 6, 5, 6, 7, 5, 
     // Top 
     2, 3, 7, 2, 7, 6, 
     // Bottom 
     0, 5, 1, 0, 4, 5, 
     // Left 
     0, 2, 4, 4, 2, 6, 
     // Right 
     1, 5, 3, 5, 7, 3 
    }; 

这将是一个立方体。我会将这个预定义的颜色与计算值混合使用。这意味着立方体的颜色会因其位置而改变。设置为RGB值的三维矢量和设置使用它在片段着色器:

loc_col_ = glGetUniformLocation(program_, "color"); 

现在在我的渲染功能,我把立方体在2D圈,移动它们,使它们旋转:

for (int i = 0; i < num_of_cubes_; ++i) { 
     double fi = 2 * PI * (i/(double) num_of_cubes_); 
     glm::mat4 position = glm::translate<float>(cubes_radius_ * cos(fi), cubes_radius_ * sin(fi), 0); 
     glm::mat4 crackle = glm::translate<float>(0, 0.1 * (sin(2 * PI * (SDL_GetTicks()/500.0) + i)), 0); 
     glm::mat4 rotate = glm::rotate<float>(360 * (SDL_GetTicks()/16000.0), 0, 0, 1); 
     world_ = position * crackle * rotate; 
     glm::vec3 color = glm::vec3((1 + cos(fi)) * 0.5, (1 + sin(fi)) * 0.5, 1 - ((1 + cos(fi)) * 0.5)); 
     glUniformMatrix4fv(loc_world_, 1, GL_FALSE, &(world_[0][0])); 
     glUniform3fv(loc_col_, 1, &(color[0])); 
     glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); 
    } 

你可以在这里看到我不仅发送世界矩阵,还发送颜色矢量。在片段着色器 线性插补是通过混合()函数achived:

#version 130 

in vec3 vs_out_col; 
in vec3 vs_out_pos; 
out vec4 fs_out_col; 

uniform vec3 color; 

void main() { 
     fs_out_col = vec4(mix(color, vs_out_col, 0.5), 1); 
} 

颜色是在所传递的值呈现而vs_out_col从将其在“信道” 1

到达那里的顶点着色器来

我希望你能理解我。

+0

Okey ...我已经过了,感谢分享! – danksch

1

顶点和片段着色器上的布局位置是独立的。 QT可能会误导enableAttributeArray,因为在OpenGL中,此函数被称为glEnableVertexAttribArray - 顶点是此处的关键字。因此,您可以将每个顶点数据仅传递到顶点着色器,然后使用输入/输出(插值)将其传递到片段着色器中。

如果你想使用片段着色器的多个输出,你必须使用位置和Output buffers

This链接也应该是有帮助的,我会在稍后总结。

+0

好的,谢谢你的提示! – danksch