About Store Forum Documentation Contact



Post Reply 
Rendering Problem
Author Message
sydbod Offline
Member

Post: #1
Rendering Problem
The task I am trying to achieve:
In a project like a flight sim game one requires a massive spread between the near plane and far plane for the camera. (typically from 0.1 to 3000000)
The Z buffer can not handle this spread so the image has to be made up of 2 successive world renders.
First the back half of the world is rendered and then the front half of the world is rendered over the top.(I have done this on a number of other game libraries with no problems).

For the above to work, one has to make sure that the second render does not clear out the contents of the first render.
From the game headers, it looks like one is required to run under "Renderer.type(RT_SINGLE_PASS);" to get access and usage to "Renderer.clear_color=0;// set screen clearing color to transparent."
I am setting this color to transparent so that the second render does not erase the first render.

Here is some sample code I am trying.
Code:
/******************************************************************************/
#include "stdafx.h"
/******************************************************************************/
Mesh mbox ,
     mball;
/******************************************************************************/
void InitPre()
{
   App.name("Viewport");
   App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE|APP_ALLOW_SINGLE_PASS;
   Renderer.type(RT_SINGLE_PASS);
   Renderer.clear_color=0;// set screen clearing color to transparent.
   PakAdd("../data/engine.pak");


   //D.full(true);
}
/******************************************************************************/
Bool Init()
{
   Cam.dist=3;

   Material *material=Materials("../data/mtrl/brick/0.mtrl");

   mbox .create(1).base(0).create( Box(4),VTX_TEX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside
   mball.create(1).base(0).create(Ball(1),VTX_TEX0|VTX_NRM|VTX_TNG)          ; // create mesh ball

   // set mesh materials, rendering versions and bounding boxes
   mbox .setMaterial(material).setRender().setBox();
   mball.setMaterial(material).setRender().setBox();

   return true;
}
void Shut()
{
}
/******************************************************************************/
Bool Main()
{
   if(Kb.bp(KB_ESC))return false;
   CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button
   return true;
}
/******************************************************************************/
void RenderBack()
{
   switch(Renderer())
   {
      case RM_SOLID:
         mbox .draw(MatrixIdentity);
         mball.draw(MatrixIdentity);
      break;

      case RM_LIGHT:
         LightPoint(25,Vec(0,3,0)).add();
      break;
   }
}
void RenderFront()
{
   switch(Renderer())
   {
      case RM_SOLID:
         mball.draw(MatrixIdentity);
      break;

      case RM_LIGHT:
         LightPoint(25,Vec(0,3,0)).add();
      break;
   }
}

void Draw()
{
   // render back part to active viewport
   ViewportFull.range=30;
   ViewportFull.from=2.12;
   ViewportFull.set();
   Renderer(RenderBack);

   // render front part to active viewport over the top of the back part
   ViewportFull.range=2.12;
   ViewportFull.from=1.0;
   ViewportFull.set();
   Renderer(RenderFront);
}
/******************************************************************************/

For some reason the "void RenderFront()" is totally obliterating the image from "void RenderBack()" when it should only be adding to the image.

Any help would be greatly appreciated. :(
07-22-2009 08:24 AM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #2
Re: Rendering Problem
well I can tell you one thing,
that the screen is always cleared when calling Render(..)
the alpha of the clear color is just ignored.

but, why aren't you using normal rendering with just shadowing limited using D.shdFrac?
07-22-2009 01:25 PM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #3
Re: Rendering Problem
The problem is not one of creating shadows. It is all about polygon Z fighting.
In an aircraft, the camera sits at the pilots eye point.
The closest part of the cockpit is within about 0.1 unit (meter) from the eye point.
The pilot has to have a view distance of around 300KM (300,000 units). Yes water surfaces and sloping shore lines have to be visiable to these distances for the view to be realistic.
The ratio of the far plane to the near plane for the frustum is therefor 3,000,000 to 1.
With the Z buffer set to 24bit mode (default for windows programs) the maximum ratio for far/near should be no larger than around 5,000 to 1 , otherwise Z fighting of the graphics will become visable. (at 3,000,000 to 1 the terrain polygons are swapping backwards and forwards badly)
I have tried swapping over from the Z buffer mode to a linear W buffer mode to try to extend the range before Z fighting becomes visiable, but that started causing huge problems for close objects inside of the cockpit.

To overcome this Z fighting one has to run with something like 32bit Z buffer mode or larger, but almost none of the current video cards support this.

The only solution that tends to be used is to build up the image in 2 steps.
Have one camera rendering from 0.1 to around 200, and another camera rendering from 200 to 300000.
The image from the furthest view camera gets rendered first, and the image from the closer camera overwrites on top of the further camera image.
This approach works very well, but it can only function if one can stop the first rendered image from being erased.

The proof of concept code I am trying to port across to this library, I created under "DarkGDK", and I am trying to use the same approach.

Basically the cameras were created like
Code:
void SetupCamera( void )
{
        // Camera variables
    float fHorizontalPixels = 1024.0;
    float fVerticalPixels = 768.0;
    float fAspect = fHorizontalPixels / fVerticalPixels;
    float fFov = 1;// in radians *******
    float fNear = 0.3f;
    float fMiddle = 300.0f; //change over point between the 2 cameras
    float fFar = 300000.0f;

    dbMakeCamera(1);// create the second camera.
    dbSetCameraRange ( 1, fNear, fMiddle );
    dbSetCameraRange ( 0, fMiddle, fFar );
    dbSetCameraAspect ( 1, fAspect );
    dbSetCameraAspect ( 0, fAspect );
    dbSetCameraFOV ( 1, 180/3.14 );
    dbSetCameraFOV ( 0, 180/3.14 );

    /********************************************************************************​**************************************
    * Disable the backdrop of the closest camera so we can see the content of the furthest camera behind it.
    * REMEMBER.. cameras create their picture starting from lowest number camera sequentially upto highest numbered camera.
    ***************************************************************************​********************************************/
    dbBackdropOff(1);
}

And the rendering was a simple
Code:
dbSync( ); //Update screen
in the game loop.

Any camera that was active would render.

The problem with the other library was that it was so slow, and it did not provide a means to programmer control the rendering of each individual object.

Because aircraft terrain are so huge, I eventually went to 3 active cameras where the near and far camera moved around the terrain creating their images, and then I overwrote that image with the third camera sitting at world(0,0,0) that only produced the cockpit render, but I want to unwind this third camera and actually reposition the game world every frame so that ALL the rendering cameras will always stay at world(0,0,0).

I hope this explained what I am trying to do.
07-22-2009 02:21 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #4
Re: Rendering Problem
yeah, I see now, this is an interesting concept
in fact it is somehow similar to the 3D Skybox topic which was posted recently.

this too relates to rendering a "different scene" at start, and then overwriting it with "closer scene"

ill try to do something about it. but I think ill be able to look at it only after the weekend. until the weekend ill be outside of my city.
07-22-2009 02:38 PM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #5
Re: Rendering Problem
Thank you for the offer to look at it.
If a solution can be found under "RT_MULTI_PASS" mode rather than "RT_SINGLE_PASS", that would be much better still, as it would leave the water shader intact and working.
Even if it means creating a transparent pass through from the "ViewportFull" to an overlaying full size "SecondaryViewport", that would also be great.
Will be very interested in the outcome, next week some time. smile

EDIT:
Here are some snapshot that I created under D3D.(Wanted to try out D3D)
I gave an overlap of 1% for the far plane of the near camera, with the near plane of the far camera. This helps remove the odd transparent pixel from happening on the joint line if that is not done.

Back camera:
[Image: back-1.jpg]

Front camera:
[Image: front-1.jpg]

Combined view:
[Image: combined-1.jpg]

As can be seen, it can work very effectively.
07-22-2009 03:29 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #6
Re: Rendering Problem
I think I have an idea how to put this functionality into the current renderer of the engine. but I must ask you for patience, since again ill be away for a few days.
08-19-2009 01:18 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #7
Re: Rendering Problem
I thought it will be more complicated, but what I tested actually works,

Please try something like this:

Code:
Bool Init()
{
..
  D.hwDepthBuffer(false); // make sure hardware depth buffer is disabled
..
}


void RenderStuff()
{
// here draw all models normally, for example:
   box .draw(MatrixIdentity);
   ball.draw(MatrixIdentity);
}

void Render()
{
   if(Renderer()==RM_EARLY_Z)return; // don't use EarlyZ at all

   if(Renderer()==RM_SOLID) // use Z splitting only in RM_SOLID mode
   {
      Viewport temp=ViewportActive; // get current viewport
  
      ViewportActive.from=3; // limit rendering from 3 meters only to draw the "background"
      ViewportActive.set();

      RenderStuff(); // draw everything
      D.clearZ(); // clear depth buffer
      
      ViewportActive.from =0.01; // limit rendering from 0.01 to 3 meters to draw the "foreground"
      ViewportActive.range=3;
      ViewportActive.set();

      RenderStuff(); // draw everything

      temp.set(); // restore previous viewport
   }else
   {
      RenderStuff(); // handle other rendering modes normally (without Z splitting)
   }

   if(Renderer()==RM_PALETTE)
  {
     draw particles
  }

   if(Renderer()==RM_LIGHT)
  {
    draw lights;
  }
}

void Draw()
{
   Renderer(Render);
   D.text(0,0.9,S+Tm.fps());
}


I have tested it with water and 1 particle, so far it worked ok, but don't know if it won't do any complications with other effects.
I'll test this more, and possibly include this as a tutorial.
08-19-2009 06:03 PM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #8
Re: Rendering Problem
Thanks for that Esenthel smile

I will have a go with it this weekend and see how things fall in place.

If this works fine with the other shaders (shadow map), volumetric cloud, then a nice little multiplayer open source WW2 South Pacific flight sim will be started.
08-20-2009 06:46 AM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #9
Re: Rendering Problem
Had a quick try with that procedure on the water demo program.
Set the transition distance to 30 units.
It appears that there are some interactions that will require some looking into.In the following picture, the sky background overwrites the long distance image.
[Image: 2c.jpg]

Whenever you get around to looking at this again, there is not immediate hurry as I am a little tied up rewriting a new frontend for another game, that will take a little time.
08-20-2009 11:58 AM
Find all posts by this user Quote this message in a reply
xenno Offline
Member

Post: #10
Re: Rendering Problem
I'm not a programmer and i don't want to say how to do something.
I follow some games based on real time planet rendering, and recently saw an update about Zbuffer.
Could be usefull?

<!-- m --><a class="postlink" href="http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=263350">http://www.gamedev.net/community/forums ... ?jn=263350</a><!-- m -->

Good luck with your project ^^

My PC:
Proccessor: Core2 Quad Q9650
Ram: 4GB
HD: 500 Gb
Video Card: 285GTX 1Gb
Microsoft Windows Vista
08-20-2009 08:42 PM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #11
Re: Rendering Problem
Thanks for that info xenno smile , that information is most interesting.
I did not know could store a frame of data and use it for comparison in a following frame that way.
Then again I am just starting out with playing with shaders.
Shame that article did not give more info about the pixel shader code being used.
Problem for me is that I am using the free version of the program, and therefor it does not give me access to shader creation.

@ Esenthel
Just an idea.
It appears the problem is caused by "D.clearZ(); // clear depth buffer" after the first set of rendering.
If one could create a "D.pushZ(); // push Z values to an end value in depth buffer" Then things should work.
IE: the new function should look at the Z values and if there is a value for a pixel in there rather than maximum distance then that pixel value should be rewritten to one quantum number closer than the maximum value. This way the first rendering image will become an object at the very back end of the Z buffer and will still work for the sky no matter if you are using a shader or an early Z approach for rendering the sky.
08-21-2009 02:05 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #12
Re: Rendering Problem
@xenno: the article uses manually specyfing outDepth position which is not recommended because it eliminates many video card optimizations.

@sydbod: I know what could be the problem, but im just away from my computer until monday (going for friends wedding wink ) and cant look into the codes right now.
(and the idea is good, but generally there is no way for manipulation of the Z buffer, I will do this some other way after I come back)
08-21-2009 07:14 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #13
Re: Rendering Problem
you can try something like this: (ive added new method rebuildDepth)

however I dont guarantee that it will work with other special effects

Code:
/******************************************************************************/
void RenderMeshes()
{
   // draw ground
   ground.draw(MatrixIdentity);

   // draw objects
   for(Int x=-10; x<=10; x++)
   for(Int z=-10; z<=10; z++)object.draw(Matrix().setPos(Vec(x,0,z)*400));
}
/******************************************************************************/
void RenderWithZSplit()
{
   if(Renderer()==RM_EARLY_Z)return; // don't use EarlyZ rendering mode at all

   if(Renderer()==RM_SOLID) // handle solid mode rendering separately
   {
      Viewport temp=ViewportActive; // remember current viewport

      Flt from =ViewportActive.from ,
          to   =ViewportActive.range,
          split=Lerp(from,to,0.001f);

      // set viewport ranges to cover the "background"
      ViewportActive.from =split;
      ViewportActive.range=to;
      ViewportActive.set();

      RenderMeshes(); // render meshes
      D.clearZ    (); // clear Z buffer

      // set viewport ranges to cover the "foreground"
      ViewportActive.from =from;
      ViewportActive.range=split;
      ViewportActive.set();

      RenderMeshes();

      // restore viewport
      temp.set();
      
      // set Z-Buffer from F32 internal render target
      Renderer.rebuildDepth();
   }else
   {
      RenderMeshes();
   }
}
void RenderNormal()
{
   RenderMeshes();
}
/******************************************************************************/
void Render()
{
   if(Kb.b(KB_SPACE))RenderWithZSplit();
   else              RenderNormal    ();
}
/******************************************************************************/
void Draw()
{
   Renderer(Render);
   D.text(0,0.9,S+"Fps "+Tm.fps());
   D.text(0,0.8,S+"Viewport Range "+Round(ViewportActive.range/1000)+"KM");
   D.text(0,0.7,"Hold Space to use Z Splitting");
}
/******************************************************************************/
08-28-2009 12:28 PM
Find all posts by this user Quote this message in a reply
sydbod Offline
Member

Post: #14
Re: Rendering Problem
Thanks for that Esenthel.
I will update the library and try it out during this weekend.
I am sorry to be putting you through all this trouble, and me not even a paying customer at the moment.

If the worst comes to the worst, then maybe I should just switch over to the "W Buffer" rather than the "Z Buffer"
It will require a little more precision or Z/W Buffer enabling/disabling in creating cockpit views (distances between gauge dials and gauge faces etc), but am I correct in assuming that all the normal special effects like water and especially object clouds, etc will work if using "W Buffer"?
08-28-2009 03:10 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #15
Re: Rendering Problem
EE doesnt support W buffering wink
08-28-2009 10:08 PM
Find all posts by this user Quote this message in a reply
Post Reply