I have a quad, the size of my viewport window that has an equivalently sized and proportioned texture map applied to it. Both the vertex shader and the fragment shader work, and the expected result is output to the screen.
I am trying to write a geometry shader in OpenGL that loads a texture (it’s already been passed through an edge detection algorithm, so I’m left with a black background and white edges), and then queries each pixel of the loaded texture to determine whether or not there is an edge (a white pixel). If it does find an edge, I want the geometry shader to create a point at the corresponding location of the edge pixel, continue along the selected axis until it finds another edge, creates a point there, and then emits a line between the two, stored in a buffer.
Is it possible to sample a texture within a geometry shader? If so, how would I go about uploading the image to a uniform and hen extracting the information of individual pixels?
Geometry shaders have the ability to do a lookup into a texture map, if
supported by the GL implementation. The maximum number of texture image
units available to a geometry shader is
MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB; a maximum number of zero indicates
that the GL implementation does not support texture accesses in geometry
So ensure that MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB is not set to 0.
I went quickly to these specs and it looks at first glance there can have some tricks.
Yes. However, implicit derivatives aren’t available outside fragment shaders, so functions which depend upon them will always sample from the base mipmap level.
The same as for any other shader.
Create a texture, bind it to a specific texture image unit, store the index of that unit (e.g. 0 for GL_TEXTURE0) in a uniform variable with glUniform1i(). The GLSL variable must be of a sampler type which matches the texture’s target (e.g. sampler2D for GL_TEXTURE_2D).
Within the shader you can use any of the texture query functions listed in the GLSL specification. If you want to retrieve texels using integer array indices, use texelFetch(). If you want to use a normalised coordinate vector, use texture(), textureLod(), textureGrad() etc.
I would say that this kind of looping all around the values will certainly lead to very poor performances. The double loop will make things even worse.
An edge links two vertices. So the texture at the vertex position should be white too if the vertex belong to an edge. So querying the texture at the texture coordinate of each vertex of each edge of the input triangle should be far enough.
Finally, you can have a look at this paper, which seems to do what you want to do.
The paper itself seems to do the opposite of what I want to do, starting from geometry and then rendering an image, whereas I want to try and get geometry from an image. I’ll see if it can kickstart the flow of some creative juices though.
I thought maybe I could use some kind of edge detection convolution kernel in the fragment shader to output gl_fragCoord to a VBO, and then use the geometry shader to link those vertices into lines. I can then find the intersection point of the longest lines in both the X and Y axes and output that as the centre of my shape.
Guys, I’ve been trying to post this same post for a while now, it just won’t seem to work; it says something about URLs?
Edge detection in the fragment shader (or a compute shader) is a viable option. But that will give you a set of points in unspecified order; you’ll need to organise the points into line strips, and a geometry shader isn’t much use for that.
GClements, I tried to do it and then ran into that option… It’s getting too late for me to continue trying to implement this into my dissertation, so I will have to write the report with what I’ve got so far (which unfortunately isn’t much). My knowledge of sorting algorithms is limited, is there any particular one you guys would suggest?
Additionally, there would be an output of of a vec4(x, y, z, 1/w) for each fragment. Could they not be sorted so that the vec4s with the same value of x, are stored next to each-other, and then those can be passed through the geometry shader as lines? I’m just throwing stuff at the wall and seeing what’ll stick at this point…
For sorting on the GPU, either even-odd mergesort or bitonic sort (both are O(n*log2(n)), but bitonic sort has better locality). But that wouldn’t necessarily help much; the hard part is collating the points into line segments.
They could, but that isn’t going to give you anything resembling a correct result.
Also, you would probably want to avoid having to order the points as they’re generated, as that is going to harm parallelism and thus performance.
If the edge-detection algorithm involves determining the line equation for the edge, then I’d suggest clustering (e.g. k-means) based upon that. Points can then be sorted based upon distance along the line (i.e. the dot product of the point’s position and edge’s tangent vector).