Sign in to follow this  
calidev234

Rendering Question.

Recommended Posts

I have an .x file that I made and when I look at it in the MeshViewer (that comes in the utility folder of the DirectX SDK) the rendering looks great: But when I use my render code it looks like shit:

Share this post


Link to post
Share on other sites
Hell, I meant to hit 'show preview' and hit submit....

Anyway, I'm using this to render the mesh:


//draw each mesh subset
for( DWORD i=0; i<model->material_count; i++ )
{
d3ddev->SetMaterial( &model->materials[i] ); // Set the material and texture for this subset
d3ddev->SetTexture( 0, model->textures[i] );
model->mesh->DrawSubset( i ); // Draw the mesh subset
}



And I'm setting up my render state like this:


//use ambient lighting and z-buffering
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE); //remember to fix this in ch11
d3ddev->SetRenderState(D3DRS_AMBIENT, WHITE); //should be ambient option instead
d3ddev->SetRenderState(D3DRS_VERTEXBLEND, 0);
d3ddev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
d3ddev->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
d3ddev->SetNPatchMode( 0 );

//ADDED
d3ddev->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
d3ddev->SetRenderState( D3DRS_DITHERENABLE, TRUE );
d3ddev->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
d3ddev->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
d3ddev->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
d3ddev->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); //D3DFILL_WIREFRAME : D3DFILL_SOLID



And I'm setting up my lighting like this (in the Main Loop):


//Setup the Light
D3DLIGHT9 light;
D3DXVECTOR3 vecLightDirUnnormalized(1.0f, -1.0f, 1.0f);
ZeroMemory( &light, sizeof(D3DLIGHT9) );
light.Type = D3DLIGHT_SPOT; //D3DLIGHT_SPOT, D3DLIGHT_POINT, D3DLIGHT_FORCE_DWORD, D3DLIGHT_DIRECTIONAL
light.Diffuse.r = 0.5;
light.Diffuse.g = 0.5;
light.Diffuse.b = 0.5;
light.Specular.r = 0;
light.Specular.g = 0;
light.Specular.b = 0;

light.Ambient.r = 1;
light.Ambient.g = 1;
light.Ambient.b = 1;

D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized );

light.Position = D3DXVECTOR3(CAMERA_X, CAMERA_Y, CAMERA_Z);
light.Direction = D3DXVECTOR3( 0.0f, 0.0f, 1.0f);

light.Attenuation0 = 0.0f;
light.Attenuation1 = 0.0f;
light.Attenuation2 = 0.0f;

light.Range = ((float)sqrt(FLT_MAX));

switch( light.Type )
{
case D3DLIGHT_POINT:
light.Attenuation0 = 1.0f;
break;
case D3DLIGHT_DIRECTIONAL:
light.Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
break;
case D3DLIGHT_SPOT:
light.Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
light.Range = 1.0f;
light.Falloff = 100.0f;
light.Theta = 0.3f;
light.Phi = 0.40f;
light.Attenuation2 = 1.0f;
}

// Set Light for vertex shader
D3DXVECTOR4 vLightDir( 0.0f, 1.0f, -1.0f, 0.0f );
D3DXVec4Normalize( &vLightDir, &vLightDir );
d3ddev->SetVertexShaderConstantF(1, (float*)&vLightDir, 1);

d3ddev->SetLight(0, &light ) ;
d3ddev->LightEnable(1, TRUE );




So I'm not sure. Does anybody have any ideas.

Thank you,

Joshua

Share this post


Link to post
Share on other sites
From the looks of it, the only thing thats different is the lighting (consequently the shading).

I spotted this line:
d3ddev->SetRenderState(D3DRS_AMBIENT, WHITE);

Presuming that WHITE is actually the colour white - RGB(255,255,255) (or 1.0,1.0,1.0 [smile]) then it'll effectively "override" all of the lighting properties you've set.

D3DRS_AMBIENT is added to the final colour of all vertices, and WHITE being the maximum means that no matter what you do (short of adding a "dark light") it'll always stay at the maximum.

Change it to something more grey/black and you might get better results.

hth
Jack

Share this post


Link to post
Share on other sites
Hello Jack, thank you for your response. I changed what you suggested and the colors look fine now, however I'm still running into the rendering issue.

As can be seen by looking at the second image the wall closest to the camera view it should be a solid looing wall with three windows in it (refer to the first image for how it should look). However where the windows are rendered and certain pieces of the wall are not being rendered entirely. And if I rotate it will change. I'm certain the mesh file is made correctly; because I have culling turned on and it's fine; so I'm not really sure.

So I'm not certain.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
jollyjeffers hit the target. Play with the ambient and diffuse parameters and adjust the result as you would like.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by calidev234
Hello Jack, thank you for your response. I changed what you suggested and the colors look fine now, however I'm still running into the rendering issue.

As can be seen by looking at the second image the wall closest to the camera view it should be a solid looing wall with three windows in it (refer to the first image for how it should look). However where the windows are rendered and certain pieces of the wall are not being rendered entirely. And if I rotate it will change. I'm certain the mesh file is made correctly; because I have culling turned on and it's fine; so I'm not really sure.

So I'm not certain.


Oh.. sorry, I didn't pay attention. It seems a depth-buffer problem. Increase the z value of the near view-plane in D3DXMatrixPerspectiveLH/RH function.

Share this post


Link to post
Share on other sites
Ok, so I've been playing around with D3DXMatrixPerspectiveFovLH, as well as the Direct3D presentation parameters and I'm still not getting very good rendering.

The code is set up as follows:

1. Direct3D Presentation Parameters


D3DDISPLAYMODE dm;
d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.BackBufferCount = 2;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = true;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
d3dpp.FullScreen_RefreshRateInHz = 0;

//create Direct3D device
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);



2. The Perspective

RECT r;
GetClientRect( hwnd, &r );
r.top += 28;
r.bottom -= 20;
float fAspect = (float)(r.right - r.left) / (float)(r.bottom - r.top);
D3DXMATRIX mat;
D3DXMatrixPerspectiveFovLH(&mat, 0.25f*3.141592654f, fAspect, 1.0f, 10000.0f);
d3ddev->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );





3. 3D Device setup


d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE);
d3ddev->SetRenderState(D3DRS_AMBIENT, GREY);
d3ddev->SetRenderState(D3DRS_VERTEXBLEND, 0);
d3ddev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
d3ddev->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
d3ddev->SetNPatchMode( 0 );

d3ddev->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
d3ddev->SetRenderState( D3DRS_DITHERENABLE, TRUE );
d3ddev->SetRenderState( D3DRS_NORMALIZENORMALS, FALSE );
d3ddev->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
d3ddev->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
d3ddev->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME);



4. The Light setup in the MainLoop


D3DLIGHT9 light;
D3DXVECTOR3 vecLightDirUnnormalized(1.0f, -1.0f, 1.0f);
ZeroMemory( &light, sizeof(D3DLIGHT9) );
light.Type = D3DLIGHT_POINT;
light.Diffuse.r = 1.0;
light.Diffuse.g = 1.0;
light.Diffuse.b = 1.0;
light.Ambient.r = 0.1f;
light.Ambient.g = 0.1f;
light.Ambient.b = 0.1f;

D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized );

light.Position = D3DXVECTOR3(PosX, PosY, PosZ);
light.Direction = D3DXVECTOR3( LookX, LookY, LookZ);

light.Range = ((float)sqrt(FLT_MAX));

switch( light.Type )
{
case D3DLIGHT_POINT:
light.Attenuation0 = 1.0f;
light.Range = 600.0f;
light.Falloff = .10f;
light.Theta = .1f;
light.Phi = .6f;
break;
case D3DLIGHT_DIRECTIONAL:
light.Position = D3DXVECTOR3(PosX, PosY, PosZ);
break;
case D3DLIGHT_SPOT:
light.Position = D3DXVECTOR3(PosX, PosY, PosZ);
light.Range = 1.0f;
light.Falloff = 1000.0f;
light.Theta = 0.3f;
light.Phi = 0.40f;
light.Attenuation2 = 1.0f;
}

// Set Light for vertex shader
D3DXVECTOR4 vLightDir( 0.0f, 1.0f, -1.0f, 0.0f );
D3DXVec4Normalize( &vLightDir, &vLightDir );
d3ddev->SetVertexShaderConstantF(1, (float*)&vLightDir, 1);

d3ddev->SetLight(0, &light ) ;
d3ddev->LightEnable(0, TRUE );



And all of this has this affect on the rendering:



As can be seen by the areas circled in red the rendering is not great. If I get really close to the walls then they look ok; but so far the rendering is not usable.

I'm a little lost. Does anybody have any ideas?

Thank you,

Joshua

Share this post


Link to post
Share on other sites
D3DXMATRIX mat;
D3DXMatrixPerspectiveFovLH(&mat, 0.25f*3.141592654f, fAspect, 1.0f, 10000.0f);
d3ddev->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );


10,000.0f still seems a little high to me. Which leads onto the next big question:

How big is that model we're looking at? Both as a raw model (the geometry you're loading from disk) and the rendered size (factoring in any scaling in the world matrix).

In knowing how big it is, you can do two things:

1. Maximize your depth value usage by, ideally, configuring zNear and zFar to exactly enclose the space that the model occupies. In reality this can be a bit of a bugger when the camera moves and the mesh rotates, but you can probably gain a lot by reducing the current zNear value.

2. As you observed, the D3D Mesh Viewer tool doesn't corrupt, so the actual raw data is probably fine (it's not stored in a form that IEEE754 issues will become a factor). However, if you're reducing the size of your mesh substantially you might well be finding that the rendered geometry is mapping to the same Z values.

hth
Jack

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Just complementing jollyjeffers's comments:

Z-buffer is a non-linear method. It gives you a lot of precision close to the camera's eye and little precision off in the distance. So, put the near frustum plane as far from the camera's eye as you can tolerate.

Two solutions:

1) Use w-buffer method instead of z-buffer (some cards don't support it):

pDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_USEW);


2) Increase the z-position of the near frustum plane. For example:

D3DXMatrixPerspectiveFovLH(&mat, 0.25f*3.141592654f, fAspect, 5.0f, 10000.0f);

Share this post


Link to post
Share on other sites
I´m not the Z-Buffer expert, pretty sure about that, though:
Recently read an article linked here in some thread somewhere, and if I understood it correctly, it would double the accuracy 'range' (range with some specific acceptable error) of your depth buffer if you doubled the value for the near plane. So instead of 1.0f use 2.0f for doubled range, using 4.0f might probably not hurt, either.... just put the near plane as far away as you can bear. And perhaps decrease the far plane distance, if needed. I am currently using 5.0f for near and 8000.0f for far plane and got no visual glitches... but that obviously depends on the scene you´re rendering....

Share this post


Link to post
Share on other sites
Calidev, the visual artifacts you pointed out in that screenshots are called "z-fighting". Google is your friend here, but like suggested above: adjusting near and far clipping planes (to increase z-buffer resolution at viewing distance) usually does the trick. Pay special attention to the near plane.

Also, from the screenshot it seems the geometry is faulty: t-junctions (an other good thing to google on!) cause seams in between adjacent polygons, allowing the geometry behind it to shine through.

Share this post


Link to post
Share on other sites
Thank you; I was playing with the near plane (setting it to 5.0) and it helped out a great deal. It looks a lot better now; but I'm still not getting the lighting like it is in the MeshViewer(of the DirectX SDK); I guess I need to play around with that. But it looks really great in the MeshViewer (so crisp and clean).

Thank you,

Joshua

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by calidev234
Thank you; I was playing with the near plane (setting it to 5.0) and it helped out a great deal. It looks a lot better now; but I'm still not getting the lighting like it is in the MeshViewer(of the DirectX SDK); I guess I need to play around with that. But it looks really great in the MeshViewer (so crisp and clean).

Thank you,

Joshua

See the light settings in "mview.cpp" from Mesh Viewer code. This file is in the ..\DXSDK\Extras\MView path.

Share this post


Link to post
Share on other sites
umm of course you aren't going to get the same coloring with the lighting.. you are using 16-bit colors when you initialize whereas the mesh viewer defaults to 32-bit :) Other than that the mesh viewer is probably lighting slightly different.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Based on your last screenshot, it seems you are using a point or spot light, and the range of the light seems small to iluminate the whole model.
Try to increase it. For example:

light.Range = 10000.0f;

Also, try to use a directional light instead of a point light.

Note:
Remember that to get exactly the rendering shown by Mesh Viewer, you need to use the same lighting properties (including the position or direction of the light) and the same camera settings.

Share this post


Link to post
Share on other sites
Saruman, I understand the 16 vs. 32 bit argument and I tried to default my viewer to 32 but it WOULD NOT create the 3d Device; only the 16 worked. But the MeshViewer worked fine (on the same computer).

As for the other lighting issues, yes I agree with both of you that the type, possition, etc. must be the same.

Thank you,

Joshua

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