当我想在同一程序的不同着色器阶段使用制服时,如何指定显式统一位置?
使用自动分配时,当标识符匹配时,将不同阶段的制服分配到同一位置.但是如何使用the定义着色器中的位置
layout (location = ...)
Run Code Online (Sandbox Code Playgroud)
句法?
以下引用自:https://www.opengl.org/wiki/Uniform_( GLSL)/ Explicit_Uniform_Location
将相同的统一位置分配给同一着色器或同一程序中的两个制服是非法的.即使这两个制服具有相同的名称和类型,并且在不同的着色器阶段中定义,明确地将它们分配给相同的统一位置也是不合法的; 将发生链接器错误.
以下是GLSL规范的引用:
程序中没有两个默认块统一变量可以具有相同的位置,即使它们未被使用,否则将生成编译时或链接时错误.
我正在使用OpenGL 4.3.
由于阅读代码非常庞大,我发现,制服尚未使用. 这导致以下情况:在GTX 780上,以下代码运行没有问题(虽然它似乎不应该).在Intel HD 5500板载图形芯片上,根据GL_ARB_DEBUG_OUTPUT扩展,代码在链接时产生SHADER_ID_LINK错误.它指出,均匀位置与另一个制服重叠.
顶点着色器:
#version 430 core
layout(location = 0) in vec4 vPosition;
layout(location = 2) in vec4 vTexCoord;
layout(location = 0) uniform mat4 WorldMatrix; // <-- unused in both stages
out vec4 fPosition;
out vec4 fTexCoord;
void main() { ... }
Run Code Online (Sandbox Code Playgroud)
片段着色器:
#version 430 …Run Code Online (Sandbox Code Playgroud) Cook-Torrance BRDF以及Lambert BRDF上有很多材料.虚幻引擎4中的真实着色和将霜冻运动转换为BPR,可以深入解释如何将它们实现为实时渲染.
他们省略的是两个BRDF的组合,以创建完整的着色模型.如果我理解正确,我们可以使用至少两个基本原则来做到这一点:镜面和金属工作流程.这是对它们的比较.
我决定实施金属工作流程.所以我有以下参数来计算:
对于镜面反射部分,我需要确定我的镜面反射颜色.
Mamoset说明了这一点
当使用metalness地图,绝缘表面 - 在metalness地图设定为0.0(黑色)像素 - 被分配一个固定的反射率值(线性:0.04的sRGB:0.22),并使用反射率的地图为漫反射值.对于金属表面 - 金属度贴图中设置为1.0(白色)的像素 - 镜面反射颜色和强度取自反照率贴图,漫反射器中的漫反射值设置为0(黑色).
因此,镜面反射颜色应通过以下方式计算:
vec3 specularColor = mix(vec3(0.04), material.albedo, material.metalness);
Run Code Online (Sandbox Code Playgroud)
随后,这可用于计算反射辐射.为了限制我的问题的扩展,我将在这里参考Brian Karis的实现,其中包括:
vec3 L_specular = specularIBL(specularColor, material.roughness, normal, view);
Run Code Online (Sandbox Code Playgroud)
对于漫射部分,我需要确定反照率.
如何工作在上面的相同引用中描述:
vec3 albedo = mix(material.albedo, vec3(0), material.metalness);
Run Code Online (Sandbox Code Playgroud)
现在,Lambert BRDF可用于计算来自某些入射辐照度E的漫射光照:
vec3 L_diffuse = f_lambert(albedo) * E;
Run Code Online (Sandbox Code Playgroud)
为了得到最终的光度,漫反射和镜面反射部分组合在一起:
vec3 L = kd * L_diffuse + ks * L_specular;
Run Code Online (Sandbox Code Playgroud)
我的问题是如何计算kd和ks?
ks. …我无法将立方体贴图读回 CPU。当我在glTexImage2D调用中将数据传递给立方体贴图时,可以毫无问题地读回这些数据。但是当我渲染到立方体贴图时,只有立方体贴图的正 x 侧包含合理的数据。其他一切都是 0(而不是未初始化)。
我正在使用分层渲染渲染到立方体贴图,然后通过在着色器中对其进行采样来检查立方体贴图的内容。我在那里得到的是正确的。但glGetTexImage似乎不像我想象的那样工作。
当我glGetTexImage按照以下建议调用时,没有绑定帧缓冲区:www.gamedev.com
我这样做错了吗?有人知道这里可能出了什么问题吗?
glGenTextures(1, &c_cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, c_cubemap);
// load data ...
auto width = positiveX->width;
auto height = positiveX->height;
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ...);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ...);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ...);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ...);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ...);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB16F, width, …Run Code Online (Sandbox Code Playgroud) 目前,我正在实施良好的旧 Phong 着色。总的来说,它看起来很正确,但在正常情况下出现了一种我无法解释的模式。
如果不仔细观察,我认为斯坦福兔子看起来很正确。

在这张图片中,我可视化了法线并提高了饱和度以使问题更加明显。

这是我的顶点着色器:
#version 330 core
layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec3 vNormal;
out vec4 fWorldPosition;
smooth out vec3 fWorldNormalSmooth;
...
void main() {
fWorldNormalSmooth = normalize(NormalMatrix*vNormal);
fWorldPosition = WorldMatrix*vPosition;
gl_Position = ProjectionMatrix*ViewMatrix*WorldMatrix*vPosition;
}
Run Code Online (Sandbox Code Playgroud)
这是我的片段着色器:
#version 330 core
smooth in vec3 fWorldNormalSmooth;
in vec4 fWorldPosition;
out vec4 color;
...
vec4 shadePointLight(Material material, PointLight pointLight, vec3 worldPosition, vec3 worldNormal) {
vec3 cameraPosition = wdiv(inverse(ViewMatrix)*vec4(0, 0, 0, 1));
vec3 …Run Code Online (Sandbox Code Playgroud) 我正在OpenGL中实现深度预处理.在Intel HD Graphics 5500上,此代码工作正常,但在Nvidia GeForce GTX 980上却没有(下图显示了由此产生的z-fighting).我正在使用以下代码生成图像.(省略了与问题无关的所有内容.)
// ----------------------------------------------------------------------------
// Depth Prepass
// ----------------------------------------------------------------------------
glEnable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
glUseProgam(program1); // The problem turned out to be here!
renderModel(...);
// ----------------------------------------------------------------------------
// Scene Rendering
// ----------------------------------------------------------------------------
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_FALSE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glUseProgam(program2); // The problem turned out to be here!
renderModel(...);
Run Code Online (Sandbox Code Playgroud)
似乎glDepthFunc没有更改为GL_LEQUAL.但是,当我逐步完成RenderDoc中的GL调用时,glDepthFunc会设置为correnctly.
这听起来像是一个驱动程序错误,或者你有什么建议我可能做错了吗?当这是一个驱动程序错误时,我怎么能实现深度预先通过呢?