I solved my issue by creating a new gll program and attaching a compute shader to it.
unsigned int vs = CompileShader(vertShaderStr, GL_VERTEX_SHADER);
unsigned int fs = CompileShader(fragShaderStr, GL_FRAGMENT_SHADER);
unsigned int cs = CompileShader(compShaderStr, GL_COMPUTE_SHADER);
glAttachShader(mainProgram, vs);
glAttachShader(mainProgram, fs);
glAttachShader(computeProgram, cs);
glLinkProgram(computeProgram);
glValidateProgram(computeProgram);
glLinkProgram(mainProgram);
glValidateProgram(mainProgram);
glUseProgram(computeProgram);
Then, in the Render loop I switch programs and run the compute shader.
glUseProgram(computeProgram);
glDispatchCompute(resolutionX, resolutionY, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(mainProgram);
/* Drawing the whole screen using the shader */
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* Poll for and process events */
glfwPollEvents();
updateBuffer();
Update();
/* Swap front and back buffers */
glfwSwapBuffers(window);
I pass the data from compute shader to fragment shader via shader storage buffer.
void setupBuffer() {
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glNamedBufferStorage(ssbo, sizeof(float) * (resolutionX * resolutionY +
SH_EXTRA_FLOATS), &data, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT); //sizeof(data) only works for statically sized C/C++ arrays.
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);
}
void updateBuffer() {
float d[] = { data.min, data.max };
glNamedBufferSubData(ssbo, 0, 2 * sizeof(float), &d);
}
In the compute shader, I can access the buffer like this:
layout(std430, binding = 1) buffer bufferIn
{
float min;
float max;
float data[];
};
layout(std430, binding = 1) buffer destBuffer
{
float min;
float max;
float data[];
} outBuffer;
void main() {
screenResolution;
int index = int(gl_WorkGroupID.x + screenResolution.x * gl_WorkGroupID.y);
dvec2 coords = adjustCoords();
dvec4 position = rotatedPosition(coords);
for (i = 0; i < maxIter; i++) {
position = pow2(position);
double length = lengthSQ(position);
if (length > treashold) {
float log_zn = log(float(length)) / 2.0;
float nu = log(log_zn / log(2.0)) / log2;
float iterAdj = 1.0 - nu + float(i);
float scale = iterAdj / float(maxIter);
if (scale < 0)
data[index] = -2;
data[index] = scale;
if (scale > max) max = scale;
if (scale < min && scale > 0) min = scale;
return;
}
}
data[index] = -1;
};
And finally, in the fragment shader, I can read the buffer like this:
layout(std430, binding = 1) buffer bufferIn
{
float min;
float max;
float data[];
};
if (data[index] == -1) {
color = notEscapedColor;
return;
}
float value = (data[index] - min) / (max - min);
if (value < 0) value = 0;
if (value > 1) value = 1;
Here is the code in its entirety.