My intention was, that the less space an object takes up on the screen, the less bright the object should appear.
This is fragment shader fs_1
#version 450 core
layout (binding = 3, offset = 0) uniform atomic_uint area;
void main(void) {
atomicCounterIncrement(area);
}
That's the second fragment shader, 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);
}
I then attached the shaders to the program object. Now, the problematic part comes. I wonder if that's even acceptable or a complete mess. I created a named buffer and then bound it to the GL_ATOMIC_COUNTER_BUFFER
binding point. Then, I bound it to binding number 3. I reset the counter with zero. After that, my intention was to reuse the atomic counter buffer in the second fragment shader, so I bound it to the GL_UNIFORM_BUFFER
target. Last, I pass the maximum expected area to the second shader, in order to calculate the brightness.
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
Like so, it doesn't seem to work. I also somewhere need to insert glColorMask
, I suppose. This, in order to turn off the output of the first fragment shader. Furthermore, I think, I have to do something with glMemoryBarrier
. Or is that not necessary? Have I called the functions in the wrong order?
I found no real references to it in the internet, no sample code on how to accomplish that. I'd be thankful for any answers.
Edit:
In addition, I have got some error message which makes the problem obvious:
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
I have very soon remarked that that might be the problem, that two fragment shaders have the main
body. So how could I fix that? Could I leave both main
bodies and instead create a second program object?
I got the design to work, eventually!
I've followed the great advices in the comments. To sum up: I created two program objects with the same vertex shader attached to them. After that, I called program
(with fragment shader fs_1
) as follows:
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
For some reason, I didn't have to call glMemoryBarrier
or glColorMask
.
I then made the following calls in my render-loop:
virtual void render(double currentTime) {
glUseProgram(program1);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
There, I used the second program object, program1
(with fragment shader fs_2
). I suppose it works, because there needs to be a vertex shader in each program object, not just in one. I then drew the triangle the first time, without any color output, but just to calculate the area. I then drew it the second time, using the "counted area" to calculate the brightness of the triangle.
I also realised, that the shaders are only executed when you issue a draw call.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments