跨多个着色器的 OpenGL 统一
Posted
技术标签:
【中文标题】跨多个着色器的 OpenGL 统一【英文标题】:OpenGL Uniform Across Multiple Shaders 【发布时间】:2015-10-08 01:07:06 【问题描述】:我在 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_eyePositionUL
和m_eyePositionGeomShaderUL
都刚刚加载了glGetUniformLocation
)
glUniform3fv(m_eyePositionUL, 1, &m_camera.getPosition()[0]);
glUniform3fv(m_eyePositionGeomShaderUL, 1, &m_camera.getPosition()[0]);
我怎样才能只将一个制服上传到 OpenGL 并在几何着色器和顶点着色器中都使用它?
【问题讨论】:
【参考方案1】:这有点令人惊讶,但 OpenGL 让它变得简单。您所要做的就是在两个着色器中使用相同的统一名称!
然后在那个统一的位置上传一次。
将几何着色器中的uniform vec3 eyePositionWorldGeomShader;
替换为uniform vec3 eyePositionWorld;
,并在片段着色器中保持统一名称相同。
那么就不要上传其他 Uniform,这样你的 C++ 代码就可以了
glUniform3fv(m_eyePositionUL, 1, &m_camera.getPosition()[0]);
【讨论】:
以上是关于跨多个着色器的 OpenGL 统一的主要内容,如果未能解决你的问题,请参考以下文章