GL_QUADS and multiple texture coords

Discussion about everything. New games, 3d math, development tips...
Post Reply
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

GL_QUADS and multiple texture coords

Post by Spintz »

Is there any way with OpenGL to use multiple texture coords in a situation like this :

Code: Select all

glBegin(GL_QUADS);

glColor4ub( 255,255,255,255 );

glTexCoord2f( tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y );
glVertex2f( npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y );

glTexCoord2f( tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y );
glVertex2f( npos.LowerRightCorner.X, npos.UpperLeftCorner.Y );

glTexCoord2f( tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y );
glVertex2f( npos.LowerRightCorner.X, npos.LowerRightCorner.Y );

glTexCoord2f( tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y );
glVertex2f( npos.UpperLeftCorner.X, npos.LowerRightCorner.Y );

glEnd();
Or is there a way to tell texture stage 2 to use texture stage 1's texture coordinates, like in DirectX, you do

Code: Select all

pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
to tell texture stage 1 to use texture coordinates from texture stage 0.
Image
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

I had a quick look at irrlicht's implementation.
It uses the ARB multitexture extension which. and that has extensions for setting texture coords as well.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Yes, but Irrlicht only does it for vertex lists, not with individual calls to glVertex, etc.
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yep, glMultiTexCoord2f
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Awesome, thanks for help, that worked. What I needed it for was I just added a function to IrrSpintz to draw2DImage with using a separate texture for the alpha mask.

Here's function in OpenGL -

Code: Select all

//! Draws a texture, using another textures color
void COpenGLDriver::draw2DImageUsingAlphaTexture(video::ITexture* texture, video::ITexture* alphaTexture,
	const core::rect<s32>& destRect, const core::rect<s32>& sourceRect )
{
	if (!texture || !alphaTexture )
		return;

	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
	const core::dimension2d<s32>& ss = texture->getOriginalSize();
	float ssw=1.0f/ss.Width;
	float ssh=1.0f/ss.Height;

	core::rect<f32> tcoords;
	tcoords.UpperLeftCorner.X = (((f32)sourceRect.UpperLeftCorner.X)+0.5f) * ssw;
	tcoords.UpperLeftCorner.Y = (((f32)sourceRect.UpperLeftCorner.Y)+0.5f) * ssh;
	tcoords.LowerRightCorner.X = (((f32)sourceRect.UpperLeftCorner.X +0.5f + (f32)sourceRect.getWidth())) * ssw;
	tcoords.LowerRightCorner.Y = (((f32)sourceRect.UpperLeftCorner.Y +0.5f + (f32)sourceRect.getHeight())) * ssh;

	s32 xPlus = -(renderTargetSize.Width>>1);
	f32 xFact = 1.0f / (renderTargetSize.Width>>1);

	s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1);
	f32 yFact = 1.0f / (renderTargetSize.Height>>1);

	core::rect<float> npos;
	npos.UpperLeftCorner.X = (f32)(destRect.UpperLeftCorner.X+xPlus+0.5f) * xFact;
	npos.UpperLeftCorner.Y = (f32)(yPlus-destRect.UpperLeftCorner.Y+0.5f) * yFact;
	npos.LowerRightCorner.X = (f32)(destRect.LowerRightCorner.X+xPlus+0.5f) * xFact;
	npos.LowerRightCorner.Y = (f32)(yPlus-destRect.LowerRightCorner.Y+0.5f) * yFact;

	setTexture( 0, texture );
	setRenderStates2DMode( false, true, true );
	setTexture( 1, alphaTexture );

	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

	extGlActiveTextureARB( GL_TEXTURE1 );
	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE );
	glTexEnvf( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS );
	glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE );
	glEnableClientState( GL_TEXTURE_COORD_ARRAY );

	extGlActiveTextureARB( GL_TEXTURE0 );

	glBegin(GL_QUADS);

	pGlMultiTexCoord2f( GL_TEXTURE0, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y );
	pGlMultiTexCoord2f( GL_TEXTURE1, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y );
	glVertex2f( npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y );

	pGlMultiTexCoord2f( GL_TEXTURE0, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y );
	pGlMultiTexCoord2f( GL_TEXTURE1, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y );
	glVertex2f( npos.LowerRightCorner.X, npos.UpperLeftCorner.Y );

	pGlMultiTexCoord2f( GL_TEXTURE0, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
	pGlMultiTexCoord2f( GL_TEXTURE1, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y );
	glVertex2f( npos.LowerRightCorner.X, npos.LowerRightCorner.Y );

	pGlMultiTexCoord2f( GL_TEXTURE0, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y );
	pGlMultiTexCoord2f( GL_TEXTURE1, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y );
	glVertex2f( npos.UpperLeftCorner.X, npos.LowerRightCorner.Y );

	glEnd();

	// Reset Render States
	extGlActiveTextureARB( GL_TEXTURE1 );
	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
	glTexEnvf( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
	glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
	
	glDisable( GL_BLEND );
	glBlendFunc( GL_ONE, GL_ZERO );

	setTexture( 1, 0 );
}
And in DirectX9 -

Code: Select all

//! Draws a texture, using another textures color
void CD3D9Driver::draw2DImageUsingAlphaTexture(video::ITexture* texture, video::ITexture* alphaTexture,
	const core::rect<s32>& destRect, const core::rect<s32>& sourceRect )
{
	if( !texture || !alphaTexture )
		return;

	const core::dimension2d<s32>& ss = texture->getOriginalSize();
	f32 ssw=1.0f/ss.Width;
	f32 ssh=1.0f/ss.Height;

	core::rect<f32> tcoords;
	tcoords.UpperLeftCorner.X = (((f32)sourceRect.UpperLeftCorner.X)+0.5f) * ssw ;
	tcoords.UpperLeftCorner.Y = (((f32)sourceRect.UpperLeftCorner.Y)+0.5f) * ssh;
	tcoords.LowerRightCorner.X = (((f32)sourceRect.UpperLeftCorner.X +0.5f + (f32)sourceRect.getWidth())) * ssw;
	tcoords.LowerRightCorner.Y = (((f32)sourceRect.UpperLeftCorner.Y +0.5f + (f32)sourceRect.getHeight())) * ssh;

	core::dimension2d<s32> renderTargetSize = getCurrentRenderTargetSize();

	s32 xPlus = -(renderTargetSize.Width>>1);
	f32 xFact = 1.0f / (renderTargetSize.Width>>1);

	s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1);
	f32 yFact = 1.0f / (renderTargetSize.Height>>1);

	core::rect<f32> npos;
	npos.UpperLeftCorner.X = (f32)(destRect.UpperLeftCorner.X+xPlus+0.5f) * xFact;
	npos.UpperLeftCorner.Y = (f32)(yPlus-destRect.UpperLeftCorner.Y+0.5f) * yFact;
	npos.LowerRightCorner.X = (f32)(destRect.LowerRightCorner.X+xPlus+0.5f) * xFact;
	npos.LowerRightCorner.Y = (f32)(yPlus-destRect.LowerRightCorner.Y+0.5f) * yFact;

	setTexture( 0, texture );
	setTexture( 1, alphaTexture );

	setRenderStates2DMode( false, true, true );

	// Set alphaTexture as texture 1, get the alpha value, and then use that on texture 2
	// the actual texture, to draw with texture 1's alpha
	pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );

	pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

	S3DVertex vtx[4]; // clock wise
	vtx[0] = S3DVertex(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y , 0.0f, 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
	vtx[1] = S3DVertex(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y , 0.0f, 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
	vtx[2] = S3DVertex(npos.LowerRightCorner.X, npos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
	vtx[3] = S3DVertex(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, 0xFFFFFFFF, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);

	s16 indices[6] = {0,1,2,0,2,3};
	setVertexShader(EVT_STANDARD);
	pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], SizeOfS3DVertex);

	// Reset Changed RenderStates
	pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
	pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );

	pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
	pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
	pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR );
	setTexture( 1, 0 );
}
I needed this cause I was doing a render to texture, and then wanted to render that texture onto a circular HUD radar, and needed to use a texture to specify the alpha mask for the render texture into the HUD. Basically, it's like Texture Splatting in 2D. Here's screenshot of result -

Image

These are the beginnings of a HUD i started putting together today for a spaceship. The texture for radar on the bottom is generated by doing a renderToTexture and rendering certain texture for the planets, sun and your location and scaled to 2D space on the render target. That texture is then drawn, using this new function with a TGA texture specifying the transparency to use. Then another texture is drawn with draw2DImage to draw the rest of the HUD ( which needs a lot of work :) )

Oh, and I had to add a pointer and get the function using wglGetProcAddress for PFNGLMULTITEXCOORD2FPROC. Thanks again, was banging my head on that one for a couple hours.
Image
Post Reply