Render To Texture

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
71M
Posts: 122
Joined: Tue Jun 21, 2005 5:28 am
Location: London

Render To Texture

Post by 71M »

Could somebody please explain to me why the following code doesn't work?
I'm basically trying to get rendering to a texture working, but failing miserably!
The font renderer uses the current GU draw list to store polys in. Is that correct or is there another way to render 2D polygons into the render target?

Any help will be greatly received!

Cheers,
71M

Code: Select all

	static const u32		RENDER_TARGET_WIDTH( 256 );
	static const u32		RENDER_TARGET_HEIGHT( 128 );
	u8 *					p_back_buffer( ( u8 * )sceGuSwapBuffers() );		// Get the address of the back buffer
	u8 * const				p_render_target( ( u8 * )( 2 * 512 * 272 * 4 ) );	// Where we are to render to, 2 x frame buffers @ 32bbp
	u32						frame( 0 );

	while ( CInput::IsButtonDown( CInput::TRIANGLE ) == false )
	{
		CInput::Process();

		sceGuStart( GU_DIRECT, CGfx::GetDrawList() );

		// Setup render target viewport
		sceGuDrawBufferList( GU_PSM_8888, p_render_target, RENDER_TARGET_WIDTH );
		sceGuOffset( 2048 - ( RENDER_TARGET_WIDTH / 2 ), 2048 - ( RENDER_TARGET_HEIGHT / 2 ) );
		sceGuViewport( 2048, 2048, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT );

		if ( frame == 0 )	sceGuClearColor( 0xff800000 );
		else				sceGuClearColor( 0xff000080 );

		sceGuClear( GU_COLOR_BUFFER_BIT );

		CFont::GetDefaultFont()->Print( "COME ON!", V2( 0.f, 0.f ), 0xff00ff00 );	// Render some text


		// Restore normal viewport and draw buffer
		sceGuDrawBufferList( GU_PSM_8888, p_back_buffer, 512 );
		sceGuOffset( 2048 - ( CGfx::s_ScreenWidth / 2 ), 2048 - ( CGfx::s_ScreenHeight / 2 ) );
		sceGuViewport( 2048, 2048, CGfx::s_ScreenWidth, CGfx::s_ScreenHeight );

		sceGuClearColor( 0xff554433 );
		sceGuClear( GU_COLOR_BUFFER_BIT );

		//
		//	Draw the render target half size on the screen
		//
		vert_list[ 0 ].uv.x = 0.f;
		vert_list[ 0 ].uv.y = 0.f;
		vert_list[ 0 ].color = 0xffffffff;
		vert_list[ 0 ].pos.x = 0.f;
		vert_list[ 0 ].pos.y = 0.f;
		vert_list[ 0 ].pos.z = 0.f;

		vert_list[ 1 ].uv.x = RENDER_TARGET_WIDTH;
		vert_list[ 1 ].uv.y = 0.f;
		vert_list[ 1 ].color = 0xffffffff;
		vert_list[ 1 ].pos.x = 0.f + ( RENDER_TARGET_WIDTH / 2 );
		vert_list[ 1 ].pos.y = 0.f;
		vert_list[ 1 ].pos.z = 0.f;

		vert_list[ 2 ].uv.x = 0.f;
		vert_list[ 2 ].uv.y = RENDER_TARGET_HEIGHT;
		vert_list[ 2 ].color = 0xffffffff;
		vert_list[ 2 ].pos.x = 0.f;
		vert_list[ 2 ].pos.y = 0.f + ( RENDER_TARGET_HEIGHT / 2 );
		vert_list[ 2 ].pos.z = 0.f;

		vert_list[ 3 ].uv.x = RENDER_TARGET_WIDTH;
		vert_list[ 3 ].uv.y = RENDER_TARGET_HEIGHT;
		vert_list[ 3 ].color = 0xffffffff;
		vert_list[ 3 ].pos.x = 0.f + ( RENDER_TARGET_WIDTH / 2 );
		vert_list[ 3 ].pos.y = 0.f + ( RENDER_TARGET_HEIGHT / 2 );
		vert_list[ 3 ].pos.z = 0.f;

		const u8 * const	p_render_target_edram( ( u8 * )( ( u32 )( p_render_target ) + ( u32 )( sceGeEdramGetAddr() ) ) );

		sceGuEnable( GU_TEXTURE_2D );
		sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
		sceGuTexWrap( GU_CLAMP, GU_CLAMP );
		sceGuTexFilter( GU_LINEAR, GU_LINEAR );
		sceGuTexScale( 1.0f, 1.0f );
		sceGuTexOffset( 0.0f, 0.0f );
		sceGuTexMode( GU_PSM_8888, 0, 0, 0 );
		sceGuTexImage( 0, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT, RENDER_TARGET_WIDTH, p_render_target_edram );
		sceGuDrawArray( GU_TRIANGLE_STRIP, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 4, 0, vert_list );

		frame = ( frame ? 0 : 1 );

		sceGuFinish();
		sceGuSync( 0, 0 );

		sceDisplayWaitVblankStart();

		p_back_buffer = ( u8 * )sceGuSwapBuffers();
	}
71M
Posts: 122
Joined: Tue Jun 21, 2005 5:28 am
Location: London

Post by 71M »

Oh, by the way I don't have a Z buffer, hence only 2 frame buffers are currently reside in VRAM.

Code: Select all

u8 * const            p_render_target( ( u8 * )( 2 * 512 * 272 * 4 ) );   // Where we are to render to, 2 x frame buffers @ 32bbp
Paco
Posts: 54
Joined: Sun Oct 09, 2005 6:53 pm

Post by Paco »

71M wrote:Oh, by the way I don't have a Z buffer, hence only 2 frame buffers are currently reside in VRAM.
The Gu init will set a ZBuffer up for ya, so make sure you explicitly disable Z writes and Z compares. Check the source code code for sceGuDrawBuffer() if you want to see exactly what it does.
Paco
71M
Posts: 122
Joined: Tue Jun 21, 2005 5:28 am
Location: London

Post by 71M »

Hi Paco,
Yup, all z/depth tests are disabled after the call to sceGuDrawBuffer().
I tried rendering to the top of VRAM just to make sure, but still the same results.
71M
Posts: 122
Joined: Tue Jun 21, 2005 5:28 am
Location: London

Post by 71M »

Hmm, after further tests, it seems that the alpha component isn't being cleared correctly.
If I upload a texture with alpha set to 255 to the render target address it works fine.
Is there something else that I need to do to clear the alpha bits?
Does this sound correct in anyones experience?

Cheers,
71M
Paco
Posts: 54
Joined: Sun Oct 09, 2005 6:53 pm

Post by Paco »

71M wrote:Hmm, after further tests, it seems that the alpha component isn't being cleared correctly.
Ahh yes you can't use the texture alpha from a rendertarget unless you do some extra work. If I remember correctly, the alpha channel of a rendertarget contains the stencil buffer.
Paco
71M
Posts: 122
Joined: Tue Jun 21, 2005 5:28 am
Location: London

Post by 71M »

Excellent, thanks for that information. At least it's not me going mad :)
I have done some extra work, and everything seems to be working correctly now.
To see the render to target and the code that appears to be working for me, check out the next release of FileAssistant++ ;)

Cheers,
71M
Post Reply