Sign in to follow this  
v0dKA

How can I tell if I'm rendering outside the viewport?

Recommended Posts

In most cases, if I have a bug in my DirectX program, it involves something not being drawn. This is usually due to either 1) the object being drawn was set up correctly but is being drawn outside the view, or 2) the object was set up incorrectly, but if it was, it would have been inside the view. In order to facilitate debugging, I would like to be able to determine if the problem is due to case 1 (drawn outside the view). Is there a good procedure to determine if the object I'm drawing does not appear because it's outside of what my camera can see?

Share this post


Link to post
Share on other sites
Well if the object is outside ur frustum (camera) then it will get clipped and wont be rendered..

But ur best of creating ur own frustum looking class and then checking the AABB of the object against that.

At the end of the day OpenGL & DirectX purely help us with the Rendering, were still suppose to handle most other functions.

Share this post


Link to post
Share on other sites
I tend to debug by using D3DXVec3Project(). Picking a single vertex or (if available) information from the bounding box/sphere and feeding it in should give you some information. It's worth noting when using that function that it's not easy to interpret why it's going wrong, more a confirmation that it is going wrong [smile]

Another area to look into is that of planes - there are some interesting properties (iirc the inner product of a point and a plane) where you'd be able to tell if a given location is outside the frustum (and in which direction)...

hth
Jack

Share this post


Link to post
Share on other sites
Awesome, I'll have a look at that, but unfortunately, this doesn't apply to my current project (my vertices are transformed).

If I'm using transformed coordinates, do I have to set up a world, view, or projection matrix? Does lighting have to be enabled or disabled?

I can't understand why my application won't draw anything... I'm giving up for the night, but if anyone can pick it apart, I'd appreciate it. Part of the trouble is that I'm mixing tutorials that are written for 8.0 with those written for 9.0, and the end result is a faulty program. Or perhaps the problem isn't even directx related... I'm simply trying to display a color wheel (square) for now (will be expanded later), but nothing is drawn (the Clear() method is clearly called, but the color square itself is not drawn).


#include <windows.h>
#define D3D_DEBUG_INFO
#include <d3dx9.h>

// Enable debug mode in this project
#define DEBUG_MODE_ON
// Enable debug spew of each pixel in the colored pixel buffer
// (disabled -- too many pixels!)
//#define OUTPUT_PIXELS

// Windows prototypes
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
void RegisterWindowClass( HINSTANCE hInstance );
void CreateAppWindow( HINSTANCE hInstance );
WPARAM StartMessageLoop();

// Direct3D prototypes
bool InitDirect3D( );
void Render();
void CleanUp();
bool Setup();

// Globals
HWND g_hWnd;
IDirect3D9* g_pD3D = NULL;
IDirect3DDevice9* g_pDevice = NULL;
IDirect3DVertexBuffer9* g_pColoredPixelBuffer = NULL;

// Constants
const unsigned short MAX_HUE = 240;
const unsigned short MAX_SAT = 241;
const unsigned short MAX_LUM = 241;

// Vertex structures
struct TransformedColoredVertex
{
float x, y, z, rhw;
D3DCOLOR color;

TransformedColoredVertex()
{
rhw = 1.0;
}
TransformedColoredVertex( float _x, float _y, float _z, D3DCOLOR _color )
{
x = _y;
y = _y;
z = _y;
color = _color;
rhw = 1.0;
}
static const DWORD FVF;
};
const DWORD TransformedColoredVertex::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;

// Function prototypes
static double HueToRGB(const double m1, const double m2, double h );
D3DCOLOR HLStoRGB(const double H, const double L, const double S );


////////////////////////////////
// WinMain()
////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
RegisterWindowClass( hInstance );
CreateAppWindow( hInstance );
ShowWindow( g_hWnd, SW_SHOWDEFAULT );
UpdateWindow( g_hWnd );

bool success = ( InitDirect3D( ) && Setup() );
if( success )
WPARAM result = StartMessageLoop();
CleanUp();

return 0;
}

////////////////////////////////
// WndProc()
////////////////////////////////
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
ValidateRect( g_hWnd, NULL );
return 0;
case WM_KEYDOWN:
switch( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}

////////////////////////////////
// RegisterWindowClass()
////////////////////////////////
void RegisterWindowClass( HINSTANCE hInstance )
{
WNDCLASSEX wc;
wc.cbSize = sizeof( WNDCLASSEX );
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = (HCURSOR)LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = "Direct3DApp";
wc.hIconSm = NULL;

RegisterClassEx( &wc );
}

////////////////////////////////
// CreateAppWindow()
////////////////////////////////
void CreateAppWindow( HINSTANCE hInstance )
{
g_hWnd = CreateWindowEx(
NULL,
"Direct3DApp",
"Basic Direct3D Application",
WS_OVERLAPPEDWINDOW,
100,
100,
648,
514,
GetDesktopWindow(),
NULL,
hInstance,
NULL );
}

////////////////////////////////
// StartMessageLoop()
////////////////////////////////
WPARAM StartMessageLoop()
{
MSG msg;
while( 1 )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render();
}
}
return msg.wParam;
}

////////////////////////////////
// InitDirect3D()
////////////////////////////////
bool InitDirect3D()
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
if( !g_pD3D )
{
MessageBox( 0, "Direct3DCreate9() - FAILED", 0, MB_OK | MB_ICONERROR );
return false;
}

D3DCAPS9 caps;
g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps );

// Hardware vertex processing
int vp = 0;
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = 1280;
d3dpp.BackBufferHeight = 1024;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = g_hWnd;
d3dpp.Windowed = false;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

HRESULT hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
vp, &d3dpp, &g_pDevice );

if( FAILED( hr ) )
{
MessageBox( 0, "CreateDevice() - FAILED", 0, MB_OK | MB_ICONERROR );
return false;
}

return true;
}

////////////////////////////////
// Setup()
////////////////////////////////
bool Setup()
{
HRESULT hr = g_pDevice->CreateVertexBuffer(
MAX_HUE * MAX_SAT * sizeof( TransformedColoredVertex ),
D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY,
TransformedColoredVertex::FVF,
D3DPOOL_MANAGED,
&g_pColoredPixelBuffer, 0 );

if( FAILED( hr ) )
{
MessageBox( NULL, "Failed to create vertex buffer for g_pColoredVertexBuffer.", "Error", MB_OK | MB_ICONERROR );
return false;
}

TransformedColoredVertex* vertices;
g_pColoredPixelBuffer->Lock( 0, 0, (void**)&vertices, 0 );

for( unsigned short sat = 0; sat < MAX_SAT; ++sat )
{
for( unsigned short hue = 0; hue < MAX_HUE; ++hue )
{
D3DCOLOR rgb = HLStoRGB( (double)hue / (double)MAX_HUE, 0.5, (double)sat / (double)MAX_SAT );

#ifdef DEBUG_MODE_ON
#ifdef OUTPUT_PIXELS
char buffer[1024];
wsprintf( buffer, "Hue=%d, Sat=%d -- Red=%d, Green=%d, Blue=%d, RGB=0x%X\n",
hue, sat, (int)(BYTE)(rgb>>16), (int)(BYTE)(rgb>>8), (int)(BYTE)(rgb), (DWORD)rgb );
OutputDebugString( buffer );
#endif
#endif

vertices[ sat * MAX_HUE + hue ] = TransformedColoredVertex( (float)hue, (float)sat, 0.0, rgb );
}
}

g_pColoredPixelBuffer->Unlock();

g_pDevice->SetRenderState( D3DRS_LIGHTING, false );

g_pDevice->SetStreamSource( 0, g_pColoredPixelBuffer, 0, sizeof( TransformedColoredVertex ) );
//g_pDevice->SetVertexShader( NULL );
g_pDevice->SetFVF( TransformedColoredVertex::FVF );

return true;
}

////////////////////////////////
// Render()
////////////////////////////////
void Render()
{
g_pDevice->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 255, 255, 255 ), 0, 0 );

g_pDevice->BeginScene();
g_pDevice->DrawPrimitive( D3DPT_POINTLIST, 0, MAX_HUE*MAX_SAT );
g_pDevice->EndScene();

g_pDevice->Present( NULL, NULL, NULL, NULL );
}

////////////////////////////////
// CleanUp()
////////////////////////////////
void CleanUp()
{
if( g_pColoredPixelBuffer ) {
g_pColoredPixelBuffer->Release();
g_pColoredPixelBuffer = 0;
}
if( g_pDevice ) {
g_pDevice->Release();
g_pDevice = 0;
}
if( g_pD3D ) {
g_pD3D->Release();
g_pD3D = 0;
}
}

// COLOR TRANSFORMATION FUNCTIONS
// ------------------------------

static double HueToRGB(const double m1, const double m2, double h )
{
if (h<0) h+=1.0;
if (h>1) h-=1.0;
if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);
if (2.0*h < 1 ) return m2;
if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
return m1;
}

D3DCOLOR HLStoRGB(const double H, const double L, const double S )
{
double r,g,b;
double m1, m2;

if (S==0) r=g=b=L;
else {
if (L <=0.5) m2 = L*(1.0+S);
else m2 = L+S-L*S;
m1 = 2.0*L-m2;
r = HueToRGB(m1,m2,H+1.0/3.0);
g = HueToRGB(m1,m2,H);
b = HueToRGB(m1,m2,H-1.0/3.0);
}

D3DCOLOR ret_color;
ret_color = D3DCOLOR_XRGB( (int)(r*255.0), (int)(g*255.0), (int)(b*255.0) );
return ret_color;
}


Share this post


Link to post
Share on other sites
Quote:
Original post by v0dKA
Awesome, I'll have a look at that, but unfortunately, this doesn't apply to my current project (my vertices are transformed).

In that case, dumping out the coordinates to the debug window should suffice [smile]

Quote:
Original post by v0dKA
If I'm using transformed coordinates, do I have to set up a world, view, or projection matrix? Does lighting have to be enabled or disabled?

All of the matrix transforms as well as lighting are ignored - it doesn't really matter what you set them to...

Quote:
Original post by v0dKA
I can't understand why my application won't draw anything...

Try removing D3DUSAGE_POINTS from your CreateVertexBuffer() call. That is specifically for point-sprite rendering (similar, but not required for D3DPT_POINTLIST rendering). I've got a feeling that it's spotting that flag, and then later on you haven't enabled point sprite rendering (D3DRS_POINTSPRITEENABLE iirc) and it's consequently not doing what you're wanting it to [smile]

hth
Jack

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this