Learning GL 33 from GLES 2

Hi, as it is my first time here, I would like to introduce myself as an ivy league educated programmer without a degree; while I do not pretend to be at Bill Gate’s level I had a chance to sit with him at MTV Studios for ‘the Notorious B.G’ filming. I asked him one question off of film, “What do you think of linux?” “It’s an annoyance,” was his reply.

My question is, do I need to call glDrawElementsInstanced in order to get an gl_InvocationID in the shader? I am at a stopping point with my project and would like some help. I have code available if needed.

The project is from a 2017 animation contest.

I am attempting a more solid approach with more advanced opengl; hopefully multisampled framebuffer objects.

No. Why would you think that you might need this specific draw call?

Check out these sections in the wiki:

[ul]
[li]Geometry_Shader#Inputs [/li][li]Tessellation_Control_Shader#Inputs [/li][/ul]

I am, or was, confused about the language of the rendering pipeline. In GLES 2, the shaders are simple, tessellation (location) and fragment (color) processing. With the addition of the geometry shader in GL 33 my programming technique is to use it to modify the 3D camera projections of the properly termed tessellation (vertex) stage. I looked directly here:

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/gl_InvocationID.xhtml

and the verbiage confused me, and being mostly self taught in opengl, I decided to ask for help and take a break before proceeding.

My current understanding is that the gl_InvocationID allows for multiple instances of the same tessellation output for repeated renderings.

To admin: I am still experiencing issues with my project, would you leave this thread open until I am able to map a multisampled framebuffer object to a GLFW LWJGL window?

[QUOTE=abb2104;398122]I am, or was, confused about the language of the rendering pipeline.
…geometry shader gl_InvocationID … and the verbiage confused me …

My current understanding is that the gl_InvocationID allows for multiple instances of the same tessellation output for repeated renderings.[/QUOTE]

I think I see where the disconnect is. You might have crossed the meaning of the word “instance” used in two different contexts.

[ol]
[li]gl_InvocationID for tessellation evaluation shaders just tells you which input patch vertex (control point) this shader run should handle. [/li][li]gl_InvocationID for geometry shaders (when used with geometry shader instancing) tells you which “copy” of the primitive this shader run should handle. [/li][li]Whereas, glDrawElementsInstanced is one of the calls used to launch what’s called an instanced draw call. [/li][/ol]
Though the latter two can both be used to render multiple copies of geometry, the “instancing” technique referred to in each of these is different. In the instanced draw call case, the geometry replication happens up at the draw call dispatch stage (ahead of the whole shader pipeline, including the vertex shader). Whereas in the geometry shader instancing case, the geometry replication occurs after the vertex shader before the geometry shader.

If you’re using an instanced draw call and you want to know which draw call instance you’re currently rendering, use gl_InstanceID (in the vertex shader). OTOH, if you’re using geometry shader instancing and want to know which geom shader instance you’re currently rendering, use gl_InvocationID (in the geometry shader).

I think part of the problem is that you are using words incorrectly. Or at least, not the way OpenGL does.

GL ES 2.0 does not have tessellation shaders: it has Vertex Shaders and Fragment Shaders. So when you say “tessellation”, you seem to mean “vertex”.

I took out the gl_InvocationID from your above guidelines, yet still am met without success.

Here is my Geometry shader to map a 2D framebuffer to a window:


public static CharSequence geomShader2D() {
        CharSequence ret;
        
        ret = "#version 330 core
";
        ret += "#extension GL_ARB_separate_shader_objects : enable
";
        ret += "#extension GL_ARB_gpu_shader5 : enable
";
        ret += "precision highp float;
";
        ret += "
";
        ret += "layout(triangles) in;
";
        ret += "
";
        ret += "layout(location=0) in vec2 coord[];
";
        ret += "layout(location=1) in vec2 extents[];
";
        ret += "layout(location=2) in float vert_ind[];
";
        ret += "
";
        ret += "layout(location=0) out vec2 tex_coord;
";
        ret += "
";
        ret += "layout(triangle_strip, max_vertices = 3) out;
";
        ret += "
";
        ret += "void main() {
";
        ret += "vec2 acoord = coord[0] / extents[0];
";
        ret += "tex_coord = acoord;
";
        ret += "acoord *= 2.0;
";
        ret += "acoord -= 1.0;
";
        ret += "gl_Position = vec4(acoord, 0.0, 1.0);
";
        ret += "EmitVertex();
";
        ret += "if ((int(vert_ind[0]) % 3) == 2) EndPrimitive();
";
        ret += "}
";
        ret += "
";
        ret += "
";
        
        return ret;
    }

Does the above Geometry Shader look correct?

It’d be a lot easier for folks to read if you just posted the GLSL shader without all the Java string wrappage clutter:


#version 330 core
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_gpu_shader5 : enable
precision highp float;

layout(triangles) in;

layout(location=0) in vec2 coord[];
layout(location=1) in vec2 extents[];
layout(location=2) in float vert_ind[];

layout(location=0) out vec2 tex_coord;

layout(triangle_strip, max_vertices = 3) out;

void main() {
  vec2 acoord = coord[0] / extents[0];
  tex_coord = acoord;
  acoord *= 2.0;
  acoord -= 1.0;
  gl_Position = vec4(acoord, 0.0, 1.0);
  EmitVertex();
  if ((int(vert_ind[0]) % 3) == 2) EndPrimitive();
}

Compiles fine here on desktop GL, but I haven’t looked through the logic.

I think that I am looking in the wrong place in my code. My overall goal is just to map a multisampled framebuffer object to a lwjgl window. I wrote the shaders, as I was accustomed to doing with GLES 2; however, it seems that there is a glBlitFramebuffer call that I could use. OpenGL Frame Buffer Object (FBO) . I took out the shader functions and here is my rendering call:


public void runOnce(long frameitr) {
        
        if (GLFW.glfwWindowShouldClose(this.window)) {
            this.app_logic.setDone(true);
            return;
        }
        
        if (this.active) {
            if (this.needed) {
                GL.createCapabilities();
                
                GL33.glBindFramebuffer(GL33.GL_DRAW_FRAMEBUFFER, this.texFBOMain3D[0]);
                    GL33.glEnable(GL33.GL_DEPTH_TEST);
                    GL33.glClearDepth(1.0);
                    GL33.glDepthFunc(GL33.GL_LEQUAL);
                
                    GL33.glClearColor(0.5f, 0.7f, 0.9f, 1.0f);
                    
                    GL33.glViewport(0,0,DisplayHandler.CONSTANTS.GL_WIDTH, DisplayHandler.CONSTANTS.GL_HEIGHT);
                    
                    GL33.glClear(GL33.GL_COLOR_BUFFER_BIT | GL33.GL_DEPTH_BUFFER_BIT);
                    
                    GL33.glFinish();
                    
                GL33.glBindFramebuffer(GL33.GL_DRAW_FRAMEBUFFER, 0);
                
                GL33.glBindFramebuffer(GL33.GL_READ_FRAMEBUFFER, this.texFBOMain3D[0]);
                    GL33.glViewport(0,0,DisplayHandler.CONSTANTS.WINDOW_WIDTH, DisplayHandler.CONSTANTS.WINDOW_HEIGHT);
            
                    GL33.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                    GL33.glClear(GL33.GL_COLOR_BUFFER_BIT);
                
                    GL33.glBlitFramebuffer(0, 0, DisplayHandler.CONSTANTS.GL_WIDTH, DisplayHandler.CONSTANTS.GL_HEIGHT,
                           0, DisplayHandler.CONSTANTS.WINDOW_HEIGHT - DisplayHandler.CONSTANTS.GL_HEIGHT, DisplayHandler.CONSTANTS.GL_WIDTH, 0,
                           GL33.GL_COLOR_BUFFER_BIT | GL33.GL_DEPTH_BUFFER_BIT,
                           GL33.GL_NEAREST);
                    
                    GL33.glFinish();
                GL33.glBindFramebuffer(GL33.GL_READ_FRAMEBUFFER, 0);
                
                GLFW.glfwSwapBuffers(this.window);
            }
        }
        
        GLFW.glfwPollEvents();
        
        return;
    }

Am I missing some configuration issues? Still a blank screen when trying to map the fbo.

It seems clear from your geometry shader that you don’t quite understand how a GS works. It’s not a vertex shader. The VS takes a single vertex as input and writes a single vertex as output.

A geometry shader takes a primitive as input. That’s why its input values are arrayed; if a GS takes triangles as input, then its input arrays contain 3 vertices worth of data. Your shader only ever reads index 0 from the array, so indices 1 and 2 never do anything.

A geometry shader writes primitives as output. That’s why it has the EmitVertex and EmitPrimitive functions; so that you can call them multiple times within the same GS invocation. You don’t build up primitives from multiple GS invocations; each invocations writes zero or more distinct primitives. Your shader only ever emits a single vertex. And since a triangle cannot be composed of a single vertex, nothing happens.

Presumably, your shader ought to look like this:


void main() {
  for(int i = 0; i < coord.length; ++i)
  {
    vec2 acoord = coord[i] / extents[i];
    tex_coord = acoord;
    acoord *= 2.0;
    acoord -= 1.0;
    gl_Position = vec4(acoord, 0.0, 1.0);
    EmitVertex();
  }
  EndPrimitive();
}

I would like to know more about the array output values, I got some sort of error along the lines of ‘output values must not be looped when arrayed’ when I put the tex_coord variable into an output array. There are multiple instances of the output, are they modified, overwritten? I would like to implement a geometry shader, could you explain more, Alfouse Reinheart?

There are no “array output values”, so it’s not clear what you’re talking about. You output different values for different vertices by using the same output variable, with EmitVertex calls between them. That is, each call to EmitVertex takes the current values of the output values as a single vertex. And then renders their contents undefined.

There are no “array output values” I was referring to the passing out to the fragment shader.