将顶点着色器中的浮点数组传递给glsl 3.3中的片段着色器

时间:2014-04-30 22:40:49

标签: opengl glsl shader

我想传递

out float texture_contribs[16]

使用glsl 3.3从顶点着色器到frament着色器

然而,无论顶点着色器中的值如何,框架着色器中的值始终为0.0。

这是我的顶点着色器代码:

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 normalMatrix;

layout(location = 0) in vec4 in_position;
layout(location = 1) in vec4 in_colour;
layout(location = 2) in vec2 in_coord;
layout(location = 3) in vec3 in_normal;
layout(location = 4) in float texture_contributions[16];

out vec2 texcoord;
out vec4 pass_colour;
out float texture_contribs[16];

smooth out vec3 vNormal;

void main()
{
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_position;
    texcoord = in_coord;
    vec4 vRes = normalMatrix*vec4(in_normal, 0.0); 
    vNormal = vRes.xyz;
    pass_colour = in_colour;
    for (int i = 0; i < 16; i++)
    {
        texture_contribs[i] = texture_contributions[i];
    }
}

这里是片段着色器代码:

uniform sampler2D texture[16];

in vec2 texcoord;
in vec4 pass_colour;
in float texture_contribs[16];

smooth in vec3 vNormal;

out vec4 out_colour;

struct SimpleDirectionalLight
{
   vec3 vColor;
   vec3 vDirection;
   float fAmbientIntensity;
};

uniform SimpleDirectionalLight sunLight;

void main()
{
    vec4 vTexColor = texture2D(texture[2], texcoord) * texture_contribs[2] + texture2D(texture[3], texcoord) * texture_contribs[3];
    if(vTexColor.a < 0.1)
        discard;
    float fDiffuseIntensity = max(0.0, dot(normalize(vNormal), -sunLight.vDirection));
    out_colour = vTexColor*pass_colour*vec4(sunLight.vColor*(sunLight.fAmbientIntensity+fDiffuseIntensity), 1.0);
}

我尝试将数组拆分为单个变量并单独传递它们的值,它们的值仍然会在片段着色器中消失。

1 个答案:

答案 0 :(得分:5)

OpenGL 3.3至少需要16个顶点属性位置。

顶点属性限制 (由GLSL定义):

const int gl_MaxVertexAttribs = 16; // Minimum: 16 Vertex Attribute Slots

顶点属性限制 (在OpenGL中查询):

GLuint max_vtx_attribs;
glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &max_vtx_attribs);

AMD是我所知道的唯一提供超过16个属性的供应商(它们在某些驱动程序/硬件组合上提供29-32)。 Intel,Apple,NVIDIA和Mesa都给你16.如果你想编写可移植代码,你应该尝试定位不超过16个顶点属性。否则,您必须为不同的供应商编写不同的代码路径,这并不好玩。

实际应用程序的要求并不多,每个顶点属性超过16个,而且通常依赖于更适合存储大量数据的东西,例如纹理/着色器存储缓冲区对象。


您的GLSL顶点着色器的处理方式与当前编写的方式相混淆。

  

OpenGL 3.3 Core Profile Specification - 2.7顶点规范 - 第26页

     
    

顶点着色器(请参阅部分 2.11 )访问 4分量通用顶点属性 的数组。该数组的第一个插槽编号为 0 ,数组的大小由依赖于实现的常量GL_MAX_VERTEX_ATTRIBS指定。

  

GLSL 3.3中的每个顶点属性位置都能够存储单个vec4,大于vec4例如 mat4)的数据类型将跨越多个地点。小于vec4的数据类型占用整个位置,这是着色器开始遇到问题的地方。您已经声明了一个16元素的标量数组,每个标量都有自己的顺序位置,从 4 开始。这意味着阵列占据 4 - 19 的位置,但大多数实施都没有 20 位置可以分发。

  

OpenGL 3.3 Core Profile Specification - 2.11.3顶点属性 - 第55页

     
    

如果通用属性变量由编译器和链接器确定在执行着色器时可以访问该属性,则该属性变量被认为是活动的。在顶点着色器中声明但从未使用过的属性变量不会计入限制。如果编译器和链接器无法做出确定的确定,则属性将被视为活动。 如果活动顶点属性的数量超过GL_MAX_VERTEX_ATTRIBS,程序对象将无法链接。

  

前4个顶点属性( 0 - 3 )处于活动状态,标量数组创建的16个属性也是如此。您的GLSL程序(应该)无法链接任何不提供至少20个顶点属性的实现。如果没有,那么您就有了不合规的实现。


这里的问题是你的每个标量都浪费了3个组件的存储空间。

您实际上不需要使用16个属性槽来存储所有每个顶点数据。如果将float的这个16元素数组替换为vec4或单个mat4的4元素数组,则只需使用4个属性插槽即可存储相同数量的数据。

然后您的存储要求变为:

4 in_positionin_colourin_coordin_normal)+ 4 ({{1} })= 8

这也极大地简化了顶点指针的设置,因为你只需要8个而不是20个。