0
$\begingroup$

I am trying a simple passthrough just to get a feel for the geometry shader. I am taking in a single point and trying to output that point from the geometry shader, it works with the vertex and fragment shaders, but when I add in the geometry shader I get no output. There are no compilation errors neither.

I am using python's moderngl and have it set to render as points with vao.render(moderngl.POINTS).

vertex shader

#version 330

in vec3 point;
in vec4 color;

out vec3 v_point;
out vec4 v_color;

void main(){
    v_point = point;
    v_color = color;
}

geometry shader

#version 330

layout (points) in;
layout (points, max_vertices=1) out;

in vec3 v_point[1];
in vec4 v_color[1];

out vec4 g_color;

void main() {
    gl_Position = vec4(v_point[0], 1.0);
    EmitVertex();
    EndPrimitive();
    g_color = v_color[0];
}

fragment shader

#version 330

in vec4 g_color;

out vec4 f_color;

void main() {
    f_color = g_color;
}

python code:

import moderngl
import numpy as np

from PIL import Image

ctx = moderngl.create_standalone_context()

shaders_source = {}

with open("vert_test.glsl", "r") as f:
    shaders_source['vertex_shader'] = f.read()

with open("geom_test.glsl", "r") as f:
    shaders_source['geometry_shader'] = f.read()

with open("frag_test.glsl", "r") as f:
    shaders_source['fragment_shader'] = f.read()

prog = ctx.program(**shaders_source)

points = np.array([
    [0.0, 0.0, 0.0, 1, 0, 0, 1],
])

ctx.enable(moderngl.PROGRAM_POINT_SIZE)
vbo = ctx.buffer(points.astype('f4').tobytes())
vao = ctx.simple_vertex_array(prog, vbo, 'point', 'color')

fbo = ctx.simple_framebuffer((512, 512))

fbo.use()

fbo.clear(0.0, 0.0, 0.0, 1.0)

vao.render(moderngl.POINTS)

Image.frombytes('RGB', fbo.size, fbo.read(), 'raw', 'RGB', 0, -1).show()
$\endgroup$
2
$\begingroup$

You are setting g_color after the vertex have been emitted so it will have no effect. EmitVertex() will emit the poition and whatever values are current in the out attributes. Set the attribute before emitting the vertex.

The gemometry shader can create geometry by emitting multiple vertices or destroy geometry by not emitting something. This is why the order of the Emit functions are very important.

The second issue is that you are enabling PROGRAM_POINT_SIZE. This requires the shader to set gl_PointSize. If this is not set the behaviour is undefined. Depending on drivers the default point size might be 0 or 1. It seems intel drivers use 0 as the default causing the point to be discarded.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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