在glsl 3.3中将浮点数组从顶点着色器传递到片段着色器

库里洛

我试图通过

out float texture_contribs[16]

使用glsl 3.3从顶点着色器到框架着色器

但是,无论顶点着色器中的值如何,帧着色器中的值始终为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);
}

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

安东·科尔曼(Andon M.Coleman)

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)。英特尔,苹果,NVIDIA和Mesa都给您16。如果要编写可移植的代码,则应尝试定位的顶点属性不超过16个。否则,您必须为不同的供应商编写不同的代码路径,这很无聊。

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


GLSL顶点着色器的当前编写方式使事情变得混乱。

的OpenGL 3.3核心配置文件规格- 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核心配置文件规格- 2.11.3顶点属性-第55

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

第一4个顶点属性(0 - 3)是激活的,如可通过您的标量阵列创建的16。您的GLSL程序(应该)在任何不提供至少20个顶点属性的实现上均无法链接。如果不是,则您有一个不兼容的实现。


这里的问题是您的每个标量都在浪费3个分量的存储空间。

您实际上并不需要消耗16个属性槽来存储所有每个顶点数据。如果float用的4元素数组vec4或single替换此16元素数组mat4,则仅使用4个属性槽就可以存储相同数量的数据。

然后,您的存储需求将变为:

  4in_positionin_colourin_coordin_normal)+ 4texture_contributions)= 8

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章