Hello there, long time since my last post here!
I was reading a little bit about geometry shaders here, and after finding out that there’s support in shadestyle for them, I decided to give it a try .
I tried a simple application, namely transform a LINE primitive type into a pair of triangles forming a rectangle to achieve a “widened” line.
Here’s some little code

``````import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.vertexBuffer
import org.openrndr.draw.vertexFormat
import org.openrndr.math.Vector3

fun main() = application {
configure {
width = 1000
height = 1000
}

program {
val bufferVertices = vertexBuffer(vertexFormat {
position(3)
}, 2)

bufferVertices.put {
write(Vector3(0.0, -200.0, 0.0))
write(Vector3(0.0, 200.0, 0.0))
}

extend {
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.WHITE
vertexTransform = """
x_position += vec3(100.0, 0.0, 0.0) * (2.0 * gl_VertexID - 1.0);
""".trimIndent()

geometryPreamble ="""
layout (lines) in;
layout (triangle_strip, max_vertices = 4) out;
""".trimIndent()

geometryTransform = """

vec3 a = vec3(gl_in[0].gl_Position);
vec3 b = vec3(gl_in[1].gl_Position);
vec3 n = normalize(b - a);
vec3 o = vec2(n.y, -n.x, 0.0);

gl_Position = vec4(a + o * 100.0, 0.0);
EmitVertex();

gl_Position = vec4(a - o * 100.0, 0.0);
EmitVertex();

gl_Position = vec4(b + o * 100.0, 0.0);
EmitVertex();

gl_Position =  vec4(b - o * 100.0, 0.0);
EmitVertex();

EndPrimitive();
""".trimIndent()
fragmentTransform = """
x_fill.rgb = vec3(1.0, 0.0, 0.0);
""".trimIndent()
}
drawer.translate(drawer.bounds.center)
drawer.vertexBuffer(bufferVertices, DrawPrimitive.LINES)
}
}
}
``````

If you run the code, you’ll notice that while the vertex and fragment shaders are correctly run, the geometry shader seems not to be called. To check this, just remove one of those precious semi-columns in the `geometryTransform` string, and you’ll see that the code still runs with no error, making me think the string is indeed not added to the graphic pipeline.
I have the feeling that `drawer.vertexBuffer` might not be the right place to use a geometry shader, but I couldn’t figure it out from the source code.
Has anyone successfully used geometry shaders in openRNDR?

UPDATE: This low-level approach seems to work as intended outside of shadeStyle…

``````import org.openrndr.application
import org.openrndr.draw.*
import org.openrndr.internal.Driver
import org.openrndr.math.Vector3

fun main() = application {
configure {
width = 1000
height = 1000
}

program {
val bufferVertices = vertexBuffer(vertexFormat {
position(3)
}, 2)

bufferVertices.put {
write(Vector3(0.0, -0.5, 0.0))
write(Vector3(0.0, 0.5, 0.0))
}

val vs = """
#version 330
in vec3 a_position;
uniform float t;
vec2 rotate(vec2 v, float a) {
float s = sin(a);
float c = cos(a);
mat2 m = mat2(c, s, -s, c);
return m * v;
}
void main() {
vec2 a = rotate(a_position.xy, t);
gl_Position = vec4(a, 0.0, 1.0);
}
"""

val fs = """
#version 330
out vec4 o_output;
void main() {
o_output = vec4(1.0, 0.0, 0.0, 1.0);
}
"""

val gs = """
#version 330
layout (lines) in;
layout (triangle_strip, max_vertices = 4) out;
void main(){
vec3 a = vec3(gl_in[0].gl_Position);
vec3 b = vec3(gl_in[1].gl_Position);
vec3 n = normalize(b - a);
vec3 o = vec3(n.y, -n.x, 0.0);

gl_Position = vec4(a + o * 0.02, 1.0);
EmitVertex();

gl_Position = vec4(a - o * 0.02, 1.0);
EmitVertex();

gl_Position = vec4(b + o * 0.02, 1.0);
EmitVertex();

gl_Position =  vec4(b - o * 0.02, 1.0);
EmitVertex();

EndPrimitive();
}
"""

extend {
}
}
}
``````

Thank you for sharing your discoveries

In the orx demo folder there’s just one example for geometry shaders:

I remember trying it but couldn’t make full sense of it.
I still have a bunch of uncommitted changes / tests to the three gs shader files from that example.

Maybe now that it’s fresh for you, could you take a look at that demo and see if it works? Adding some comments would be super welcome too

Cheers!

1 Like

Hello!
I have given a look at the code: the geometry shader there is “transparent”, namely it emits the exact same geometry, and doesn’t produce any new information.
Here I have modified the example

``````import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.DrawPrimitive
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.meshgenerators.boxMesh

fun main() {
application {
configure {
width = 1000
height = 1000
}
program {
val vb = boxMesh(5.0, 5.0, 5.0)
val vsCode = """
#version 410 core

in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord0;

out InVertex {
vec3 va_position;
vec3 va_normal;
} vertexOut;

uniform mat4 view;
uniform mat4 proj;
uniform mat4 model;

void main() {
vertexOut.v_addedProperty = vec4(1.0, 0.0, 0.0, 1.0);
vertexOut.va_position = a_position;
vertexOut.va_normal = a_normal;
gl_Position = vec4(a_position, 1.0);
}
""".trimIndent()
val gsCode = """
#version 410 core

layout (triangles) in;
layout (line_strip, max_vertices = 3) out;

in InVertex {
vec3 va_position;
vec3 va_normal;
} vertices[];

out vec3 va_position;
out vec3 va_normal;
out vec3 color;

uniform vec3 offset;

uniform mat4 view;
uniform mat4 proj;
uniform mat4 model;

void main() {
int i;
for(i = 0;i < gl_in.length();i++) {
gl_Position = proj * view * model * gl_in[i].gl_Position;
color = vec3(gl_in[i].gl_Position.x * 0.6, gl_in[i].gl_Position.y * 0.6, 1.0);
EmitVertex();
}
EndPrimitive();
}
""".trimIndent()
val fsCode = """
#version 410 core
in vec3 color;
out vec4 o_color;
void main() {
o_color = vec4(color, 1.0);
}
""".trimIndent()
vsCode = vsCode,
gsCode = gsCode,
fsCode = fsCode,
name = "x"
)
extend(Orbital())
extend {
drawer.clear(ColorRGBa.PINK)