PDA

View Full Version : glDrawArrays(GL_POINTS,...) only drawing a single point



TravisG
11-24-2013, 11:18 AM
I would like to ask you to have a look at this question (copy and pasted from gamedev.stackexchange since I can't post URLS as a new user):

I have been debugging this for a while but I can't seem to find the issue.

I created a framebuffer for layered rendering like this


GLuint buffer;
glGenFramebuffers(1,&buffer);
glBindFramebuffer(GL_FRAMEBUFFER,buffer);

glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTAC HMENT0,textures[0],0);

GLenum blub[] = {GL_COLOR_ATTACHMENT0};

glDrawBuffers(1,blub);

where textures[0] is a 3D texture for layered rendering. The texture is texture complete, using nearest for min and mag filtering, no mip mapping, clamp to edge for s,t and r. I can sample from it fine (I initialize the texture to a color based on the z coordinate inside the 3d texture, it's initialized fine as well). The size of the 3D texture right now is 32x32x32 texels.

The framebuffer is framebuffer complete (checked it using glCheckFramebufferStatus).

Then I create and fill a buffer with vertex data for the points like this:


vector<vec2> points;
points.push_back(vec2(0.0f,0.0f)); //should draw in the middle
points.push_back(vec2(0.5f,0.5f)); //3/4th in each direction
points.push_back(vec2(-0.5f,-0.5f)); //opposite of second point
points.push_back(vec2(-0.95f,-0.95f)); //first texel on the bottom left

glGenBuffers(1,&result);

glBindBuffer(GL_ARRAY_BUFFER,result);
glBufferData(GL_ARRAY_BUFFER,points.size()*2*sizeo f(float),&points[0],GL_STATIC_DRAW);

where vec2 is the vec2 floating point vector class provided by GLM.

Then I render it by doing this:


glViewport(0,0,textureSizeX,textureSizeY);
glBindFramebuffer(buffer);
glUseProgram(shader);
glBindBuffer(GL_ARRAY_BUFFER,_pointbuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
glDrawArrays(GL_POINTS,0,4);

where shader is a shader constructed from vertex, geometry and fragment shaders. It compiles fine without warnings. Depth and stencil testing are disabled. textureSizeX and textureSizeY are the width and height of the 3D texture.

Vertex shader:


#version 430

layout(location =0) in vec2 pos;


void main()
{
gl_Position = vec4(pos.xy,0,1);
}

Geometry shader:


#version 430

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

void main()
{
gl_Layer = 0;
gl_Position = vec4(gl_in[0].gl_Position.xy,1,1);
gl_PointSize = 1.0f;


EmitVertex();
EndPrimitive();
}

Fragment shader:


#version 430


out vec4 outcolor;

void main()
{
outcolor = vec4(0,1,0,0);
}

However, only the first point is drawn, as expected in the middle of layer 0 of the 3D texture. I can move around the coordinates of the first point and get the expected results. The points after the first point are always ignored, however. What am I doing wrong?

Hardware is GTX 770 with driver version 331.82 (latest version). Tested it on GT 555M (Notebook GPU), same results. The OpenGL device context is version 4.3.

edit: Tried so far: When I extend the attribute input of the vertex data to a vec4, and change the argument in glVertexAttribPointer accordingly, as expected the z and w components of the vec4 contain the coordinates of the second point, so the positions seem to be in memory as expected.

Similarly, if I change the offset using glVertexAttribPointer (e.g. putting (void*)(sizeof(vec2)*3) as the last parameter), the respective point is drawn.

Just to test if something may be wrong with the rasterization in general, I tried emitting triangles instead of points in the geometry shader. This works as expected.

I've been debugging this issue for about 20 hours now, and I don't feel like I'm closing in to the solution.

TravisG
11-24-2013, 12:26 PM
As a small update: Somehow the values arriving at gl_in[x] seem to be broken / undefined. When I try to render triangles instead of points, I can output triangles if I output constants from the geometry shader. However, if I change one of the constants to an input from gl_in[x], the position of that specific vertex seems to be an implementation defined constant which is the same for all gl_ins, i.e. gl_in[0].gl_Position, gl_in[1]... etc.. It's not vec4(0,0,0,0), the point seems to be somewhere around vec4(-0.2,-0.5,?,?);

Here's the geometry shader that demonstrates this error:


#version 430

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

void main()
{

gl_Position = vec4(-1.0f,-1.0f,0.5f,1.0f);
//gl_Position = gl_in[0].gl_Position;
EmitVertex();

gl_Position = vec4(-1.0f,0.0f,0.5f,1.0f);
//gl_Position = gl_in[1].gl_Position;
EmitVertex();


//gl_Position = vec4(1.0f,-1.0f,0.5f,1.0f);
gl_Position = gl_in[0].gl_Position;
EmitVertex();

EndPrimitive();
}

Note that this is essentially the pass-through example shader given from Wikipedia. Something very weird is going on here and I have no idea how to fix it.

TravisG
11-24-2013, 12:45 PM
Scratch that, using layout(location =0) in vec2 pos; and 0 in both of the function calls on the C++ side fixed it. Anybody knows why this is? Querying max attribute locations gives me 16 on my GTX 770, so layout(location = 5) and glEnableVertexAttribArray(5) plus glVertexAttribPointer(5) should work, shouldn't it?

Dark Photon
11-24-2013, 06:09 PM
Should, yes, barring a syntax error.