Multitexturing in GX for Wii?

Post Reply
User avatar
Izhido
Posts: 107
Joined: Fri Oct 19, 2007 10:57 pm
Location: Costa Rica
Contact:

Multitexturing in GX for Wii?

Post by Izhido » Thu Mar 15, 2012 5:29 am

(I probably shouldn't be doing this, but I'm that desperate for an answer. You'll understand when you see it.)

Once again, my google skills failed me.

Do you people have any examples of code that does multiple textures on a single polygon in GX hardware for Wii, that you're not using right now? :)

I'm having some issues with z-fighting on a project I'm working on, and I think that's because it is trying to blend 2 polygons with different textures, when the coordinates of such polygons can't really be guaranteed to be the same in code.

Besides, I really would like to learn how to do multitexturing.

Any help you can give me will be highly appreciated!

WinterMute
Site Admin
Posts: 1845
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Multitexturing in GX for Wii?

Post by WinterMute » Thu Mar 15, 2012 3:00 pm

Not sure what you googled for but a brief search turned this up for me.

http://www.chadheim.com/projects/projectfps/

If you feel like digging out the technical bits of that code and creating a multitexturing example it would be much appreciated.
Help keep devkitPro toolchains free, Donate today

Personal Blog

User avatar
Izhido
Posts: 107
Joined: Fri Oct 19, 2007 10:57 pm
Location: Costa Rica
Contact:

Re: Multitexturing in GX for Wii?

Post by Izhido » Thu Mar 15, 2012 9:22 pm

@WinterMute: As usual, right on target!

Incidentally, what were your search terms? I have this crazy theory that Google does different searches for different people in different countries; mine are almost always the wrong ones. :(

----------------------------------------------

As it turned out, it was extremely simple. You just need to:

1) Tell GX you will set 2 or more texcoords to generate ( GX_SetNumTexGens(2); GX_SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY); );
2) Tell GX you will use 2 or more TEV stages ( GX_SetNumTevStages(2); );
3) Tell GX how will pixels from previous stages will blend with the following ones ( GX_SetTevOp(GX_TEVSTAGE1, GX_BLEND); );
4) Specify which stages get which textures ( GX_LoadTexObj(&tex1, GX_TEXMAP0); GX_LoadTexObj(&tex2, GX_TEXMAP1); );
5) Alter your vertex descriptors appropiately ( GX_SetVtxDesc(GX_VA_TEX1, GX_DIRECT); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0); );
6) And, of course, call the appropiate texcoord specification functions twice or more, even if they use the same values ( GX_TexCoord2f32(0.0f,1.0f); GX_TexCoord2f32(0.0f,1.0f); ).

For posterity, I'll post the program that does all of these:

(The code came from this: NeHe lesson 6 modified for GX, THEN for multitexturing.

Code: Select all

/*---------------------------------------------------------------------------------

	multitexture

	modification to nehe lesson 6 port to GX, showing multiple textures per polygon
	original port:  shagkur
	modifications:  Izhido

---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <gccore.h>
#include <wiiuse/wpad.h>

// The two textures to use in this lesson
#include "crate_tpl.h"
#include "crate.h"
#include "NeHe_tpl.h"
#include "NeHe.h"

#define DEFAULT_FIFO_SIZE	(256*1024)

static GXRModeObj *rmode = NULL;
static void *frameBuffer[2] = { NULL, NULL};


int main(int argc,char **argv)
{
	f32 yscale;
	u32 xfbHeight;
	u32 fb = 0;
	f32 rquad = 0.0f;
	u32 first_frame = 1;
	GXTexObj textureNeHe;
	GXTexObj texturecrate;
	Mtx view; // view and perspective matrices
	Mtx model, modelview;
	Mtx44 perspective;
	void *gpfifo = NULL;
	GXColor background = {0, 0, 0, 0xff};
	guVector cam = {0.0F, 0.0F, 0.0F},
			up = {0.0F, 1.0F, 0.0F},
		  look = {0.0F, 0.0F, -1.0F};

	TPLFile neheTPL;
	TPLFile crateTPL;

	VIDEO_Init();
	WPAD_Init();

	rmode = VIDEO_GetPreferredMode(NULL);

	// allocate the fifo buffer
	gpfifo = memalign(32,DEFAULT_FIFO_SIZE);
	memset(gpfifo,0,DEFAULT_FIFO_SIZE);

	// allocate 2 framebuffers for double buffering
	frameBuffer[0] = SYS_AllocateFramebuffer(rmode);
	frameBuffer[1] = SYS_AllocateFramebuffer(rmode);

	// configure video
	VIDEO_Configure(rmode);
	VIDEO_SetNextFramebuffer(frameBuffer[fb]);
	VIDEO_Flush();
	VIDEO_WaitVSync();
	if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();

	fb ^= 1;

	// init the flipper
	GX_Init(gpfifo,DEFAULT_FIFO_SIZE);
 
	// clears the bg to color and clears the z buffer
	GX_SetCopyClear(background, 0x00ffffff);
 
	// other gx setup
	GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
	yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight);
	xfbHeight = GX_SetDispCopyYScale(yscale);
	GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
	GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
	GX_SetDispCopyDst(rmode->fbWidth,xfbHeight);
	GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
	GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
 
	if (rmode->aa)
        GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
    else
        GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);

	GX_SetCullMode(GX_CULL_NONE);
	GX_CopyDisp(frameBuffer[fb],GX_TRUE);
	GX_SetDispCopyGamma(GX_GM_1_0);

	// setup the vertex attribute table
	// describes the data
	// args: vat location 0-7, type of data, data format, size, scale
	// so for ex. in the first call we are sending position data with
	// 3 values X,Y,Z of size F32. scale sets the number of fractional
	// bits for non float data.
	// An additional descriptor is added for a second texture.
	GX_ClearVtxDesc();
	GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_TEX1, GX_DIRECT); // <-- Texcoords for the second TEV

	// Though not really relevant, the items here were rearranged 
	// so they match the previous lines
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGB8, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0);

	// set number of rasterized color channels
	GX_SetNumChans(1);

	//set number of texture coordinates to generate (two, for multitexture)
	GX_SetNumTexGens(2);

	// setup texture coordinate generation
	// args: texcoord slot 0-7, matrix type, source to generate texture coordinates from, matrix to use
	// The setup gets duplicated for both textures
	GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
	GX_SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);

    GX_InvVtxCache();
	GX_InvalidateTexAll();

	// Opening both textures from header files
	TPL_OpenTPLFromMemory(&crateTPL, (void *)crate_tpl,crate_tpl_size);
	TPL_GetTexture(&crateTPL,crate,&texturecrate);
	TPL_OpenTPLFromMemory(&neheTPL, (void *)NeHe_tpl,NeHe_tpl_size);
	TPL_GetTexture(&neheTPL,nehe,&textureNeHe);

	// setup our camera at the origin
	// looking down the -z axis with y up
	guLookAt(view, &cam, &up, &look);
 
	// setup our projection matrix
	// this creates a perspective matrix with a view angle of 90,
	// and aspect ratio based on the display resolution
    f32 w = rmode->viWidth;
    f32 h = rmode->viHeight;
	guPerspective(perspective, 45, (f32)w/h, 0.1F, 300.0F);
	GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE);

	guVector cubeAxis = {1,1,1};

	while(1) {

		WPAD_ScanPads();
		if ( WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0);

		// Sets the number of TEV stages, so as to indicate we're using 2 textures.
		// These lines do not really belong in here, since they can be called
		// outside this loop; this was made to be consistent with the original ported example:
		GX_SetNumTevStages(2);

		// The first texture is used as the base for the cube; that is,
		// the cube is intended to be a "crate":
		GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); // <-- Overwrite anything existing at that location
		GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);

		// The second texture is blended with the first, giving it the impression
		// of being a "sticker" plastered over the crate:
		GX_SetTevOp(GX_TEVSTAGE1, GX_BLEND); // <-- Blend with previous texture
		GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);

		guMtxIdentity(model);
		guMtxRotAxisDeg(model, &cubeAxis, rquad);
		guMtxTransApply(model, model, 1.5f,0.0f,-7.0f);
		guMtxConcat(view,model,modelview);
		// load the modelview matrix into matrix memory
		GX_LoadPosMtxImm(modelview, GX_PNMTX0);
		
		GX_LoadTexObj(&texturecrate, GX_TEXMAP0);
		GX_LoadTexObj(&textureNeHe, GX_TEXMAP1);

		GX_Begin(GX_QUADS, GX_VTXFMT0, 24);			// Draw a Cube

			GX_Position3f32(-1.0f, 1.0f, -1.0f);    // Top Left of the quad (top)
			GX_Color3f32(0.0f,1.0f,0.0f);                   // Set The Color To Green
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32(-1.0f, 1.0f, 1.0f);     // Top Right of the quad (top)
			GX_Color3f32(0.0f,1.0f,0.0f);                   // Set The Color To Green
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32(-1.0f, -1.0f, 1.0f);    // Bottom Right of the quad (top)
			GX_Color3f32(0.0f,1.0f,0.0f);                   // Set The Color To Green
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32(- 1.0f, -1.0f, -1.0f);          // Bottom Left of the quad (top)
			GX_Color3f32(0.0f,1.0f,0.0f);                   // Set The Color To Green
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);

			GX_Position3f32( 1.0f,1.0f, -1.0f);     // Top Left of the quad (bottom)
			GX_Color3f32(1.0f,0.5f,0.0f);                   // Set The Color To Orange
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32(1.0f,-1.0f, -1.0f);     // Top Right of the quad (bottom)
			GX_Color3f32(1.0f,0.5f,0.0f);                   // Set The Color To Orange
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32(1.0f,-1.0f,1.0f);       // Bottom Right of the quad (bottom)
			GX_Color3f32(1.0f,0.5f,0.0f);                   // Set The Color To Orange
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32( 1.0f,1.0f,1.0f);       // Bottom Left of the quad (bottom)
			GX_Color3f32(1.0f,0.5f,0.0f);                   // Set The Color To Orange
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);

			GX_Position3f32( -1.0f, -1.0f, 1.0f);           // Top Right Of The Quad (Front)
			GX_Color3f32(1.0f,0.0f,0.0f);                   // Set The Color To Red
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32(1.0f, -1.0f, 1.0f);     // Top Left Of The Quad (Front)
			GX_Color3f32(1.0f,0.0f,0.0f);                   // Set The Color To Red
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32(1.0f,-1.0f, -1.0f);     // Bottom Left Of The Quad (Front)
			GX_Color3f32(1.0f,0.0f,0.0f);                   // Set The Color To Red
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32( -1.0f,-1.0f, -1.0f);   // Bottom Right Of The Quad (Front)
			GX_Color3f32(1.0f,0.0f,0.0f);                   // Set The Color To Red
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);
	
			GX_Position3f32( -1.0f,1.0f,1.0f);      // Bottom Left Of The Quad (Back)
			GX_Color3f32(1.0f,1.0f,0.0f);                   // Set The Color To Yellow
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32(-1.0f,1.0f,-1.0f);      // Bottom Right Of The Quad (Back)
			GX_Color3f32(1.0f,1.0f,0.0f);                   // Set The Color To Yellow
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32(1.0f, 1.0f,-1.0f);      // Top Right Of The Quad (Back)
			GX_Color3f32(1.0f,1.0f,0.0f);                   // Set The Color To Yellow
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32( 1.0f, 1.0f,1.0f);      // Top Left Of The Quad (Back)
			GX_Color3f32(1.0f,1.0f,0.0f);                   // Set The Color To Yellow
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);

			GX_Position3f32(1.0f, -1.0f, -1.0f);    // Top Right Of The Quad (Left)
			GX_Color3f32(0.0f,0.0f,1.0f);                   // Set The Color To Blue
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32(1.0f, 1.0f,-1.0f);      // Top Left Of The Quad (Left)
			GX_Color3f32(0.0f,0.0f,1.0f);                   // Set The Color To Blue
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32(-1.0f,1.0f,-1.0f);      // Bottom Left Of The Quad (Left)
			GX_Color3f32(0.0f,0.0f,1.0f);                   // Set The Color To Blue
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32(-1.0f,-1.0f, -1.0f);    // Bottom Right Of The Quad (Left)
			GX_Color3f32(0.0f,0.0f,1.0f);                   // Set The Color To Blue
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);

			GX_Position3f32( 1.0f, -1.0f,1.0f);     // Top Right Of The Quad (Right)
			GX_Color3f32(1.0f,0.0f,1.0f);                   // Set The Color To Violet
			GX_TexCoord2f32(0.0f,0.0f);
			GX_TexCoord2f32(0.0f,0.0f);
			GX_Position3f32( -1.0f, -1.0f, 1.0f);           // Top Left Of The Quad (Right)
			GX_Color3f32(1.0f,0.0f,1.0f);                   // Set The Color To Violet
			GX_TexCoord2f32(1.0f,0.0f);
			GX_TexCoord2f32(1.0f,0.0f);
			GX_Position3f32( -1.0f,1.0f, 1.0f);     // Bottom Left Of The Quad (Right)
			GX_Color3f32(1.0f,0.0f,1.0f);                   // Set The Color To Violet
			GX_TexCoord2f32(1.0f,1.0f);
			GX_TexCoord2f32(1.0f,1.0f);
			GX_Position3f32( 1.0f,1.0f,1.0f);       // Bottom Right Of The Quad (Right)             
			GX_Color3f32(1.0f,0.0f,1.0f);                   // Set The Color To Violet
			GX_TexCoord2f32(0.0f,1.0f);
			GX_TexCoord2f32(0.0f,1.0f);

		GX_End();                                   // Done Drawing The Quad 

		GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
		GX_SetColorUpdate(GX_TRUE);
		GX_CopyDisp(frameBuffer[fb],GX_TRUE);

		GX_DrawDone();

		VIDEO_SetNextFramebuffer(frameBuffer[fb]);
		if(first_frame) {
			first_frame = 0;
			VIDEO_SetBlack(FALSE);
		}
		VIDEO_Flush();
 		VIDEO_WaitVSync();
		fb ^= 1;

		rquad -= 0.15f;				// Decrease The Rotation Variable For The Quad     ( NEW )
	}
}

Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests