Tried to switch to geometry shaders for my square & triangle faces but ran into an issue with input, the example I followed didn’t specify an array limit for gl_in[] but when I try to compile my glsl it complains it needs a limit, yet this would defy the purpose of the geometry shader (at least the way I’m trying to use it), someone mind taking a look at telling me if there’s a way to go about doing it how I’ve tried:
#version 430
uint vertices = 3;
uint uquarter = ~0u / 4;
double dquarter = double(uquarter);
void emit_vertex( vec4 PosPoint, uint x, uint y )
{
vec4 point = { 0.0, 0.0, 0.0, 0.0 };
point.x = float(double(x) / dquarter);
point.y = float(double(y) / dquarter);
point.w = 1.0;
point.xy += PosPoint.xy;
gl_Position = point;
EmitVertex();
}
void main()
{
for ( int i = 0; i < gl_in.length(); ++i )
{
vec4 PosPoint = gl_in[i].gl_Position;
uint v, qtr = ~0u / 4, oct = ~0u / 8;
double aim;
double cap = double(~0u);
double max = double(3);
for ( v = 0, aim = 0.0; v < 3; ++v, ++aim )
{
uint rotate = uint((aim / max) * cap);
uint linear = rotate % qtr;
uint curved = linear + (linear / 3);
/* Normal vertex */
emit_vertex( PosPoint, linear, uquarter - linear );
/* Curve vertex */
if ( linear < oct )
emit_vertex( PosPoint, curved, uquarter - linear );
else
emit_vertex( PosPoint, linear, uquarter - curved );
}
}
}
Making a working GS requires that you specify certain things. Among them is what primitive type the GS is made for. That means that every GS is specific to a particular primitive, so the array size of the input is specific to that primitive size. You don’t have to explicitly write this size in your shader anywhere, but you do have to specify the input primitive which defines the input size.
Is there a way to declare that it be used for any primitive? I’m designing my shader around that, I REALLY do not want to waste bytes on duplicate shaders for different types that do the exact same thing, it’s really wasteful and error prone.
Well that’s silly, there’s absolutely no reason it should require that, vertex & color shaders can work without knowing if they’re working with triangles, lines or points, there’s no reason the geometry shader needs to know either, it should only deal with the buffer (which also seems weird to me, isn’t the point to generate a shape around a point? why does it need to access the buffer of points when it’s only dealing with one point per usage anyways?), oh well, I’ve set it to points for now but I still see it as shooting devs in both feet for no good reason.
Also having another strange issue with a uniform being “inactive” despite being used, originally was used in vertex shader by I’ve just switched that to geometry shader as it made more sense there.
#version 430
layout(points) in;
uint vertices = 3;
uint uquarter = ~0u / 4;
double dquarter = double(uquarter);
uniform ivec2 WinLimit;
uniform vec2 WinScale;
void emit_vertex( vec4 PosPoint, uint x, uint y )
{
vec4 point = { 0.0, 0.0, 0.0, 0.0 };
point.x = float(double(x) / dquarter);
point.y = float(double(y) / dquarter);
point.w = 1.0;
point.xy *= WinScale.xy;
point.xy += PosPoint.xy;
gl_Position = point;
EmitVertex();
}
void main()
{
for ( int i = 0; i < gl_in.length(); ++i )
{
vec4 PosPoint = gl_in[i].gl_Position;
uint v, qtr = ~0u / 4, oct = ~0u / 8;
double aim;
double cap = double(~0u);
double max = double(3);
for ( v = 0, aim = 0.0; v < 3; ++v, ++aim )
{
uint rotate = uint((aim / max) * cap);
uint linear = rotate % qtr;
uint curved = linear + (linear / 3);
/* Normal vertex */
emit_vertex( PosPoint, linear, uquarter - linear );
/* Curve vertex */
if ( linear < oct )
emit_vertex( PosPoint, curved, uquarter - linear );
else
emit_vertex( PosPoint, linear, uquarter - curved );
}
}
}
Getting this output:
make debug=1 run
...
cd bin && ./d-check_extra.elf
Attempting to open 'libd-extraglfw.so' & 'libd-extragl.so'
Creating program '[vfxapp.pyramid]'
text = 'point.glsl'
point=shaders/point.glsl
text = '2d-shape.glsl'
shape=shaders/2d-shape.glsl
text = 'pixel.glsl'
shaders/pixel.glsllsl
src/extra/viewfx/vfxapp.c:273: Error 0x00000002 (2) ENOENT
Unable to open 'shaders/pixel.glsllsl'
source = GL_DEBUG_SOURCE_API, defect = GL_DEBUG_TYPE_ERROR, weight = GL_DEBUG_SEVERITY_HIGH, seekid = 1 (GL_ID_UNKOWN)
report = GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
test/extra/main.c:347: WinLimit not found
source = GL_DEBUG_SOURCE_API, defect = GL_DEBUG_TYPE_ERROR, weight = GL_DEBUG_SEVERITY_HIGH, seekid = 1 (GL_ID_UNKOWN)
report = GL_INVALID_OPERATION in glGetUniformLocation(program not linked)
test/extra/main.c:374: WinScale not found
source = GL_DEBUG_SOURCE_API, defect = GL_DEBUG_TYPE_ERROR, weight = GL_DEBUG_SEVERITY_HIGH, seekid = 1 (GL_ID_UNKOWN)
report = GL_INVALID_OPERATION in glGetAttribLocation(program not linked)
test/extra/main.c:399: Error 0xFFFFFFFF (-1) EUNKNOWN
test/extra/main.c:503: Error 0xFFFFFFFF (-1) EUNKNOWN
test/extra/main.c:254: Error 0xFFFFFFFF (-1) EUNKNOWN
Compilation finished successfully.
WinLimit I understand but WinScale? That IS in use so it should be locatable, any ideas?
generate shapes using just the center point and vertex count, wether the shape is connected to a bigger primitive or not is irrelevant to the shader. I’m basically treating all standard 2d shapes as circles, just with varying numbers of vertices.
It has to know because that is its function. Your problem is that you want to do something that GS’s aren’t meant to do. What you seem to want is a vertex shader that can output multiple vertices. GS’s aren’t that.
A GS takes as input a primitive and outputs zero or more primitives. That’s its job. Taking a primitive requires knowing what primitive it is taking, because again, that’s its job.
The tool you want seems to be a compute shader. There, each invocation can read a separate vertex from an SSBO and write 6 vertices to a different SSBO. You can then use that buffer as source input data to a rendering operation. This works better because shared vertices don’t generate duplicate data (though if you’re using indexed rendering, you will have to change your indices accordingly).
Your problem is that the program didn’t link, almost certainly because the GS lacked an output declaration too. A GS needs a layout in declaration, but it needs other stuff too, as I linked to.
Uh, isn’t gl_Position an output though? Quite the important output too.
Edit: Side note, switched to compute shader as you suggested, compiles fine but haven’t been able to test it because of some bazar memory issue (unrelated to opengl, just mentioning for the curious), somehow my temporary buffer for paths is being both wiped & restored, the wiping is intentional, it’s to ensure the constructed path ends where I expect it to, however the weird part is that even though the debugger shows it being cleared it somehow gets restored before the next path is constructed, creating a corrupt path by the end of it, for example where I should get “shaders/color.glsl” I instead get “shaders/color.glsllsl”, I know where the end “lsl” came from but don’t understand how it’s still there after being wiped, I even tried looking for old pointers but even that doesn’t turn up anything, as far as I can find this situation should be impossible and yet it occurs.
I don’t know what you mean by that. As previously stated, a GS takes a primitive as input and outputs zero or more primitives. There are multiple kinds of primitives you can output, so your GS needs to specify what type of primitive gets output.
That is, a GS doesn’t have to output the same kind of primitive as it inputs. You can turn points into triangles, triangles into lines, etc.
A vertex, by itself, doesn’t mean anything. It only gains meaning when it (and others) are aggregated into one or more primitives. The GS’s output primitive type tells what kind of primitive the GS’s output vertices will be aggregated into.
I get specifying the output, that’s fine, but there still shouldn’t be a need to specify the input, that should be optional, how are GPUs supposed to know whether a shader is intended for many kinds of input or just a single? It should be set to all by default and let the developer switch to specific if they’re expecting only specific.
What you have said doesn’t make sense with the OpenGL rendering pipeline.
A GS takes a primitive as input. But a vertex shader outputs a series of vertices. Therefore, for a GS (or rendering in general) to make sense, those vertices must be assembled into a set of primitives.
Given a series of vertices, assembling a primitive involves reading some of these vertices based on a particular algorithm. This includes retaining the first vertex in a triangle fan (since each triangle in the fan has the same first vertex), front/back facing calculation for alternating triangles in a strip, etc. That algorithm is the primitive type.
A GS does not just get access to however many vertices were spat out by prior vertex processing stages. It receives a primitive. That means the vertex stream has to be assembled into primitives. So there needs to be an algorithm for that.
The GS’s input primitive type.
As previously stated, what you want is not what a GS is intended to provide.
If you want something more free-form, then you’re looking for NVIDIA’s mesh shader vertex pipeline. Of course, that’s an NVIDIA-only technology.
Then it’s been given a shitty name, instead of geometry (which implies any shape) it should been called the primitive shader, that would be more intuitive, either way it doesn’t serve the purpose I expected it to be doing so I’m trying out the compute shader as soon as I can fix this poxy corrupt path/buffer bug.
Compute shader wasn’t working out so I’ve resorted to using gl_VertexID and a uniform to decide how many vertices are expected for the referenced center point (for now the center is duplicated, I’ll switch to indexed later).
Was about to say “still having issues with uniforms though” but as I was typing I realised I forgot to send output to the fragment shader, fixing that resolved the issue quick smart, now I just gotta track down a segfault
Not sure if it’ll get you what you want. But you can output multiple points from a single vertex shader execution, and then render them with a draw call using whatever primitive type you want. Just use transform feedback in the middle.
That sounds like it might work, do you mind doing a quick and dirty example for a square? Just use a flat list of vertices inside the shader that you just add the input vertex to.