Trying to display sprites

Hello,

I’m trying to display sprite for a particle application. I’m using shader but they don’t work.

This is the piece of code that I use in order to initiate the renderer :

if(LoadTGA(&treeTexture,p_variable->m_SPRITE )){
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_POINT_SPRITE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

	setVertexShader("../../../data/particule_shader.vert");
	setFragmentShader("../../../data/particule_shader.frag");
	setTransformUniform(p_variable->m_VERTEX_SIZE,"pointSize");
	setTransformUniform(m_windowSetup->m_width,"viewPortWidth");

	glActiveTexture(GL_TEXTURE0);
	glGenTextures(1, &treeTexture.texID);
	glBindTexture(GL_TEXTURE_2D, treeTexture.texID);				
	glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
}

here is my function which loads and launchs shaders :

void Renderer::setFragmentShader(char* frag) {
	char *fs = NULL;
	int success;

	f = glCreateShader(GL_FRAGMENT_SHADER);

	fs = textFileRead(frag);

	const char * ff = fs;

	glShaderSource(f, 1, &ff,NULL);

	free(fs);

	glCompileShader(f);

	glAttachShader(p,f);

	glLinkProgram(p);
	glUseProgram(p);

	glGetShaderiv(f, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		GLchar infoLog[GL_INFO_LOG_LENGTH];
		glGetShaderInfoLog(f, GL_INFO_LOG_LENGTH, NULL, infoLog);
		std::cout<<"Erreur dans la compilation du fragment shader `"&lt;&lt;frag&lt;&lt;"'"&lt;&lt;std::endl;
		fprintf(stderr, "Info log: %s
", infoLog);
	}else std::cout&lt;&lt;"Fragment shader `"<<frag<<"' OK!"<<std::endl;
}

Where f and p are GLuint, in the other hand setVertexShader use GLuint v and the same p

Here are my two shaders :

Vertex shader :

uniform float pointSize;
uniform float viewPortWidth;
void main()
{		
	vec4 camera_pos = gl_ModelViewMatrixInverse[3];
	float dist = distance(gl_Position.xyz, camera_pos.xyz);	
	gl_PointSize=pointSize*viewPortWidth/dist;
	gl_Position = ftransform();
	gl_FrontColor=gl_Color;
}

Fragment shader :

void main()
{
	gl_FragColor=gl_TexCoord[0];
}

My function which load thoses shaders alert me if there is an error during the compilation. Finally they compile fine at execution, the problem is that vertices dont change size when they are displayed (even if I put gl_PointSize=20.0 in the shader) and sprite texture is not displayed.

Ask me if you want other specific piece of code and thanks in advance for your help.

Try using glEnable(GL_PROGRAM_POINT_SIZE) rather than glEnable(GL_VERTEX_PROGRAM_POINT_SIZE).

I can’t because GL_PROGRAM_POINT_SIZE is undefined.

[HR][/HR]
Edit : tried with glEnable(34370) ( GL_PROGRAM_POINT_SIZE ( -- value ) - Factor Documentation ) without effect.

[HR][/HR]
Edit : I fixed gl_PointSize problem by not launching fragment shader so I assume problem came from gl_FragColor=gl_TexCoord[0];

I used this because of this pdf : https://graphics.stanford.edu/wikis/cs248-11-winter/CS_248%3A_Interactive_Computer_Graphics?action=AttachFile&do=get&target=OpenGLParticles.pdf @ slide 5.

But if I must not use this line, I don’t know how to display my particule.tga on each vertex of my particle system. Can you help me?

Your fragment shader is also incorrect, though I wasn’t going to address this until the sprite size was working correctly. On second thought, it might be the source of the problem. Try substituting the following:


uniform sampler2D spriteTexture;
void main()
{
    gl_FragColor = texture2D( spriteTexture, gl_PointCoord );
}

And initialize the spriteTexture uniform to zero (the unit you bound the texture to). You were previously assigning undefined texture coordinates to the output color. Sprites use a special variable, gl_PointCoord, which contains the texture coordinates for the generated quad ([0,1]). You also need to use a texture sampler to extract the color from the texture given a set of texture coordinates.

Thanks you.

I changed my shaders a couple of hours and I’m reassured that they fit with what you’r saying. I’m not going in the wrong way ^^

Now my init function looks like that :

if(LoadTGA(&treeTexture,p_variables->m_SPRITE )){
	glEnable(GL_POINT_SPRITE);
	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);

	glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
	glGenTextures(1, &treeTexture.texID);
	glBindTexture(GL_TEXTURE_2D, treeTexture.texID);
	/*glTexImage2D(GL_TEXTURE_2D, 
                               0,
                               treeTexture.type, 
                               treeTexture.width,
                               treeTexture.height,
                               0,
                               treeTexture.type,
                               GL_UNSIGNED_BYTE,
                               treeTexture.imageData
                              );*/

        gluBuild2DMipmaps(GL_TEXTURE_2D,
                              treeTexture.type==GL_RGB?3:4,
                              treeTexture.width,
                              treeTexture.height,
                              treeTexture.type,
                              GL_UNSIGNED_BYTE,
                              treeTexture.imageData
                             );

	p=glCreateProgram();
	setVertexShader("../../../data/particule_shader_sprite.vert");
	setFragmentShader("../../../data/particule_shader_sprite.frag");
	setTransformUniform(p_variables->m_VERTEX_SIZE,"pointSize",p_variables->m_FLOAT);
	setTransformUniform(m_windowSetup->m_width,"viewPortWidth",p_variables->m_FLOAT);
	setTransformUniform( 0,"texture",p_variables->m_INT);
}

The problem is that if I use glTexImage2D, my rendering is all black whereas if I use gluBuild2DMipmaps, I’ve got some white quads(according to gl_PointSize) without texture nor alpha transparency. I don’t really understand because it appears that gluBuild2DMipmaps is calling glTexImage2D for each mipmap level it creates…

You also need to use a texture sampler to extract the color from the texture given a set of texture coordinates.

I don’t get it, isn’t that what is doing glTexImage2D or gluBuild2DMipmaps?

When you’re using shaders, the fixed function pipeline no longer affects rendering in the same way (and in some cases, not at all). Textures that you bind to units are not automatically sampled - you need to do that yourself using a texture sampler uniform and a texture() call. This gives you the flexibility to sample the texture wherever and whenever you want, which you could not do in the fixed function pipeline. Your glTexEnv() calls are ignored; this is replaced by glEnable(GL_POINT_SPRITE), so you can safely remove that call from your program.

For your textures, set the GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_LINEAR, GL_LINEAR (for the glTexture2D() call), or
GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR (for gluBuild2DMipmaps) via glTexParameteri().

Also, I’m not sure about your blending mode – it looks like it’s set so that the sprite is emissive (adds to the background it renders over). Perhaps try glBlendFunc(GL_SRC_ALPHA, GL_DST_ONE_MINUS_SRC_ALPHA).

Finally, make sure you’re enabling GL_POINT_SPRITE and GL_PROGRAM_POINT_SIZE around the code where you render the sprites, not around the initialization code (where they have no effect).