Strange problems with billboard shader (Geometry shader)

Hi guys, I’ve been trying to fix this problem for a while now. And I think I’m a little crazier because of it, I’ve already posted this issue in the GameDev.net forums, but they couldn’t help me. :frowning:

So basically certain things don’t travel through the shader properly, for example, they get recognized in the geometry shader, but not in the vertex and visa-versa.

Anyways codes are below, I’ve tried so many different variations on the shaders. Including layout locations and have gotten different results from different locations.

Geometry Shader

#version 330
#extension GL_ARB_separate_shader_objects : enable



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


uniform mat4 gVP;
uniform vec3 gCameraPos;



layout (location = 1) in float inScale[1];
layout (location = 3) in vec4 inTexCoord[1];
layout (location = 2) in vec4 inColor[1];



layout (location = 3) out vec2 TexCoord;
layout (location = 2) out vec4 Color;



void main(void)
{
	vec3 Pos = gl_in[0].gl_Position.xyz;
	
	vec3 toCamera = normalize(gCameraPos - Pos);
	vec3 up = vec3(0.0, 1.0, 0.0);
	vec3 right = cross(toCamera, up);
	

	vec2 tcTL = inTexCoord[0].xy;
	vec2 tcBR = vec2(inTexCoord[0].z,inTexCoord[0].w);
	float Sc = 20.0;
	vec4 col = inColor[0];

	Pos -= (right * (Sc * 0.5));
	Pos.y -= Sc * 0.5;
	gl_Position = gVP * vec4(Pos, 1.0);
	TexCoord = vec2(tcTL.x, tcTL.y);
	Color = col;
	EmitVertex();

	Pos.y += Sc;
	gl_Position = gVP * vec4(Pos, 1.0);
	TexCoord = vec2(tcTL.x, tcBR.y);
	Color = col;
	EmitVertex();

	Pos.y -= Sc;
	Pos += right * Sc;
	gl_Position = gVP * vec4(Pos, 1.0);
	TexCoord = vec2(tcBR.x, tcTL.y);
	Color = col;
	EmitVertex();

	Pos.y += Sc;
	gl_Position = gVP * vec4(Pos, 1.0);
	TexCoord = vec2(tcBR.x, tcBR.y);
	Color = col;
	EmitVertex();

	EndPrimitive();
}

Vertex Shader

#version 330
#extension GL_ARB_separate_shader_objects : enable




in vec3 Position;
layout (location = 3) in vec2 TexCoord;
layout (location = 2) in vec4 Color;



// vertex shader

layout (location = 3) out vec2 TexCoordOut;
layout (location = 2) out vec4 ColorOut;



void main(void)
{
    gl_Position = vec4(Position, 1.0);
	TexCoordOut = TexCoord;
	ColorOut = Color;
}

Fragment Shader

#version 330
#extension GL_ARB_separate_shader_objects : enable


uniform sampler2D TextureMap;
uniform float Alpha;

// fragment shader
layout (location = 3) in vec2 TexCoordOut;
flat layout (location = 2) in vec4 ColorOut;


out vec4 outputF;



void main(void)
{
	//vec4 tex = texture(TextureMap, TexCoordOut.xy);
	//tex.a *= Alpha;
	//tex *= ColorOut;
	//if (tex.a <= 0.0)
	//{
	//	discard;
	//}
	//else
	//{
		vec4 Test = ColorOut;

		//This test will show the correct result by colouring it the correct colour, then having the texture cut out the center
		//I have gotten the correct result from the texture once, but not the colour at the same time :(
		outputF = Test - texture(TextureMap, TexCoordOut.xy);
	//}
}

Below here is c# code, the library I’m using is OpenTK. As far as I can tell from various tests is that the VBO data is infact correct.
But I’m not sure about the VAO code. I’ve referenced the VBO construction further down.

VAO code


                GL.GenVertexArrays(1, out VAOID);
                GL.BindVertexArray(VAOID);

                GL.EnableVertexAttribArray(0);
                GL.BindBuffer(BufferTarget.ArrayBuffer, VertID);
                GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
                GL.BindAttribLocation(BillboardShader, 0, "Position");

                GL.EnableVertexAttribArray(1);
                GL.BindBuffer(BufferTarget.ArrayBuffer, ScaleID);
                GL.VertexAttribPointer(1, 1, VertexAttribPointerType.Float, false, sizeof(float), 0);
                GL.BindAttribLocation(BillboardShader, 1, "inScale");

                GL.EnableVertexAttribArray(3);
                GL.BindBuffer(BufferTarget.ArrayBuffer, CoordID);
                GL.VertexAttribPointer(3, 4, VertexAttribPointerType.Float, true, Vector4.SizeInBytes, 0);
                GL.BindAttribLocation(BillboardShader, 3, "inTexCoord");


                GL.EnableVertexAttribArray(2);
                GL.BindBuffer(BufferTarget.ArrayBuffer, ColorID);
                GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);
                GL.BindAttribLocation(BillboardShader, 2, "inColor");


                GL.BindVertexArray(0);

VBO Code

if (VertID == 0)
            {
                GL.GenBuffers(1, out VertID);
                GL.BindBuffer(BufferTarget.ArrayBuffer, VertID);
            }
            else
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, VertID);

                GL.BufferData(BufferTarget.ArrayBuffer,
                    new IntPtr(Vertices.Length * Vector3.SizeInBytes),
                    IntPtr.Zero, BufferUsageHint.DynamicDraw);
            }

            GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
                    new IntPtr(Vertices.Length * Vector3.SizeInBytes),
                    Vertices, BufferUsageHint.DynamicDraw);

            if (ScaleID == 0)
            {
                GL.GenBuffers(1, out ScaleID);
                GL.BindBuffer(BufferTarget.ArrayBuffer, ScaleID);
            }
            else
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, ScaleID);

                GL.BufferData(BufferTarget.ArrayBuffer,
                    new IntPtr(Scales.Length * sizeof(float)),
                    IntPtr.Zero, BufferUsageHint.DynamicDraw);
            }

            GL.BufferData<float>(BufferTarget.ArrayBuffer,
                    new IntPtr(Scales.Length * sizeof(float)),
                    Scales, BufferUsageHint.DynamicDraw);

            if (CoordID == 0)
            {
                GL.GenBuffers(1, out CoordID);
                GL.BindBuffer(BufferTarget.ArrayBuffer, CoordID);
            }
            else
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, CoordID);

                GL.BufferData(BufferTarget.ArrayBuffer,
                    new IntPtr(Coords.Length * Vector4.SizeInBytes),
                    IntPtr.Zero, BufferUsageHint.DynamicDraw);
            }

            GL.BufferData<Vector4>(BufferTarget.ArrayBuffer,
                    new IntPtr(Coords.Length * Vector4.SizeInBytes),
                    Coords, BufferUsageHint.DynamicDraw);


            if (ColorID == 0)
            {
                GL.GenBuffers(1, out ColorID);
                GL.BindBuffer(BufferTarget.ArrayBuffer, ColorID);
            }
            else
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, ColorID);

                GL.BufferData(BufferTarget.ArrayBuffer,
                    new IntPtr(Colors.Length * Vector4.SizeInBytes),
                    IntPtr.Zero, BufferUsageHint.DynamicDraw);
            }

            GL.BufferData<Vector4>(BufferTarget.ArrayBuffer,
                    new IntPtr(Colors.Length * Vector4.SizeInBytes),
                    Colors, BufferUsageHint.DynamicDraw);

Here’s the result:

As you can see from the above image the colours are correct (the clouds seem to have the correct alpha, which is the fourth element of the colour). I’ve had to set the Scale to 20.0 because otherwise you don’t see anything, which I believe means the Geometry shader thinks inScale is 0, even though it’s somewhere between 20 and 100 according to the c# debugger…

Thanks for any help, it’s greatly appreciated

Your code is very confusing.

First, you meticulously provide a layout(location) for every input and output… except for Position. Why? Is there something wrong with assigning it?

Second, you then meticulously assign an attribute index to inputs… to the geometry shader. The geometry shader doesn’t have attributes. So you’re not doing anything productive there. You cannot pass attributes directly to the GS; the GS gets its inputs from the vertex shader.

If you had linked your program together, you’d have gotten a linker error because of the third problem: inScale is never defined in the vertex shader. The VS never defines an output variable for location 1, so the GS gets undefined values in location 1. That’s how it works. There’s no magic passing of values from attributes directly to the GS. If the GS needs data, the VS must feed it data.

wow, that’s a massive eye-opener, here I was thinking the geometry shader came first. I didn’t assign ‘Position’ because it was the only one that consistently worked haha. Thanks I understand it a lot better now. I wonder why it didn’t error though :confused: maybe my drivers are a bit too friendly if you know what I mean.

P.S. I Love you <3 . You’re a life saver :slight_smile:
P.S.S I’m sorry about the confusing code

My original reply seems to have vanished. So now I’m posting in the non-quick-reply.

Anyway what I said before was: Thanks heaps, I didn’t realise the geometry shader was after the vertex shader. It’s now working great :smiley:

And sorry about the confusing code.

In that case, get over to the OpenGL Wiki, where you can see what the entire OpenGL pipeline looks like.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.