【发布时间】:2018-07-20 18:39:27
【问题描述】:
我的意图是,一个物体在屏幕上占据的空间越小,它看起来就越亮。
这是片段着色器fs_1
#version 450 core
layout (binding = 3, offset = 0) uniform atomic_uint area;
void main(void) {
atomicCounterIncrement(area);
}
这是第二个片段着色器,fs_2
#version 450 core
layout (binding = 3) uniform area_block {
uint counter_value;
};
out vec4 color;
layout(location = 4) uniform float max_area;
void main(void){
float brightness = clamp(float(counter_value) / max_area, 0.0, 1.0);
color = vec4(brightness, brightness, brightness, 1.0);
}
然后我将着色器附加到程序对象。现在,有问题的部分来了。我想知道这是否可以接受或完全一团糟。我创建了一个命名缓冲区,然后将其绑定到GL_ATOMIC_COUNTER_BUFFERbinding 点。然后,我将它绑定到绑定号 3。我将计数器重置为零。在那之后,我的意图是在第二个片段着色器中重用原子计数器缓冲区,所以我将它绑定到GL_UNIFORM_BUFFER 目标。最后,我将最大预期区域传递给第二个着色器,以计算亮度。
glUseProgram(program);
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buf);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, 16 * sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 3, buf);
const GLuint zero = 0;
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 2 * sizeof(GLuint), sizeof(GLuint), &zero);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, buf);
glUniform1f(4, info.windowHeight * info.windowWidth);//max_area
像这样,它似乎不起作用。我想我还需要在某个地方插入glColorMask。这是为了关闭第一个片段着色器的输出。此外,我认为,我必须对glMemoryBarrier 做点什么。还是没有必要?我是否以错误的顺序调用函数?
我在互联网上没有找到对它的真正引用,也没有关于如何实现它的示例代码。如有任何答案,我将不胜感激。
编辑:
另外,我收到了一些错误信息,这使得问题很明显:
glLinkProgram failed to link a GLSL program with the following program info log: 'Fragment shader(s) failed to link.
Fragment link error: INVALID_OPERATION.
ERROR: 0:8: error(#248) Function already has a body: main
ERROR: error(#273) 1 compilation errors. No code generated
我很快就指出这可能是问题所在,两个片段着色器具有mainbody。那么我该如何解决呢?我可以留下两个main 实体并创建第二个程序对象吗?
【问题讨论】:
-
你不能在顶点着色器甚至 CPU 上计算三角形的屏幕空间面积,然后除以它吗?即使您可以让这种设计发挥作用,它也违背了 GPU 擅长的特性,并且不太可能具有很高的性能。
-
所以亮度是物体“大小”和到相机距离(深度)的函数?
-
距离越远的对象占用的空间越小,这是对的。它在 OpenGL SuperBible 中有描述,所以我想尝试一下。只是书中没有完整描述的代码,所以我需要自己弄清楚。
-
@F.Leuthold 您是否尝试将 2 个片段着色器链接到 1 个程序 !?
-
如果我没记错的话,这些着色器应该在不同的通道中运行,那么你为什么要把它们放在同一个程序中!?除此之外,可能应该指出的是,这种方法将计算处理了多少片段,而不是在屏幕上可见多少像素。