PDA

View Full Version : Geometry shader grief



planetexp
12-20-2017, 04:08 AM
I'm still learning but this geometry shader is giving me no end of trouble and asking for some help.

My system is a MacBook Pro 2015 with Intel Iris which supports OpenGL 4.1

I'm drawing a plane using an index buffer with


glDrawElements(GL_TRIANGLE_STRIP, this->size(), GL_UNSIGNED_SHORT, 0);

Which using a the following vertex and fragment shader works perfectly. But when the geometry shader comes in I get nothing. I've tried all kinds of combination but it still gives me absolutely nothing as output. Anyone got ideas what I am doing wrong?

Here's the shaders (should simply be pass through)


// Vertex
const char* vert = R"glsl(
#version 410

layout (location = 0) in vec2 in_position;

uniform mat4 MVP;

void main() {
gl_Position = MVP * vec4(in_position.x, 0.0f, in_position.y, 1.0f);
}

)glsl";

// Geometry
const char* geom = R"glsl(
#version 410

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

void main() {

for (int i = 0; i < 3; ++i) {
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
)glsl";

// Fragment
const char* frag = R"glsl(
#version 410

out vec4 out_color;

void main() {
out_color = vec4(1.0f);
}
)glsl";


I've tried passing the colour through from vertex-geom-fragment, varying inputs, not using an MVP transform and all kinds of things. Am I missing something vital with this simple setup? I'm not setting up and glProgramParameteri because I assumed they were not necessary with geom layouts.

Thanks
Fred

Silence
12-21-2017, 01:00 AM
What you posted does not look bad.

So:
as usual, check for any OpenGL errors
copy/paste a GS example from the net and compare with what you have

planetexp
12-22-2017, 03:15 AM
Good thinking. It seems like I am actually getting error code 0x502 which is GL_INVALID_OPERATION when drawing this shape. I tried to create a minimal working example but I don't really know what I am doing wrong at this point. Been doing trial and error the last 2 days without luck. Here's the code in it's entirety:

It works perfectly without the geometry shader but with it I get error 0x502. How would I go about hunting this down? Could it somehow be that geometry shaders are not supported on my GPU or something similarly silly?

OpenGL 4.1, latest glbinding and glfw




#include <iostream>

#define GLFW_INCLUDE_NONE
#include <glbinding/gl/gl.h>
#include <glbinding/Binding.h>

#define GLFW_DLL
#include <GLFW/glfw3.h>

using namespace gl;


void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s\n", description);
}


void create_program(GLuint &handle, GLuint *shaders) {

handle = glCreateProgram();

for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
glAttachShader(handle, shaders[i]);
}

glLinkProgram(handle);

// clean up after successful linking
for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
glDetachShader(handle, shaders[i]);
}
}

// Comment to toggle geometry shader
#define GEOMETRY_SHADER


#ifdef GEOMETRY_SHADER
#define NUM_SHADERS 3
#else
#define NUM_SHADERS 2
#endif

// Globals
GLuint prog;
GLuint vbo[1];
GLuint vao; // not needed?
GLuint shaders[NUM_SHADERS];


// Vertex shader
const char* vert = R"glsl(
#version 410

layout (location = 0) in vec2 in_position;

out gs_PerVertex {
vec4 color;
} vs_out;

//uniform mat4 MVP;

void main() {

gl_Position = vec4(in_position.x, in_position.y, 0.0f, 1.0f);
// vs_out.color = vec4(1.0f); // white
}

)glsl";

// Geometry shader
const char* geom = R"glsl(
#version 410

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

// Input block
in gs_PerVertex {
vec4 color;
} gs_in[];

// Output block
out gs_PerVertex {
vec4 color;
} gs_out;

void main() {

for (int i = 0; i < 3; ++i) {
gl_Position = gl_in[i].gl_Position + vec4(0.3);
// gs_out.color = gs_in[i].color;
EmitVertex();
}
EndPrimitive();

}
)glsl";

// Fragment shader
const char* frag = R"glsl(
#version 410

in gs_PerVertex {
vec4 color;
} gs_in;

// in vec4 color;
out vec4 out_color;

void main() {

// out_color = gs_in.color;
out_color = vec4(1.0f);

}
)glsl";


void compile_info(const GLuint shader) {
GLint status(0);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

if (1 != status) {
GLint maxLength(0);
GLint logLength(0);

glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

GLchar log[maxLength];
glGetShaderInfoLog(shader, maxLength, &logLength, log);
fprintf(stderr, "Compiling shader %u failed: %s", shader, log);

}
}

void create_shader(GLuint &shader, GLenum type, const char* src) {

shader = glCreateShader(type);

glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);

// check for errors
compile_info(shader);
}

void link_info(const GLuint program) {
GLint status(0);
glGetProgramiv(program, GL_LINK_STATUS, &status);

if (1 != status) {
GLint maxLength(0);
GLint logLength(0);

glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

GLchar log[maxLength];
glGetProgramInfoLog(program, maxLength, &logLength, log);

fprintf(stderr, "Linking of program failed: %s\n", log);
}
}

void create_program(GLuint &_p, GLint *_s) {
_p = glCreateProgram();

if(_p == 0)
fprintf(stderr, "Could not create shader program.\n");

for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
glAttachShader(_p, _s[i]);
}

glLinkProgram(_p);

// Check for errors.
link_info(_p);

// Clean up.
for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
glDetachShader(_p, _s[i]);
}
}


/// Check for errors. Poll gl for all error messages and print to
/// stderr.
// TODO convert these messages to strings (with glfw?)
void check_errors() {
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "OpenGl encountered an error with code: %d\n", err);
}
}

struct Point2D {
float x, y;
};

const Point2D vertices_data[] = {
{-0.5, -0.5},
{0.5, -0.5},
{-0.5, 0.5},

{-0.5, 0.5},
{0.5, -0.5},
{0.5, 0.5}
};

int init_resources() {

// Generate shader and shader program handles
#ifdef GEOMETRY_SHADER
create_shader(shaders[0], GL_VERTEX_SHADER, vert);
create_shader(shaders[1], GL_GEOMETRY_SHADER, geom);
create_shader(shaders[2], GL_FRAGMENT_SHADER, frag);
#else
create_shader(shaders[0], GL_VERTEX_SHADER, vert);
create_shader(shaders[1], GL_FRAGMENT_SHADER, frag);
#endif

create_program(prog, shaders);

GLint a_pos = glGetAttribLocation(prog, "in_position");

if (a_pos == -1) {
fprintf(stderr, "Could not find attribute in shader.");
}

glGenBuffers(1, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW);

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(/*index:*/a_pos, /*size:*/2, /*type:*/GL_FLOAT, /*norm:*/GL_FALSE, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

glBindVertexArray(0);

check_errors();

return 1;
}

void draw_scene() {
glBindVertexArray(vao);
glUseProgram(prog);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);

glBindVertexArray(0);

check_errors();
}


void free_resources() {
glDeleteProgram(prog);
}


int main(int argc, const char * argv[]) {
GLFWwindow *window;
int width, height;

glfwSetErrorCallback(error_callback);

if (!glfwInit())
return -1;

glfwDefaultWindowHints(); // ?
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
glfwWindowHint(GLFW_RESIZABLE, false);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); // ?

window = glfwCreateWindow(640, 480, "Hello", NULL, NULL);

if (!window) {
glfwTerminate();
return -1;
}

glfwGetFramebufferSize(window, &width, &height);
glfwMakeContextCurrent(window);
glbinding::Binding::initialize(false);

init_resources();

// Just draw once to check for errors
draw_scene();
glfwSwapBuffers(window);

// Main loop
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
// draw_scene();
// glfwSwapBuffers(window);
}

// Clean up.
free_resources();

glUseProgram(0);
glDisableVertexAttribArray(0);

glfwDestroyWindow(window);
glfwTerminate();

return 0;
}

GClements
12-22-2017, 07:10 AM
It works perfectly without the geometry shader but with it I get error 0x502. How would I go about hunting this down?

Find which command generates the error. Set a breakpoint inside check_errors() when, then start adding more calls. Once you've identified the command (a call to check_errors() immediately before it succeeds, a call immediately after reports an error), refer to its documentation in the reference pages or (preferably) the specification to see the conditions which can cause that particular error.



Could it somehow be that geometry shaders are not supported on my GPU or something similarly silly?

OpenGL 4.1, latest glbinding and glfw

Geometry shaders are a requirement of OpenGL 3.2 and above.

arekkusu
12-22-2017, 09:51 AM
I don't really know what I am doing

Your error has nothing to do with OpenGL. You need to understand how pointers work:


void create_program(GLuint &handle, GLuint *shaders) {
...
for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i)

On x86_64, sizeof(GLuint *) is 8, and sizeof((GLuint *)[0]) is 4, so this always loops twice.



How would I go about hunting this down?

* Learn to use your platform's debugger. (https://www.opengl.org/discussion_boards/showthread.php/182565-No-polygons-displayed-when-porting-code-from-Windows-to-OS-X?p=1254165&viewfull=1#post1254165)

* Learn how to introspect GL state. You're checking errors, compile state, and link state. But not the object state; glGetProgram will tell you everything about your linked program (like how many shaders are attached to it). glValidateProgram's log in this case would have helpfully informed you: "Validation Failed: Program does not contain fragment shader. Results will be undefined."

planetexp
12-22-2017, 01:58 PM
Your error has nothing to do with OpenGL. You need to understand how pointers work:

Holy sweet jesus, I didn't realise I just passing a pointer. This was the issue. There was another create_program() function that I was calling as well. I didn't think to look there. Thanks a million!



* Learn to use your platform's debugger. (https://www.opengl.org/discussion_boards/showthread.php/182565-No-polygons-displayed-when-porting-code-from-Windows-to-OS-X?p=1254165&viewfull=1#post1254165)

Thank you for the link, I've been looking how to debug on macOS for ages.

Programming is like a giant game of Where's Waldo sometimes...

Cheers
Fred