Using mipmaps with RT's in DirectX9

Started by
13 comments, last by そら 11 years, 11 months ago
Please conside using IE, i would help.
Advertisement
looks like right now the only option is to get some confirmation by someone at Microsoft that this is really not possible
It is possible, I've done it before...
There's really only 4 places something can go wrong, so there's probably a small bug in your code in one of them:
* Create the resource.
* Bind the resource for writing.
* Bind the resource for sampling.
* Sample the resource.

I can't personally offer any more help/advice unless you post your code up, other then reiterating that PIX might be useful, and that you should enable the debug runtimes in the DirectX control panel to check for obvious errors.
Thanks Hodgman

I have taken the SDK's Vertex tutorial sample, and managed to reduce it to the following code to handle the most basic form of a mipmapped render target:


//-----------------------------------------------------------------------------
// File: Vertices.cpp
//
// Desc: In this tutorial, we are rendering some Vertices. This introduces the
// concept of the vertex buffer, a Direct3D object used to store
// Vertices. Vertices can be defined any way we want by defining a
// custom structure and a custom FVF (flexible vertex format). In this
// tutorial, we are using Vertices that are transformed (meaning they
// are already in 2D window coordinates) and lit (meaning we are not
// using Direct3D lighting, but are supplying our own colors).
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <d3d9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe.h>
#pragma warning( default : 4996 )
#include <d3dx9effect.h>

#define WWIDTH 640.0f
#define WHEIGHT 480.0f

#define DoSafeRelease( COM ) if( COM ){ COM->Release(); COM = NULL; }

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold Vertices
LPDIRECT3DVERTEXBUFFER9 g_pVB2 = NULL; // Buffer to hold Vertices
LPDIRECT3DTEXTURE9 g_pRTTexture = NULL;
LPDIRECT3DSURFACE9 g_pFrontBuffer = NULL;
ID3DXEffect* g_pEffect = NULL;
// A structure for our custom vertex type
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // The transformed position for the vertex
DWORD color; // The vertex color
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

struct CUSTOMTEXVERTEX
{
FLOAT x, y, z, rhw;
DWORD color;
FLOAT u, v;
};
#define D3DFVF_CUSTOMTEXVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
HRESULT R;
// Create the D3D object.
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &amp;d3dpp, sizeof( d3dpp ) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// Create the D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&amp;d3dpp, &amp;g_pd3dDevice ) ) )
{
return E_FAIL;
}
R = g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&amp;g_pFrontBuffer);
if( FAILED(R) ) return R;
// Device state would normally be set here
R = g_pd3dDevice->CreateTexture(640,480,0,(D3DUSAGE_RENDERTARGET|D3DUSAGE_AUTOGENMIPMAP), D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,&amp;g_pRTTexture, NULL);
if( FAILED(R) ) return R;

LPD3DXBUFFER ErrBuffer;
D3DXCreateEffectFromFile( g_pd3dDevice, L".\\ReadLOD.fx", NULL, NULL, 0, NULL, &amp;g_pEffect, &amp;ErrBuffer );
if( !g_pEffect ) return E_FAIL;
return S_OK;
}

//-----------------------------------------------------------------------------
// Name: InitVB()
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
// Initialize three Vertices for rendering a triangle
CUSTOMVERTEX Vertices[] =
{ // 640x480
{ (WWIDTH*0.5f ), (WHEIGHT*0.05f), 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ (WWIDTH*0.95f), (WHEIGHT*0.95f), 0.5f, 1.0f, 0xff00ff00, },
{ (WWIDTH*0.05f), (WHEIGHT*0.95f), 0.5f, 1.0f, 0xff00ffff, },
};
// Create the vertex buffer. Here we are allocating enough memory
// (from the default pool) to hold all our 3 custom Vertices. We also
// specify the FVF, so the vertex buffer knows what data it contains.
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &amp;g_pVB, NULL ) ) )
{
return E_FAIL;
}
// Now we fill the vertex buffer. To do this, we need to Lock() the VB to
// gain access to the Vertices. This mechanism is required becuase vertex
// buffers may be in device memory.
VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof( Vertices ), ( void** )&amp;pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, Vertices, sizeof( Vertices ) );
g_pVB->Unlock();

CUSTOMTEXVERTEX Grid[] =
{
{0.0f, 0.0f, 0.5f, 1.0f, 0xFFffFFff, 0.0f, 0.0f },
{640.0f, 0.0f, 0.5f, 1.0f, 0xFFffFFff, 1.0f, 0.0f },
{640.0f, 480.0f, 0.5f, 1.0f, 0xFFffFFff, 1.0f, 1.0f },
{0.0f, 0.0f, 0.5f, 1.0f, 0xFFffFFff, 0.0f, 0.0f },
{640.0f, 480.0f, 0.5f, 1.0f, 0xFFffFFff, 1.0f, 1.0f },
{0.0f, 480.0f, 0.5f, 1.0f, 0xFFffFFff, 0.0f, 1.0f }
};
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 6 * sizeof( CUSTOMTEXVERTEX ),
0, D3DFVF_CUSTOMTEXVERTEX,
D3DPOOL_DEFAULT, &amp;g_pVB2, NULL ) ) )
{
return E_FAIL;
}
VOID* pGrid;
if( FAILED( g_pVB2->Lock( 0, sizeof( Grid ), ( void** )&amp;pGrid, 0 ) ) )
return E_FAIL;
memcpy( pGrid, Grid, sizeof( Grid ) );
g_pVB2->Unlock();
return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pVB != NULL )
g_pVB->Release();
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
if( g_pRTTexture != NULL )
g_pRTTexture->Release();
if( g_pEffect != NULL )
g_pEffect->Release();
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
IDirect3DSurface9 *pRT = NULL;

/***************** Render into the g_RTTexture surface *****************/
g_pd3dDevice->SetTexture( 0, NULL );
g_pRTTexture->GetSurfaceLevel( 0, &amp;pRT);
g_pd3dDevice->SetRenderTarget( 0, pRT );
DoSafeRelease( pRT )
// Clear the backbuffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 128, 128, 128 ), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

/***************** Render into the Frame Buffer *****************/
g_pd3dDevice->SetRenderTarget(0,g_pFrontBuffer);
g_pRTTexture->GenerateMipSubLevels();
g_pd3dDevice->SetTexture( 0, g_pRTTexture );

g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 225, 0, 225 ), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
UINT passes;
g_pEffect->SetTechnique( "Render_LOD" );
g_pEffect->Begin(&amp;passes,0);
for( UINT i=0; i < passes; i++ )
{
g_pEffect->BeginPass( i );
g_pd3dDevice->SetStreamSource( 0, g_pVB2, 0, sizeof( CUSTOMTEXVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMTEXVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
g_pEffect->EndPass();
}
g_pEffect->End();
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}

//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
UNREFERENCED_PARAMETER( hInst );
// Register the window class
WNDCLASSEX wc =
{
sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
L"D3DLODRenderTarget", NULL
};
RegisterClassEx( &amp;wc );
// Create the application's window
HWND hWnd = CreateWindow( L"D3DLODRenderTarget", L"Test LOD on Render Target",
WS_OVERLAPPEDWINDOW, 100, 100, 658, 524,
NULL, NULL, wc.hInstance, NULL );
// Initialize Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Create the vertex buffer
if( SUCCEEDED( InitVB() ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
// Enter the message loop
MSG msg;
ZeroMemory( &amp;msg, sizeof( msg ) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &amp;msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &amp;msg );
DispatchMessage( &amp;msg );
}
else
Render();
}
}
}
UnregisterClass( L"D3DLODRenderTarget", wc.hInstance );
return 0;
}


and for the PixelShader, this is the code:


sampler s;

float4 PS( float4 tex : TEXCOORD0 ) : COLOR
{
return tex2Dlod( s, float4( tex.xyz, 3 ) );
}
technique Render_LOD
{
pass P0
{
PixelShader = compile ps_3_0 PS();
}
}


PIX doesn't really give me any useful information (except the fact that when creating the RT texture it doesn't take the D3DUSAGE_AUTOGENMIPMAP part, although it is explicitly created with it in the code).

Or am I missing something?

Thanks!
"lots of shoulddas, coulddas, woulddas in the air, thinking about things they shouldda couldda wouldda donne, however all those shoulddas coulddas woulddas ran away when they saw the little did to come"
Yes, so did I until now. You don't explicitly set the mip filter of your sampler, so the default of D3DTEXF_NONE will be your culprit. Set it to linear or point.
Really really thank you unbird!..

you are totalli right, I was almost convinced it was not possible, but now, after explictly setting the mip filter to point/linear it's doing it correctly.

thanks the three of you for your help!
"lots of shoulddas, coulddas, woulddas in the air, thinking about things they shouldda couldda wouldda donne, however all those shoulddas coulddas woulddas ran away when they saw the little did to come"

This topic is closed to new replies.

Advertisement