Nothing Rendered - Something wrong with code

Hi!

I am trying to render colored quads to the screen, using geometry shaders to convert from points to triangle strips. However, nothing is rendered to the screen. I am sure the data I pass to OpenGL is correct, so I suspect there must be something wrong with my code.

This is what I run on program initialization:


    m_program_q = glCreateProgram();
    m_vshader_q = glCreateShader(GL_VERTEX_SHADER);
    m_gshader_q = glCreateShader(GL_GEOMETRY_SHADER);
    m_fshader_q = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* vsource = LoadShader("buttons.vert");
    const GLchar* gsource = LoadShader("buttons.geom");
    const GLchar* fsource = LoadShader("buttons.frag");
    glShaderSource(m_vshader_q, 1, &vsource, NULL);
    glShaderSource(m_gshader_q, 1, &gsource, NULL);
    glShaderSource(m_fshader_q, 1, &fsource, NULL);
    glAttachShader(m_program_q, m_vshader_q);
    glAttachShader(m_program_q, m_gshader_q);
    glAttachShader(m_program_q, m_fshader_q);
    glCompileShader(m_vshader_q);
    glCompileShader(m_gshader_q);
    glCompileShader(m_fshader_q);
    glLinkProgram(m_program_q);

    delete [] vsource;
    delete [] gsource;
    delete [] fsource;

    char buf[512];
    glGetProgramInfoLog(m_program_q, 512, NULL, buf);
    std::cout << buf;
    glGetShaderInfoLog(m_vshader_q, 512, NULL, buf);
    std::cout << buf;
    glGetShaderInfoLog(m_gshader_q, 512, NULL, buf);
    std::cout << buf;
    glGetShaderInfoLog(m_fshader_q, 512, NULL, buf);
    std::cout << buf;

    m_loc_pos   = glGetAttribLocation(m_program_q, "in_pos");
    m_loc_color = glGetAttribLocation(m_program_q, "in_color");
    m_loc_scaler = glGetUniformLocation(m_program_q, "scaler");

    glGenBuffers(1, &m_quadbuf_id);
    glBindBuffer(GL_ARRAY_BUFFER, m_quadbuf_id);

    glGenVertexArrays(1, &m_vao_id);
    glBindVertexArray(m_vao_id);
    glEnableVertexAttribArray(m_loc_pos);
    glEnableVertexAttribArray(m_loc_color);

    glVertexAttribIPointer(m_loc_pos, 4, GL_INT, sizeof(QuadData), NULL);
    glVertexAttribPointer(m_loc_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(QuadData), (void*)offsetof(QuadData, m_color));

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

This is how I pass data:


    glBindBuffer(GL_ARRAY_BUFFER, m_quadbuf_id);
    glBufferData(GL_ARRAY_BUFFER, (m_quaddatasize + 0x20)&(~0x1F), NULL, GL_STATIC_DRAW); // Round up the size to nearest multiple of 32
    GLubyte* buf = static_cast<GLubyte*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));

    for(size_t i = 0; i < m_panelrenderers.size(); i++) {
        MyPanelRenderer* pr = m_panelrenderers[i];
        size_t s = pr->GetQuadSize();
        if (pr->NeedUpdate())
        {
            memcpy(buf, pr->GetQuadData(), s);
            pr->SetUpdated();
        }
        buf += s;
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

And this is how I draw:


    float x = 1.0f/(float)m_windowwidth, y = 1.0f/(float)(-m_windowheight);
    glUseProgram(m_program_q);
    glUniform4f(m_loc_scaler, x, y, x, y);
    glBindVertexArray(m_vao_id);
    glDrawArrays(GL_POINTS, 0, m_quadcount);
    glUseProgram(0);
    glBindVertexArray(0);

Shaders:


#version 330

uniform vec4 scaler;

in ivec4 in_pos;
in vec4 in_color;

out vec4 vertcolor;

void main() {
    gl_Position = vec4(in_pos) * scaler;
    vertcolor = in_color;
}



#version 330

layout(points) in;
layout(triangle_strip, max_vertices = 4) out;


in vec4 vertcolor[];
flat out vec4 color;

void main() {
	vec4 p0 = vec4(gl_in[0].gl_Position.xy, 0.0, 1.0);
	vec4 p1 = vec4(gl_in[0].gl_Position.zw, 0.0, 1.0);

	gl_Position = p0;
	color = vertcolor[0];
	EmitVertex();
	gl_Position = vec4(p1.x, p0.yzw);
	EmitVertex();
	color = vertcolor[0];
    gl_Position = vec4(p0.x, p1.yzw);
	EmitVertex();
    gl_Position = p1;
	EmitVertex();
}




#version 330

flat in vec4 color;

void main() {
    gl_FragColor = ivec4(color);
}

I have tried to find what’s wrong, but whatever I change, there’s still nothing rendered. glGetError() doesn’t return any errors at all.

What version of OpenGL are you coding against? I’m not sure about versions that have geometry shaders in the core, but when it was only available through extensions you needed to do things like:


glProgramParameteriEXT(prgId, GL_GEOMETRY_VERTICES_OUT_EXT, 4);
glProgramParameteriEXT(prgId, GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS);
glProgramParameteriEXT(prgId, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP);

You’re writing to a deprecated builtin (gl_FragColor) but you haven’t asked to use the compatibility profile. The fragment shader should fail to compile. Check the link status and the info log.

Also, why cast the color from vec4 to ivec4 to vec4?

I am using 3.3 core profile. I can’t find any such functions that exists in the core profile.

The shaders are compiled successfully (at least that’s all their info logs says). However, I noticed that the program info log says “Fragment shader(s) successfully linked, vertex shader(s) successfully linked.” It doesn’t say anything about the geometry shader. Anyway, what should I do instead of using gl_FragColor? Declaring a variable with that name myself causes a compile error.

About the casting, the colors are stored as 32-bit integers in CPU memory. It is automatically cast to vec4 when passed to the vertex shader, then I don’t cast it again. Or have I missed something?

In Core Profile, you declare fragment shader outputs just like vertex or geometry shader outputs:

out vec4 FragColor;

The output position will link by default to draw buffer 0. If you were using multiple draw buffers you would need to set the output location (just like setting an input attribute location) with glBindFragDataLocation().

gl_FragColor = ivec4(color);

You’re explicitly casting to ivec4, then there is an implicit cast back to vec4. That seems meaningless.

To debug further, does this draw anything if you remove the geometry shader (i.e. screen-space GL_POINTS)? Perhaps there is other state set in your context that interacts with the geometry shader tristrips (i.e. face culling.)

Oh, so there was the unnecessary casting. I’ve fixed that now.
When I disable the geometry shader, there’s still nothing rendered. The only GL calls outside what I’ve posted is a glClear(GL_COLOR_BUFFER_BIT), and some glGetError()s.

The shader logic all looks correct. I ported it back to GLSL 1.20 (using Mac OS X here…) and it produces the expected results.

What platform / drivers are you using? Try some other simple geometry shader examples to make sure the driver works?

For reference, GLUT source that works for me (assuming Mac OS X extensions…)


// gcc -o test test.c -framework GLUT -framework OpenGL && ./test

#include <GLUT/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#define glError() { \
	GLenum err = glGetError(); \
	while(err != GL_NO_ERROR) \
	{ \
		printf("glError: %s caught at %s:%u
", (char *)gluErrorString(err), __FILE__, __LINE__); \
		err = glGetError(); \
	} \
}

#define m_quad_count 4

typedef struct {
	GLint x1, y1, x2, y2;
	GLubyte r, g, b, a;
} QuadData;

// test data
QuadData quads[m_quad_count] = {
	{ 100, 100, 110, 110, 0xFF, 0x7F, 0x3F, 0xFF },
	{ 120, 100, 130, 120, 0xFF, 0x00, 0x00, 0xFF },
	{ 140, 100, 150, 130, 0x00, 0xFF, 0x00, 0xFF },
	{ 160, 100, 170, 140, 0x00, 0x00, 0xFF, 0xFF },
};
GLint m_quaddatasize = sizeof(QuadData) * m_quad_count;
GLint m_program_q;
GLuint m_quadbuf_id;
GLuint m_vao_id;
GLint m_loc_pos;
GLint m_loc_color;
GLint m_loc_scaler;
int width = 320, height = 240;


void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
	width = w;
	height = h;
}


void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	float x = 1.0f/(float)width, y = 1.0f/(float)(-height);
	glUseProgram(m_program_q);
	glUniform4f(m_loc_scaler, x, y, x, y);
	glBindVertexArrayAPPLE(m_vao_id);
	glDrawArrays(GL_POINTS, 0, m_quad_count);
	glUseProgram(0);
	glBindVertexArrayAPPLE(0);
	
	glError();
	glutSwapBuffers();
}


void init(void)
{
	// shader
	{
		GLint m_vshader_q;
		GLint m_gshader_q;
		GLint m_fshader_q;

		const GLchar* vsource =
			"#version 120
"
			"#extension GL_EXT_gpu_shader4 : require
"
			"uniform vec4 scaler;
"
			"attribute ivec4 in_pos;
"
			"attribute vec4 in_color;
"
			"varying vec4 vertcolor;
"
			"void main() {
"
			"	gl_Position = vec4(in_pos) * scaler;
"
			"	vertcolor = in_color;
"
			"}
";
		const GLchar* gsource =
			"#version 120
"
			"#extension GL_EXT_geometry_shader4 : require
"
			"#extension GL_EXT_gpu_shader4 : require
"
			"varying in vec4 vertcolor[];
"
			"flat varying out vec4 color;
"
			"void main() {
"
			"	vec4 p0 = vec4(gl_PositionIn[0].xy, 0.0, 1.0);
"
			"	vec4 p1 = vec4(gl_PositionIn[0].zw, 0.0, 1.0);
"
			"	gl_Position = p0;
"
			"	color = vertcolor[0];
"
			"	EmitVertex();
"
			"	gl_Position = vec4(p1.x, p0.yzw);
"
			"	EmitVertex();
"
			"	color = vertcolor[0];
"
			"	gl_Position = vec4(p0.x, p1.yzw);
"
			"	EmitVertex();
"
			"	gl_Position = p1;
"
			"	EmitVertex();
"
			"}
";
		const GLchar* fsource =
			"#version 120
"
			"#extension GL_EXT_gpu_shader4 : require
"
			"flat varying vec4 color;
"
			"void main() {
"
			"	gl_FragColor = color;
"
			"}
";
	
		m_program_q = glCreateProgram();
		m_vshader_q = glCreateShader(GL_VERTEX_SHADER);
		m_gshader_q = glCreateShader(GL_GEOMETRY_SHADER_EXT);
		m_fshader_q = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(m_vshader_q, 1, &vsource, NULL);
		glShaderSource(m_gshader_q, 1, &gsource, NULL);
		glShaderSource(m_fshader_q, 1, &fsource, NULL);
		glAttachShader(m_program_q, m_vshader_q);
		glAttachShader(m_program_q, m_gshader_q);
		glAttachShader(m_program_q, m_fshader_q);
		glCompileShader(m_vshader_q);
		glCompileShader(m_gshader_q);
		glCompileShader(m_fshader_q);

		glProgramParameteriEXT(m_program_q, GL_GEOMETRY_VERTICES_OUT_EXT, 4);
		glProgramParameteriEXT(m_program_q, GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS);
		glProgramParameteriEXT(m_program_q, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP);
		glLinkProgram(m_program_q);
		
		m_loc_pos   = glGetAttribLocation(m_program_q, "in_pos");
		m_loc_color = glGetAttribLocation(m_program_q, "in_color");
		m_loc_scaler = glGetUniformLocation(m_program_q, "scaler");
	}
	
	// buffer
	{
		glGenVertexArraysAPPLE(1, &m_vao_id);
		glBindVertexArrayAPPLE(m_vao_id);

		glGenBuffers(1, &m_quadbuf_id);
		glBindBuffer(GL_ARRAY_BUFFER, m_quadbuf_id);

		glEnableVertexAttribArray(m_loc_pos);
		glEnableVertexAttribArray(m_loc_color);
		glVertexAttribIPointerEXT(m_loc_pos, 4, GL_INT, sizeof(QuadData), NULL);
		glVertexAttribPointer(m_loc_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(QuadData), (void*)offsetof(QuadData, r));
	
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArrayAPPLE(0);
	
		// data upload
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_quadbuf_id);
			glBufferData(GL_ARRAY_BUFFER, (m_quaddatasize + 0x20)&(~0x1F), NULL, GL_STATIC_DRAW); // Round up the size to nearest multiple of 32
			GLubyte* buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
		
			memcpy(buf, quads, m_quaddatasize);
		
			glUnmapBuffer(GL_ARRAY_BUFFER);
			glBindBuffer(GL_ARRAY_BUFFER, 0);
		}
	}

	glError();
}


int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(width, height);
	glutCreateWindow("Geometry shader rects");

	init();
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutMainLoop();
	return 0;
}

I tried doing what I want with OpenGL 2.1 instead. It didn’t work either, which makes me believe there may be something wrong with how I create the context. But at least I’m getting the versions I’m asking for (3.3 core / 4.0 compatibility). I will try using GLUT instead of GLFW to see if that eliminates my problem.

I solved the problem:

glBufferData(GL_ARRAY_BUFFER, (m_quaddatasize + 0x20)&(~0x1F), NULL, GL_STATIC_DRAW);

This deleted the data currently in the buffer.