Skip to main content
GameDev.net gamedev.net
🔒 Locked

Splatting

Started by robinei Nov 7, 2004 at 10:49 AM 14 replies 1.9k views
Original Post
robinei
robinei
Well, this is not strictly a question on splatting, but rather on how to blend a texture with an alpha map to get the smooth fadeout. The code below(some of it is taken from these forums) is an attempt to simply draw a single quad blended with an alpha map, but it doesn't work. It just draws the textured quad with altered but homogenous intensity. I'd really appreciate it of someone could point out what's wrong, or otherwise explain to me the correct way of doing it.

GLuint texture_id, alphamap_id;

GLubyte alphamap[] = {
	  0, 128,
	128, 255,
};

GLfloat vertex[] = {
	-1.0f, -1.0f, 1.0f,
	 1.0f, -1.0f, 1.0f,
	 1.0f,  1.0f, 1.0f,
	-1.0f,  1.0f, 1.0f,
};		 

GLfloat texcoord[] = {
	0.0f, 1.0f,
	1.0f, 1.0f,
	1.0f, 0.0f,
	0.0f, 0.0f,
};

GLubyte index[] = { 0, 1, 2, 3 };

void alphamap_create(GLuint *texture, GLubyte *data) {
	glGenTextures(1, texture);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glBindTexture(GL_TEXTURE_2D, *texture);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
}

void draw_scene() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -4.0f);
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	
	glVertexPointer(3, GL_FLOAT, 0, vertex);
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
	
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glBindTexture(GL_TEXTURE_2D, texture_id);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D, alphamap_id);
	
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, index);
	
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	
	SDL_GL_SwapBuffers();
}

glActiveTextureARB(GL_TEXTURE0_ARB);
texture_load(&texture_id, "GRASS_01.JPG");
glActiveTextureARB(GL_TEXTURE1_ARB);
alphamap_create(&alphamap_id, alphamap);

robinei
robinei
Ok I changed to this:

	glVertexPointer(3, GL_FLOAT, 0, vertex);	glClientActiveTexture(GL_TEXTURE0);	glActiveTextureARB(GL_TEXTURE0_ARB);	glTexCoordPointer(2, GL_FLOAT, 0, texcoord);	glClientActiveTexture(GL_TEXTURE1);	glActiveTextureARB(GL_TEXTURE1_ARB);	glTexCoordPointer(2, GL_FLOAT, 0, texcoord);


And it resulted in this.

(http://www.stud.ntnu.no/~robine/test.png)

It this what's to be expected? I thought it would be dark in the whole upper left corner and gradualy grow lighter.
robinei
robinei
Thank you. Both worked well, but i think changing the wrapping mode resulted in what was closest to my expectation.
robinei
robinei
If I expect to draw a lot of quads with simple texture coordinates like bellow, is there a way to do that without making a large texture coordinate array with a one to one correspondence with the vertex array? This seems very redundant.

texcoord_t texcoord[] = {	{ 0.0f, 1.0f },	{ 1.0f, 1.0f },	{ 0.0f, 0.0f },	{ 1.0f, 0.0f },};
OrangyTang
OrangyTang
Assuming this is for terrain texture splatting you could:

- Just share and reuse the same texture coord array for all your terrain patches.

- Generate linear texture coords via OpenGL texture coord generation.

- Generate texture coords in a vertex shader (dead easy if you've got suitable vertex shader support, and faster than the fixed function).
robinei
robinei
Ok I've gotten GLSL to work. What I want to know in the shader is the current index, so I can do mod 4 and know what texture coordinate to use. How do I do that?
OrangyTang
OrangyTang
You can't. As far as I know index information isn't avalible in the vertex shader (and rightly so, its not actually vertex data itself).

What I did was divide the vertices' x and y coords by a constant to generate the texture coords. You might need some extra uniform varaibles to store the chunk offset in as well.
robinei
robinei
Quote:
Original post by OrangyTang
You can't. As far as I know index information isn't avalible in the vertex shader (and rightly so, its not actually vertex data itself).

What I did was divide the vertices' x and y coords by a constant to generate the texture coords. You might need some extra uniform varaibles to store the chunk offset in as well.

Ok, that works fine for alpha map coordinates since it's not repeating.
But I can't think of a way to generate either 0.0 or 1.0 for the texture coordinate components. That depends on if the vertex is to the left or right/top or down of the current quad. How to figure that out, I don't know.
robinei
robinei
Oh so larger values will wrap?

Edit: Indeed. Thanks for your help.

[Edited by - robinei on November 8, 2004 5:46:23 PM]
robinei
robinei
Below is a picture of what I've got so far. It's a 2x2 grid of 2x2 chunks. The problem is along the edges between the chunks. When creating the alphamaps for each chunk, I sample from its neighbours too, so it is certainly due to the alphamaps being separate, causing the filtering not to smooth out the differences.

Now, Bloom mention it in his article: "I should note that the base texture and the alpha maps both have the "usual problem" with chunked textures, that is, there will be seams at the chunk boundaries due to bilinear filtering problems. This can be fixed the usual way, by duplicating the pixels along the boundary and making the uv's start half a pixel into the texture (instead of at 0,0)."

I tried to start one half pixel into the alpha map, but that didn't help, and I'm not sure I understand what he meant by duplicating the pixels.

Any take on this?



[Edited by - robinei on November 9, 2004 9:53:44 PM]
Digitalfragment
Digitalfragment
Duplcating the pixels means adding in a 'border' around the outside of the texture (eg, bringing a 512x512 texture to 514x514 (1 pixel along each side). The glTexImage calls have a border argument which you set to 1, and you also need to incorporate the new pixels aligned into the data argument correctly.

Hope this helps.
robinei
robinei
I haven't got time to try it now, but that sounds like it should solve the problem. Thanks.
robinei
robinei
When I use the border thing, my application becomes mighty unresponsive for some reason, and it doesn't look any better either. The texture apparently loads correctly from what I can judge, but it take 4 seconds before anything is visible on the screen, and likely just as long to redraw. If I remove the line in the shader which uses the bordered alphamap, it behaves normally again.

I do just as the API says. 2^n + 2 dimentions.

Edit: Ok apparently texture borders are unsupported on modern hardware.. Any other solution? I could do the border thing manually, but the I would have to double the texture dimentions to keep it power of 2, so it's not that tempting.

[Edited by - robinei on November 10, 2004 2:14:12 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.