简体   繁体   English

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

[英]Passing array of floats from vertex shader to fragment shader in glsl 3.3

I am trying to pass 我试图通过

out float texture_contribs[16]

from the vertex shader to the frament shader using glsl 3.3 使用glsl 3.3从顶点着色器到框架着色器

However the values in the frament shader are always 0.0, no matter the value in the vertex shader. 但是,无论顶点着色器中的值如何,帧着色器中的值始终为0.0。

Here is my vertex shader code: 这是我的顶点着色器代码:

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

and here is the fragment shader code: 这是片段着色器代码:

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

I attempted splitting the array into individual variables and passing them separately and their values still disappear in the fragment shader. 我试图将数组拆分为单独的变量,然后分别传递它们,它们的值仍然在片段着色器中消失。

OpenGL 3.3 requires a minimum of 16 vertex attribute locations. OpenGL 3.3至少需要16个顶点属性位置。

Vertex Attribute Limit (as defined by GLSL): 顶点属性限制(由GLSL定义):

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

Vertex Attribute Limit (queried in OpenGL): 顶点属性限制(在OpenGL中查询):

GLuint max_vtx_attribs;
glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &max_vtx_attribs);

AMD is the only vendor I am aware of that offers more than the minimum of 16 attributes (they give 29-32 on some driver/hardware combinations). 我知道,AMD是唯一一家提供至少16种以上属性的供应商(它们在某些驱动程序/硬件组合中提供29-32)。 Intel, Apple, NVIDIA and Mesa all give you 16. If you want to write portable code, you should try and target no more than 16 vertex attributes. 英特尔,苹果,NVIDIA和Mesa都给您16。如果要编写可移植的代码,则应尝试定位的顶点属性不超过16个。 Otherwise, you have to write different code paths for different vendors, and that is no fun. 否则,您必须为不同的供应商编写不同的代码路径,这很无聊。

There are not many practical applications that require more than 16 per-vertex attributes, and ones that do generally rely on something better suited for storing large amounts of data such as Texture / Shader Storage Buffer Objects. 没有很多实际的应用程序需要每个顶点超过16个属性,并且通常依赖于更适合于存储大量数据的属性,例如纹理/着色器存储缓冲区对象。


Things get messy with your GLSL vertex shader the way it is currently written. GLSL顶点着色器的当前方式使事情变得混乱。

OpenGL 3.3 Core Profile Specification - 2.7 Vertex Specification - pp. 26 OpenGL 3.3核心配置文件规范 -2.7顶点规范 -第26页

Vertex shaders (see section 2.11 ) access an array of 4-component generic vertex attributes . 顶点着色器(请参阅2.11 )访问4成分通用顶点属性的数组。 The first slot of this array is numbered 0 , and the size of the array is specified by the implementation-dependent constant GL_MAX_VERTEX_ATTRIBS . 该数组的第一个插槽编号为0 ,并且数组的大小由与实现相关的常量GL_MAX_VERTEX_ATTRIBS

Each vertex attribute location in GLSL 3.3 is capable of storing a single vec4 , data types that are larger than vec4 ( eg mat4 ) will span multiple locations. GLSL 3.3中的每个顶点属性位置都能够存储单个vec4 ,大于vec4数据类型( 例如 mat4 )将跨越多个位置。 Data types that are smaller than vec4 consume an entire location and this is where your shader starts to run into issues. 小于vec4数据类型会占用整个位置,这是您的着色器开始出现问题的地方。 You have declared a 16-element array of scalars, each of which is given its own sequential location beginning at 4 . 您已经声明了一个由16个元素组成的标量数组,每个标量都有其自己的顺序位置,从4开始。 This means that the array occupies locations 4 - 19 , but most implementations do not have 20 locations to hand out. 这意味着阵列占据位置4 - 19,但大部分的实现没有20个位置来伸手。

OpenGL 3.3 Core Profile Specification - 2.11.3 Vertex Attributes - pp. 55 OpenGL 3.3核心配置文件规范 -2.11.3顶点属性 -第55页

A generic attribute variable is considered active if it is determined by the compiler and linker that the attribute may be accessed when the shader is executed. 如果编译器和链接器确定在执行着色器时可以访问该属性,则将其视为通用属性变量。 Attribute variables that are declared in a vertex shader but never used will not count against the limit. 在顶点着色器中声明但从未使用过的属性变量将不会计入限制。 In cases where the compiler and linker cannot make a conclusive determination, an attribute will be considered active. 如果编译器和链接器无法做出确定的确定,则将属性视为活动的。 A program object will fail to link if the number of active vertex attributes exceeds GL_MAX_VERTEX_ATTRIBS . 如果活动顶点属性的数量超过GL_MAX_VERTEX_ATTRIBS则程序对象将无法链接。

The first 4 vertex attributes ( 0 - 3 ) are active, as are the 16 created by your scalar array. 第一4顶点属性(0 - 3)是激活的,如可通过您的标量阵列创建的16。 Your GLSL program (should) fail to link on any implementation that does not provide at least 20 vertex attributes. 您的GLSL程序(应该)无法在任何不提供至少20个顶点属性的实现上链接。 If it does not, then you have a non-compliant implementation. 如果不是,则您有一个不兼容的实现。


The problem here is that each of your scalars is wasting 3-components worth of storage. 这里的问题是您的每个标量都在浪费3个分量的存储空间。

You do not really need to consume 16 attribute slots to store all of your per-vertex data. 您实际上并不需要消耗16个属性槽来存储所有每个顶点数据。 If you replace this 16-element array of float with a 4-element array of vec4 or a single mat4 , then you can store the same amount of data using only 4 attribute slots. 如果将这16个元素的float数组替换为vec4的4个元素数组或单个mat4 ,则可以仅使用4个属性槽来存储相同数量的数据。

Then your storage requirements become: 然后,您的存储需求将变为:

4 ( in_position , in_colour , in_coord , in_normal ) + 4 ( texture_contributions ) = 8 4in_positionin_colourin_coordin_normal )+ 4texture_contributions )= 8

This also vastly simplifies setting up vertex pointers, as you only need 8 of them instead of 20. 这也大大简化了顶点指针的设置,因为您只需要8个而不是20个即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM