OpenGL统一跨多个着色器

OpenGL Uniform Across Multiple Shaders

本文关键字:OpenGL      更新时间:2023-10-16

我在OpenGL中创建了一个应用程序,使用顶点着色器,几何着色器和片段着色器。

我有一个统一的变量,eyePositionWorld,我想在几何着色器和片段着色器中都使用。

(我正在渲染与eyePositionWorld相比的垂直位置作为颜色)

顶点着色器

#version 430
in vec4 vertexPositionModel;
in vec3 vertexColor;
in vec3 vertexNormalModel;
in mat4 modelMatrix;
uniform mat4 viewMatrix;//World To View
uniform mat4 projectionMatrix;//View to Projection
struct fData
{
    vec3 fragColor;
    vec3 fragPositionWorld;
    vec3 fragNormalWorld;
};
out fData geomData;
void main()
{
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vertexPositionModel;
    geomData.fragColor = vertexColor;
    geomData.fragPositionWorld = (modelMatrix * vertexPositionModel).xyz;
    geomData.fragNormalWorld = (modelMatrix * vec4(vertexNormalModel, 0.0)).xyz;
}

几何着色器

#version 430
layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices=3) out;
struct fData
{
    vec3 fragColor;
    vec3 fragPositionWorld;
    vec3 fragNormalWorld;
};
uniform vec3 eyePositionWorldGeomShader;
in fData geomData[];
out fData fragData;
void main() {
    gl_Position = gl_in[0].gl_Position;
    fragData = geomData[0];
    fragData.fragColor = gl_in[0].gl_Position.xyz - eyePositionWorldGeomShader;
    EmitVertex();
    gl_Position = gl_in[2].gl_Position;
    fragData = geomData[2];
    fragData.fragColor = gl_in[2].gl_Position.xyz - eyePositionWorldGeomShader;
    EmitVertex();
    gl_Position = gl_in[4].gl_Position;
    fragData = geomData[4];
    fragData.fragColor = gl_in[4].gl_Position.xyz - eyePositionWorldGeomShader;
    EmitVertex();
    EndPrimitive();
}

片段着色器

#version 430
struct fData
{
    vec3 fragColor;
    vec3 fragPositionWorld;
    vec3 fragNormalWorld;
};
in fData fragData;
uniform vec4 ambientLight;
uniform vec3 lightPositionWorld;
uniform vec3 eyePositionWorld;
uniform bool isLighted;
out vec4 color;
void main()
{
    if (!isLighted)
    {
        color = vec4(fragData.fragColor, 1.0);
    }
    else
    {
        vec3 lightVectorWorld = normalize(lightPositionWorld - fragData.fragPositionWorld);
        float brightness = clamp(dot(lightVectorWorld, normalize(fragData.fragNormalWorld)), 0.0, 1.0);
        vec4 diffuseLight = vec4(brightness, brightness, brightness, 1.0);
        vec3 reflectedLightVectorWorld = reflect(-lightVectorWorld, fragData.fragNormalWorld);
        vec3 eyeVectorWorld = normalize(eyePositionWorld - fragData.fragPositionWorld);
        float specularity = pow(clamp(dot(reflectedLightVectorWorld, eyeVectorWorld), 0.0, 1.0), 40) * 0.5;
        vec4 specularLight = vec4(specularity, specularity, specularity, 1.0);
        //Maximum Distance of All Lights
        float maxDist = 55.0;
        float attenuation = clamp((maxDist - length(lightPositionWorld - fragData.fragPositionWorld)) / maxDist, 0.0, 1.0);
        color = (ambientLight + (diffuseLight + specularLight) * attenuation) * vec4(fragData.fragColor, 1.0);
    }
}

c++代码(m_eyePositionULm_eyePositionGeomShaderUL都只是加载了glGetUniformLocation)

glUniform3fv(m_eyePositionUL, 1, &m_camera.getPosition()[0]);
glUniform3fv(m_eyePositionGeomShaderUL, 1, &m_camera.getPosition()[0]);

我怎么能只上传一个统一的OpenGL和使用它在几何着色器和顶点着色器?

这有点令人惊讶,但OpenGL使它变得容易。你所要做的就是在两个着色器中使用相同的统一名称!

然后在那个统一的位置上传一次。

在你的几何着色器中用uniform vec3 eyePositionWorld;替换uniform vec3 eyePositionWorldGeomShader;,并在碎片着色器中保持统一的名称。

然后不要上传其他的Uniform,这样你的c++代码就会变成

glUniform3fv(m_eyePositionUL, 1, &m_camera.getPosition()[0]);