简体   繁体   English

OpenGL 3.3着色器统一变量不起作用

[英]OpenGL 3.3 shaders uniform variables not working

I've got two shaders programs (because I'm using deferred shading), each one with its Vertex and Fragment shader. 我有两个着色器程序(因为我正在使用延迟着色),每个程序都有其顶点和片段着色器。 My problem is that I can successfilly compile and link both of them (glGetProgramiv with GL_LINK_STATUS returns GL_TRUE for each one) but when I try to get the addresses of my second shader program's uniforms I can get only 3 of them, instead of 27 that are currently declared. 我的问题是我可以成功填充并链接它们(glGetProgramiv和GL_LINK_STATUS都为每个返回GL_TRUE),但是当我尝试获取第二个着色器程序的制服的地址时,我只能得到其中的3个,而不是27个当前声明。

I've checked with glGetProgramiv and GL_ACTIVE_UNIFORMS to check the number of uniforms for each shader program and for the first one it's right, but for the second it's wrong. 我已经使用glGetProgramiv和GL_ACTIVE_UNIFORMS进行了检查,以检查每个着色器程序的制服数量,第一个是正确的,但是第二个是错误的。

I've noticed that the only uniforms I can get from the secondo program are the first 3 of its vertex shader, and even if I add an uniform in that vertex shader, the number of readable uniforms is always 3. 我注意到,从secondo程序中可以获得的唯一制服是其顶点着色器的前3个,即使在该顶点着色器中添加了制服,可读的制服的数量也始终为3。

(I've added only my uniform's declaration because the shaders were too long.) (由于着色器太长,我只添加了我的制服的声明。)

This is the code for the first program vertex shader (working correctly) 这是第一个程序顶点着色器的代码(正常工作)

uniform struct Matrices
{
    mat4 projectionMatrix;
    mat4 modelMatrix;
    mat4 viewMatrix;
    mat4 normalMatrix;
} matrices;

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inCoord;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inTangent;

This is the code for the first program fragment shader (working correctly) 这是第一个程序片段着色器的代码(正常工作)

uniform sampler2D gSampler;
uniform sampler2D gSamplerBump;
uniform vec4 vColor;

uniform float       gMatSpecularIntensity;
uniform float       gSpecularPower;
uniform float       gRetroilluminato;

uniform int useTexture;
uniform int useTextureBump;
uniform int fondiTextureColore;

And these are the vertex and fragment shaders that are not working properly. 这些是顶点和片段着色器无法正常工作。

Vertex: 顶点:

uniform struct Matrici
{
    mat4 projectionMatrix;
    mat4 modelMatrix;
    mat4 viewMatrix;
} matrici;

Fragment: 分段:

uniform struct MDLight
{
    vec3 vColor;
    vec3 vPosition;
    vec3 vDirection;  

    float fAmbientIntensity;
    float fStrength;

    int bOn;

    float fConeAngle;
    float fConeCosine;

    float fConstantAtt;
    float fLinearAtt;
    float fExpAtt;

    float fAltezza;
    float fLarghezza;

    vec3 vUp;
    vec3 vRight;
} gLuce;

uniform float gSpecularIntensity;
uniform float gSpecularPower;

uniform sampler2D gPositionMap;
uniform sampler2D gColorMap;
uniform sampler2D gNormalMap;
uniform vec3 gCameraPos;

uniform vec2 gScreenSize;
uniform int gLightType;

uniform int gUsaLuci;

Basically I can get only the addesses of projectionMatrix, modelMatrix and viewMatrix in the uniform struct "Matrici" of my second program vertex shader. 基本上,我只能在第二个程序顶点着色器的统一结构“ Matrici”中获得projectionMatrix,modelMatrix和viewMatrix的地址。 I've tried adding a value both inside the struct and outside but it doesen't read it. 我试过在结构体内部和外部都添加一个值,但它不会读取它。

Anyone with an idea? 有人有主意吗?


As @rems4e asked these are the complete shaders. 如@ rems4e所问,这些是完整的着色器。

Vertex shader for working program. 用于工作程序的顶点着色器。

#version 330

uniform struct Matrices
{
    mat4 projectionMatrix;
    mat4 modelMatrix;
    mat4 viewMatrix;
    mat4 normalMatrix;
} matrices;

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inCoord;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inTangent;

smooth out vec2 texCoord;
smooth out vec3 vNormal;
smooth out vec3 vTangent;
smooth out vec3 vEyeSpacePos;
smooth out vec3 vWorldPos;

void main()
{
    vec4 vEyeSpacePosVertex = matrices.viewMatrix*matrices.modelMatrix*vec4(inPosition, 1.0);
    gl_Position = matrices.projectionMatrix*vEyeSpacePosVertex;

    texCoord = inCoord;

    vec4 vRes = matrices.normalMatrix*vec4(inNormal, 0.0);
    vNormal = vRes.xyz;

    vec4 vResTang = matrices.normalMatrix*vec4(inTangent, 0.0);
    vTangent = vResTang.xyz;

    vEyeSpacePos = vEyeSpacePosVertex.xyz;

    vec4 vWorldPosVertex = matrices.modelMatrix*vec4(inPosition, 1.0);
    vWorldPos = vWorldPosVertex.xyz;
}

Fragment shader for working program. 用于工作程序的片段着色器。

#version 330

smooth in vec2 texCoord;
smooth in vec3 vNormal;
smooth in vec3 vTangent;
smooth in vec3 vEyeSpacePos;
smooth in vec3 vWorldPos;

layout (location = 0) out vec4 WorldPosOut; 
layout (location = 1) out vec4 DiffuseOut; 
layout (location = 2) out vec4 NormalOut; 
layout (location = 3) out vec4 FlagsOut; 

uniform sampler2D gSampler;
uniform sampler2D gSamplerBump;
uniform vec4 vColor;

uniform float       gMatSpecularIntensity;
uniform float       gSpecularPower;
uniform float       gRetroilluminato;

uniform int useTexture;
uniform int useTextureBump;
uniform int fondiTextureColore;

void main()
{
    vec3 vNormalized = normalize(vNormal);
    vec3 vTangente = normalize(vTangent);

    vec4 vTexColor;
    vec4 vMixedColor;

    if(useTexture == 1)
    {
        vTexColor = texture2D(gSampler, texCoord);

        if(fondiTextureColore == 1)
            vMixedColor = vTexColor * vColor;
        else
            vMixedColor = vTexColor;
    }
    else
    {
        vMixedColor = vColor;
    }

    if(useTextureBump == 1)
    {
        vec3 vNormaleBump = texture(gSamplerBump, texCoord).xyz;
        vNormaleBump = 2.0 * vNormaleBump - vec3(1.0, 1.0, 1.0);

        vTangente = normalize(vTangente - dot(vTangente, vNormalized) * vNormalized);

        vec3 vBitangente = cross(vTangente, vNormalized);

        mat3 TBN = mat3(vTangente, vBitangente, vNormalized);

        vec3 vNuovaNormale = TBN * vNormaleBump;
        vNuovaNormale = normalize(vNuovaNormale);

        vNormalized = vNuovaNormale;
    }

    WorldPosOut = vec4(vWorldPos, 1.0);
    DiffuseOut = vMixedColor;
    NormalOut = vec4(vNormalized, 1.0);

    float v1 = 0.0;
    float v2 = gMatSpecularIntensity;
    float v3 = gSpecularPower;
    float v4 = 1.0;

    if(gRetroilluminato == 1)
        v1 = 1.0;

    FlagsOut = vec4(v1, v2, v3, v4);
}

Vertex shader for NOT working program. 顶点着色器不适用于程序。

#version 330

uniform struct Matrici
{
    mat4 projectionMatrix;
    mat4 modelMatrix;
    mat4 viewMatrix;
} matrici;

layout (location = 0) in vec3 inPosition;

void main()
{
    vec4 vEyeSpacePosVertex = matrici.viewMatrix * matrici.modelMatrix * vec4(inPosition, 1.0);
    gl_Position = matrici.projectionMatrix * vEyeSpacePosVertex;
}

Fragment shader for NOT working program. 片段着色器不适用于程序。

#version 330

uniform struct MDLight
{
    vec3 vColor;
    vec3 vPosition;
    vec3 vDirection;  

    float fAmbientIntensity;
    float fStrength;

    int bOn;

    float fConeAngle;
    float fConeCosine;

    float fConstantAtt;
    float fLinearAtt;
    float fExpAtt;

    float fAltezza;
    float fLarghezza;

    vec3 vUp;
    vec3 vRight;
} gLuce;

uniform float gSpecularIntensity;
uniform float gSpecularPower;

uniform sampler2D gPositionMap;
uniform sampler2D gColorMap;
uniform sampler2D gNormalMap;
uniform vec3 gCameraPos;

uniform vec2 gScreenSize;
uniform int gLightType;

uniform int gUsaLuci;

vec3 projectOnPlane( vec3 point, vec3 planeCenter, vec3 planeNorm )
{
    return point - dot( point - planeCenter, planeNorm ) * planeNorm;
}

vec3 linePlaneIntersect( vec3 lp, vec3 lv, vec3 pc, vec3 pn ) 
{
    return lp + lv * ( dot( pn, pc - lp ) / dot( pn, lv ) );
}

bool isDavanti(vec3 p1, vec3 p2, vec3 n2)
{
    vec3 p1p2 = normalize(p1 - p2);
    float prod = dot(p1p2, n2);

    if(prod >= 0.0)
        return true;
    else
        return false;
}

vec4 getDirectionalLightColor(const MDLight dirLight, vec3 vNormale, int retroilluminato)
{
    float fDiffuseIntensity = max(0.0, dot(vNormale, -dirLight.vDirection));
    return vec4(dirLight.vColor * (dirLight.fAmbientIntensity + fDiffuseIntensity) * dirLight.fStrength, 1.0);
}

vec4 getPointLightColor(const MDLight ptLight, vec3 vWorldPos, vec3 vNormale, int retroilluminato)
{
    if(ptLight.bOn == 0)
        return vec4(0.0, 0.0, 0.0, 0.0);

    vec3 vPosToLight = vWorldPos - ptLight.vPosition;
    float fDist = length(vPosToLight);
    vPosToLight = normalize(vPosToLight);

    float fDiffuse;

    if(retroilluminato == 1 && isDavanti(vWorldPos, ptLight.vPosition, vPosToLight))
        fDiffuse = abs(dot(vNormale, -vPosToLight));
    else
        fDiffuse = max(0.0, dot(vNormale, -vPosToLight));

    float fAttTotal = (1 + fDist * 0.0001 + 0.0000001 * fDist * fDist);

    return vec4(ptLight.vColor, 1.0)*(ptLight.fAmbientIntensity + fDiffuse) / fAttTotal;
}   

vec4 GetSpotLightColor(const MDLight spotLight, vec3 vWorldPos, vec3 vNormale, int retroilluminato)
{
    if(spotLight.bOn == 0)
        return vec4(0.0, 0.0, 0.0, 0.0);

    vec3 vDir = vWorldPos-spotLight.vPosition;
    vDir = normalize(vDir);

    if(dot(vNormale, -vDir) <= 0.00 && (retroilluminato == 0))
        return vec4(0.0, 0.0, 0.0, 0.0);

    float fDistance = distance(vWorldPos, spotLight.vPosition);

    float fCosine = dot(spotLight.vDirection, vDir);

    float fDif = 1.0-spotLight.fConeCosine;

    float fFactor = clamp((fCosine-spotLight.fConeCosine)/fDif, 0.0, 1.0);

    float fAttTotal = (1 + fDistance * 0.0001 + 0.000001 * fDistance * fDistance);

    if(fCosine > spotLight.fConeCosine)
        return vec4(spotLight.vColor, 1.0)*(fFactor * spotLight.fAmbientIntensity) / fAttTotal;

    return vec4(0.0, 0.0, 0.0, 0.0);
}

vec4 GetRectLightColor(const MDLight luce, vec3 vPosVert, vec3 vNormale, int retroilluminato)
{
    if(luce.bOn == 0)
        return vec4(0.0, 0.0, 0.0, 0.0);

    vec3 direzioneLuce = normalize(luce.vDirection);
    vec3 posizioneLuce = luce.vPosition;
    vec3 normaleVertice = normalize(vNormale);

    float w = luce.fLarghezza;
    float h = luce.fAltezza;

    vec3 proj = projectOnPlane(vPosVert, posizioneLuce, direzioneLuce);
    vec3 dir = proj - posizioneLuce;

    vec2 diagonal = vec2(dot( dir, luce.vRight), dot( dir, luce.vUp));
    vec2 nearest2D = vec2(clamp(diagonal.x, -w, w), clamp(diagonal.y, -h, h));

    vec3 nearestPointInside = posizioneLuce + (luce.vRight * nearest2D.x + luce.vUp * nearest2D.y);

    vec3 lightDir = normalize(nearestPointInside - vPosVert);

    float prodDirLmLD = dot(direzioneLuce, -lightDir);
    float prodNVLD = dot(normaleVertice, lightDir);

    float NdotL = 0.0;
    float NdotL2 = 0.0;

    if(retroilluminato == 1)
    {
        NdotL = abs(prodDirLmLD);
        NdotL2 = abs(prodNVLD);
    }
    else
    {
        NdotL = max(prodDirLmLD, 0.0);
        NdotL2 = max(prodNVLD, 0.0);
    }

    float prodottoDot = NdotL2 * NdotL;

    if ( prodottoDot > 0.0 )
    {
        vec3 diffuse = vec3(sqrt(prodottoDot));
        float dist = distance(vPosVert, nearestPointInside);

        float attenuation = (1 + dist * 0.0001 + 0.000001 * dist * dist);

        vec3 light = luce.fAmbientIntensity * luce.vColor;

        return vec4(light * diffuse, 1.0) / attenuation;
    }
    else
    {
        return vec4(0.0, 0.0, 0.0, 0.0);
    }
}

vec4 GetSpecularColor(vec3 vPosVertice, vec3 vPosCamera, vec3 vNormaleVertice, const MDLight luce)
{
    vec4 vResult = vec4(0.0, 0.0, 0.0, 0.0);

    vec3 direzioneLuce = luce.vDirection;
    vec3 direzioneLuceVertice = vPosVertice - luce.vPosition;

    if(gLightType == 1)
        direzioneLuce = normalize(vPosVertice - luce.vPosition);

    if(dot(-direzioneLuce, vNormaleVertice) <= 0.0 || dot(direzioneLuce, direzioneLuceVertice) <= 0.0)
        return vResult;

    vec3 vReflectedVector = normalize(reflect(direzioneLuce, vNormaleVertice));
    vec3 vVertexToEyeVector = normalize(vPosCamera - vPosVertice);
    float fSpecularFactor = dot(vVertexToEyeVector, vReflectedVector);

    fSpecularFactor = pow(fSpecularFactor, gSpecularPower);

    if (fSpecularFactor > 0)
        vResult = vec4(luce.vColor, 1.0) * gSpecularIntensity * fSpecularFactor * luce.fAmbientIntensity;

    return vResult; 
}

vec4 GetMDLightColor(const MDLight ptLight, vec3 vWorldPos, vec3 vNormale, int retroilluminato)
{
    if(gLightType == 0)
        return getDirectionalLightColor(ptLight, vNormale, retroilluminato);
    else if(gLightType == 1)
        return getPointLightColor(ptLight, vWorldPos, vNormale, retroilluminato);
    else if(gLightType == 2)
        return GetSpotLightColor(ptLight, vWorldPos, vNormale, retroilluminato);
    else if(gLightType == 3)
        return GetRectLightColor(ptLight, vWorldPos, vNormale, retroilluminato);
}

vec2 CalcTexCoord()
{
    return gl_FragCoord.xy / gScreenSize;
}

out vec4 FragColor; 

void main()
{
    vec2 TexCoord = CalcTexCoord();
    vec4 Color = texture(gColorMap, TexCoord);

    if(gUsaLuci == 1)
    {
        vec3 WorldPos = texture(gPositionMap, TexCoord).xyz;
        vec3 Normal = texture(gNormalMap, TexCoord).xyz;
        Normal = normalize(Normal);

            int retroilluminato = 0;

        vec4 coloreLuce = GetMDLightColor(gLuce, WorldPos, Normal, retroilluminato);
        vec4 coloreRiflesso = GetSpecularColor(WorldPos, gCameraPos, Normal, gLuce);
    }
    else
    {
        FragColor = Color;
    }
}

GL_ACTIVE_UNIFORMS is mapped as its name indicates to the active uniforms, ie the ones that actually not optimized away by the shader compiler/linker. GL_ACTIVE_UNIFORMS就像其名称所指示的那样映射到活动的制服,即,着色器编译器/链接器实际上并未对其进行优化的制服。 This happens when the uniform is not used by your program, or used in a way that won't affect the final rendering. 当您的程序不使用制服,或使用不会影响最终渲染的方式时,就会发生这种情况。 Your shader code is needed to see if the uniforms you can not get the index of are used or not, but I presume they are not. 需要您的着色器代码,以查看您是否无法使用无法获得索引的制服,但是我认为它们没有被使用。

I solved my problem following @rems4e hint. 我按照@ rems4e提示解决了我的问题。

In fact I thought I was using all my uniforms, in theory, but in practice I wasn't. 实际上,从理论上讲,我认为我正在使用我的所有制服,但实际上我没有。 In all of my functions I was passing a MDLight as parameter, which, actually, was gLuce , the uniform I was trying to get the uniforms. 在我的所有函数中,我都传递了MDLight作为参数,实际上是gLuce ,我正在尝试获取制服。 Seems like that passing gLuce as parameter for other functions, OpenGL thought I was actually not using gLuce , deleting it from my active uniform list. 好像将gLuce作为其他函数的参数传递一样,OpenGL认为我实际上不是在使用gLuce ,而是从我的活动统一列表中删除了它。

So basically I just used gLuce everywhere instead the parameter I was passing to the functions and it's now working. 因此,基本上我只是在gLuce地方都使用了gLuce ,而不是我传递给函数的参数,现在它可以正常工作了。

The same for all other uniforms I wasn't able to get. 我无法获得的所有其他制服都一样。

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

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