3
$\begingroup$

I'm trying to implement the following paper in modern OpenGL

http://web.media.mit.edu/~lieber/Publications/Coloring-Book.pdf

The issue is that the algorithm described requires you to consider interior points in an orderly fashion -- horizontally first, then vertically. You also need a way to remember throughout the entire coloring process which parts have been already colored.

I initially thought of putting the logic in a fragment shader, but that will clearly not work because I have no control over the order in which it is called, and also no way to remember state between different invocations.

Maybe we can perform this logic on the CPU and use it to make a texture? The problem here is that I don't know of any way to access and modify specific pixels outside of shaders.

Note that doing this using the fixed function pipeline would be much more straightforward, but I want to learn modern OpenGL.

I'm very new to OpenGL and graphics programming, so would appreciate any suggestions on how one would go about this.

$\endgroup$

2 Answers 2

2
$\begingroup$

Flood filling is not a very GPU-friendly operation to begin with, and the algorithm described in the paper is not a very good way to go about flood-filling on the GPU either. It might be possible to make it happen with some heroic efforts and compute shaders, but if flood-filling is what you want to do, I would use a different approach altogether. For example this answer describes how to do flood-filling with a multi-pass approach where each pass extends the filled region by 1 pixel in all directions. It will take a lot of passes to fill a large region. You could probably use some variant of jump flooding for a more efficient method.

However, if you don't actually care about flood filling but are just looking to do exercises to learn GPU programming, I'd recommend trying things like: blur filters, outlining, color transforms, image warping, and so on as those will be a lot more straightforward than any kind of flood fill.

$\endgroup$
0
$\begingroup$

EDIT

After rereading your question, I got the feeling, that I misunderstood your question. So I'll expand my answer referring to this specific part of your question:

Maybe we can perform this logic on the CPU and use it to make a texture? The problem here is that I don't know of any way to access and modify specific pixels outside of shaders.

A texture is basically just an array of (color) values. If you have a 256x256 image, that uses 3 color values (RGB) and each color value is stored in a single byte (GLubyte/char), then your array has 196608 byte sized elements. The color values are usually grouped so that 3 subsequent values represent a single pixel. Then the pixels are also ordered by column and row. So the first 765 array elements represent your first row/column of pixels in the image, the next 765 the second, and so on. With this information, you can calculate where every pixel is located in the image and modify its value as desired.

In case the texture you want to modify is loaded from a file, you should already have the pixel data since this is the format that OpenGL expects when you upload your texture. If the texture is dynamically generated on the GPU, just look into the previous version of my answer (below) for further guidance.

However, calculating lots of pixel data on the CPU is probably quite ineffective. I think the best solution would be to do all modifications on the GPU. If you can't achieve what you want with the standard render pipeline, you should read some tutorials about OpenGL compute shaders. I haven't worked myself with them yet, but I am pretty confident, that your problem should be solvable with them.

Previous version

According to this discussion in the official OpenGL Forum, you can use glReadPixels to get a texture from VRAM back to your normal RAM. However, in the reference pages, they say:

glReadPixels, glReadnPixels — read a block of pixels from the frame buffer

Important here is the term "frame buffer". To find out how to use it with textures, have a look at this StackOverflow question.

However, the accepted answer also mentions, that you can use glGetTexImage (link to reference page), which is probably more suited. Have a look into the accepted answer of this StackOverflow link to get an understanding of how to use it.

Both methods should give you the pixel data on the CPU side, so you can modify it as you wish and send it back to the GPU afterward. However, this is probably a relatively slow approach.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.