VOGONS


dgVoodoo 2 for DirectX 11

Topic actions

  • This topic is locked. You cannot reply or edit posts.

Reply 820 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

(Or, old drivers misinterpreted pixel fog parameters?)

Did you mean that new drivers misinterpreted pixel fog parameters? Currently I don't know Direct3D at all. But you gave me very useful information. I'll try to investigate it later.

I've added ability to enable fog for d3d drivers. It prevents some glitches when d3d driver is used as voodoo2 driver. Current build for DX6 testing: http://veg.by/files/nfs3/outbin.7z . See thrash.ini, now it allows to enable fog and light beams for any thrash driver.
Also I've patched dx6.dll (it's that file from NFS4). I've extended texture formats array to 50 items (thank you for your valuable information and debugging). Also I've extended resolutions array to 100 items. Later I'll hide 16-bit resolutions. Currently I've left them for testing purposes.

Best regards, Evgeny

Reply 821 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t
VEG wrote:
Dege wrote:

(Or, old drivers misinterpreted pixel fog parameters?)

Did you mean that new drivers misinterpreted pixel fog parameters? Currently I don't know Direct3D at all. But you gave me very useful information. I'll try to investigate it later.

No, I mean old drivers misinterpreted it.
MS DirectX fog formula for exponential fog is defined as

fog = 1/(e^(d*density))

where d is the distance from the viewpoint (it's 'w' in fact) and 'fog' value is clamped to [0..1], AND 0 means full fog, 1 means no fog.
I did a case study for NFS3 DX6 rendering. This driver enables pixel fog for 3D rendering.
Then, when it renders the background mountains (on Rocky Pass) where


density == 0.0015873016
distance (1/(1/w)) of background polygon == 1.000476947370350393439560507285 😀

If I substitute those values into the formula, then fog == 0.99841320163859803218872152767677.
As fog factor is very close to 1.0 it means no fog at all.

Since dgVoodoo and (supposedly) new(er) hardware do their calculations according to the specification, I'm not wondering why there is no fog at all.
Old hardware probably used fog table to emulate pixel fog (like in Glide) and it was up to the driver to calculate its own table.
I don't know how particular drivers did that, what range of distance they used (there is no 0...65528 limit like in Glide), what distance resolution was the hw capable of, how they truncated the enrty values from 0..1 to 0..255, and so on. Even missing the opposite interpretation of [0..1] range could be present as a bug.
So, I guess the NFS3 developers wrote the code for a buggy driver.

Edit: both my nVidia driver and dgVoodoo works well with DX SDK fog sample, for all types of fog (linear, exp, exp2).

I've added ability to enable fog for d3d drivers. It prevents some glitches when d3d driver is used as voodoo2 driver. Current build for DX6 testing: http://veg.by/files/nfs3/outbin.7z . See thrash.ini, now it allows to enable fog and light beams for any thrash driver.
Also I've patched dx6.dll (it's that file from NFS4). I've extended texture formats array to 50 items (thank you for your valuable information and debugging). Also I've extended resolutions array to 100 items. Later I'll hide 16-bit resolutions. Currently I've left them for testing purposes.

Thanks, very cool, I tried it, it works.
Except that dgvoodoo DX emu doesn't work with DX6 renderer but I already found the cause when I debugged the fog issue.

Reply 822 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

Breath of Fire IV has text issues, random squares behind the text and lines after it. Annoying, but playable. Does not work at all natively (DXGL, WineD3D, DXWnd and D3DWindower also all fail), so can't tell if font rendering issues are because of dgVoodoo2 or Nvidia. It's not an issue with the port as Youtube videos shows no such problem. Edit: on an Intel integrated graphic card, the problem is way worse with dgVoodoo2, but it works natively.

I've just tried it with a clean install, watched the newgame intro but texts were ok.
Should I play it for a while to have the issue?
BTW, is there any way to skip the intro when I start a new game?

Reply 823 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

Thanks for this information. Now I'm debugging this code on my XP and Win 7 machines. It seems that it works in the same way in WinXP and Win7. It seems that you're right.

I've found according code in the nfs3.exe and in the dx6.dll. nfs3.exe sends density as integer 250. dx6.dll makes: 1/250=0.004 and uses this value. As I understand the main problem with density value and it needs some different transformation? I'll investigate how voodoo2.dll transforms same value before using.

Best regards, Evgeny

Reply 824 of 3949, by ZellSF

User metadata
Rank l33t
Rank
l33t
Dege wrote:
I've just tried it with a clean install, watched the newgame intro but texts were ok. Should I play it for a while to have the i […]
Show full quote

Breath of Fire IV has text issues, random squares behind the text and lines after it. Annoying, but playable. Does not work at all natively (DXGL, WineD3D, DXWnd and D3DWindower also all fail), so can't tell if font rendering issues are because of dgVoodoo2 or Nvidia. It's not an issue with the port as Youtube videos shows no such problem. Edit: on an Intel integrated graphic card, the problem is way worse with dgVoodoo2, but it works natively.

I've just tried it with a clean install, watched the newgame intro but texts were ok.
Should I play it for a while to have the issue?
BTW, is there any way to skip the intro when I start a new game?

The intro FMV is skippable, but not the intro itself.

You don't see text artifacts quite at the start, but once you get to the scene I posted a screenshot of (3-4 minutes in, before any real gameplay) you definitely should see it. It won't necessarily appear in that specific text box though... it's a bit random, but it always occurs in that scene.

Reply 825 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

Except that dgvoodoo DX emu doesn't work with DX6 renderer but I already found the cause when I debugged the fog issue.

What is the problem? Is this a problem of dgVoodoo, or something wrong in the dx6.dll and I have to fix it?

One user reported me this error:
2015-06-03-15-17-46-49e22d90.png
It seems that latest dgVoodoo also causes this problem (and maybe this user uses dgVoodoo and this is a cause of his problem).

UPD. I've investigated a little voodoo2.dll according to density. Pseudocode:

if (new_value)
{
tmp = 0;
grFogMode(2);
guFogGenerateExp(&fogtable, 1.0 / (double)new_value);
if (!grGet(4, 4, &tmp) || tmp > 64) return 0;
grFogTable(&fogtable);
result = 0;
}
else
{
grFogMode(0);
result = 1;
}

This code does same conversion (1/new_value) and after this uses guFogGenerateExp function to generate some table (it's an internal function of voodoo2.dll). It seems that I have to investigate internals of this function.

Best regards, Evgeny

Reply 826 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

As I understand the main problem with density value and it needs some different transformation?

Yes, it's a problem. When I manually modified the density value (when the game renders everything else than the background) from 0.0095xxx to 0.95xxx for example,
then I got fog. But any density value I tried were wrong in the sense that all the polygons were equally fogged independently on the distance, it didn't look good.

So, the other problem, it seems that dx6 renderer applies a scene geometry where the polygon distances from the camera are too small. When I looked at the rendered polygons, the 1/w values of their vertices altered between (roughly) 0.11 and 0.99 which means the distance range for fog was in [1..10]. That explains why higher densities gave me an equally fogged appearance.
So, if there would be a way to 'stretch' it distance somehow (by modifying the projection matrix) then all the issue may get solved without modifying density values.
One thing that just come to my mind, is the projection matrix w-friendly? It's a little suspicious the game transforms vetices by a non-w-friendly projection matrix, that's why the w-values are so small. One other thing, I didn't checked, but the game may set the projection matrix to D3D even it feeds D3D with transformed vertices, and old drivers may castigate the w values for the fog calculations. If that's the case then it all could be fixed on dgVoodoo side (but DX spec says that non w-friendly matrices aren't supported).

What is the problem? Is this a problem of dgVoodoo, or something wrong in the dx6.dll and I have to fix it?

No, it's me, some SetCooperativeLevel issue.

You don't see text artifacts quite at the start, but once you get to the scene I posted a screenshot of (3-4 minutes in, before any real gameplay) you definitely should see it. It won't necessarily appear in that specific text box though... it's a bit random, but it always occurs in that scene.

Thanks!
Meanwhile me too had the corruption... 🙁

Reply 827 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

Ok VEG, forget all the crap I wrote before, I found the problem.

dgVodoo and new drivers apply z-based fog instead of w-based one. Why is it? Citation from the SDK:

When eye-relative fog is supported, the system will automatically use eye-relative depth in favor of z-based depth if the provided projection matrix produces z-values in world space that are equivalent to w-values in device space. (You set the projection matrix by calling the IDirect3DDevice7::SetTransform method, using the D3DTRANSFORMSTATE_PROJECTION value and passing a D3DMATRIX structure that represents the desired matrix.) If the projection matrix isn't compliant with this requirement, fog effects will not be applied properly.

Since the default projection matrix is a unit matrix after creating a D3D device, and, since the game doesn't set its projection matrix to D3D (through SetTransform), the unit matrix won't meet the criteria citated above. W-fog is enabled only when a perspective projection matrix is set through D3DDevice::SetTransform, dgVoodoo always checks for that.

It seems to be needless to set the projection matrix when D3D is feeded by transformed vertices but accodring to my old-DX memories, it should always be done to give the driver a chance for calculating the near and far clipping planes for its fogtable calculations and for w-buffering.
It seems old drivers didn't (always) care.

When I forced w-based fog in dgVoodoo then I finally got fog and everything looked fine.
All you should do is set the projection matrix to D3D in the dx thrash drivers and all should be fine.

Reply 829 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

Dege, wow, it sounds good. You are awesome! 😀

But as I said before I don't know Direct3D. I've downloaded DirectX 7 SDK and http://developer.download.nvidia.com/assets/g … v/docs/Fog2.pdf for some theory. While I'm reading (it's first time when I'm touching 3D things), maybe your help will be quicker (if it is not requires too much time for you)...

HRESULT SetTransform(D3DTRANSFORMSTATETYPE dtstTransformStateType, LPD3DMATRIX lpD3DMatrix);

As I understand I have to add a call of this method somewhere. It will be very nice if you provide example which arguments I have to pass to this function.
I assume that the first argument have to be D3DTRANSFORMSTATE_PROJECTION = 3. But I don't know which D3DMATRIX I have to pass. As I understand I have to set some transform which actually doesn't transforms anything 😀 Is it a matrix full of zeroes? (Sorry for a stupid question, I don't know 3D theory at all). Or something like this?

inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
{
m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
m._11 = m._22 = m._33 = m._44 = 1.0f;
}

Or I have to find this D3DMATRIX somewhere in the dx6.dll code?
And another question. When I have to call this method? I mean every frame or only when initialization. I assume that there is have to be some other SetTransform calls with other dtstTransformStateType values, so maybe I have to add this call after this ones.

UPD. I've found code which calls SetTransform methods (0x600030B0). It seems that it sets D3DTRANSFORMSTATE_PROJECTION matrix and skips this call only when error is occurred.
2015-06-03-18-37-54-40b496fb.png
(“call dword ptr [ecx+64h]” is a SetTransform method call).

UPD2. It seems that this code isn't executed for some reason. Maybe it requires some additional call from the NFS3 code when initialization.

Last edited by VEG on 2015-06-03, 16:01. Edited 2 times in total.

Best regards, Evgeny

Reply 830 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

As I understand I have to add a call of this method somewhere. It will be very nice if you provide example which arguments I have to pass to this function.
I assume that the first argument have to be D3DTRANSFORMSTATE_PROJECTION = 3.

Yes. It's enough to call it once, after the D3D device object is created.

But I don't know which D3DMATRIX I have to pass. As I understand I have to set some transform which actually doesn't transforms anything 😀 Is it a matrix full of zeroes? (Sorry for a stupid question, I don't know 3D theory at all). Or something like this?

No, this is a unit matrix which is the default for all transformation types on the device.

I don't know where the game geometry transformations are calculated. Is it done by NFS3 exe or it's duplicated in each thrash driver?
Anyway, you need the same matrix you modified in your patch to allow wide screen.
I don't know if projection data exits in matrix form inside NFS or it's just a few constants somewhere, but the matrix form is

sx   0    0   0
0 sy 0 0
0 0 z1 1
0 0 z2 0

sx: some scale calculated from the horizontal FOV
sy: some scale calculated from the vertical FOV
z1, z2: some values calculated from the near/far planes

What the driver needs from all of this is the 3th and 4th matrix column.
3th is for back-calculating the near/far planes and the 4th is to see that it's a (w-friendly) perspective projection.
If it's difficult to mine that matrix out from the game internals then I think it's enough to provide only 4th column as it's the point. New drivers don't need the clipping planes, old ones didn't care 😀, so the matrix below should be enough (dgVoodoo will be happy with it):

1 0 0 0   (this one defines the near plane at 0.0 and far plane at 1.0
0 1 0 0 but it shouldn't be problem because a unit matrix do the same and old drivers worked with that)
0 0 1 1
0 0 0 0

So,

inline VOID D3DUtil_SetProjectionMatrix( D3DMATRIX& m )
{
m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
m._31 = m._32 = m._41 = m._42 = m._43 = m._44 = 0.0f;
m._11 = m._22 = m._33 = m._34 = 1.0f;
}

If a new driver for native DX checks for the 3th column which still causes the lack of the fog (I doubt it) then a near/far plane could be defined, say, near at 1.0 and far at 65528.0 like it was general in Glide, so

z1 = 65528 / (65528 - 1) = 1.00001526088483
z2 = -(65528 * 1) / (65528 - 1) = -1.00001526088483

inline VOID D3DUtil_SetProjectionMatrix( D3DMATRIX& m )
{
m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
m._31 = m._32 = m._41 = m._42 = m._44 = 0.0f;
m._11 = m._22 = m._34 = 1.0f;
m._33 = 1.00001526088483f;
m._43 = -1.00001526088483f;
}

Edit:

And another question. When I have to call this method? I mean every frame or only when initialization. I assume that there is have to be some other SetTransform calls with other dtstTransformStateType values, so maybe I have to add this call after this ones.

NFS3 didn't call any SetTransform when I debugged it.
So I guess you should force it to execute the code you found. 😀

Reply 831 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

Wow!!! I've forced of executing of this part of code (once at the game start) and fog is appeared. This code could be executed by nfs3.exe via THRASH_setstate function. It seems that it requires to add a call of this function with some magic numbers to code that initializes thrash driver. I think that I have to compare thrash driver init code in the NFS3 and NFS4.
P.S. Thank you for your detailed information. Without your help I could not do anything according this problem.

UPD. It seems that problem not in init code. One bool variable prevents to call all of these SetTransform. This bool is set in a code which calls d3ddevice->GetCaps() and analyses a result. Now I'll try to understand what exactly it tests and why this test is failed.

2015-06-03-19-30-02-54894662.png
(esi=0, ebx=1)

Best regards, Evgeny

Reply 832 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

Then I have 2 candidates:

#define D3DPSHADECAPS_FOGFLAT                   0x00040000L
#define D3DPRASTERCAPS_WBUFFER 0x00040000L

The first is excluded in fact because both dgVoodoo and my native driver exposes that cap.
So it seems NFS ties pixel fog to the presence of w-buffer support for some reason. Which is not supported neither by dgVoodoo nor by modern hw.

Then I guess you use a Geforce FX under WinXP. 😀

Reply 833 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

This test also failed on my XP machine. It seems that it works on XP because

It seems old drivers didn't (always) care

😀 On my machine with Windows XP GeForce G 105M is used.

Offset of the structure: 0x60014C78.
Offsset of checked value: 0x60014CE4.
If I'm not wrong, it's a dpcTriCaps.dwMiscCaps which can't have 0x00040000 bit. Maybe developers would like to write dpcTriCaps.dwShadeCaps where 0x00040000 means D3DPSHADECAPS_FOGFLAT, but made a mistake and because of “old drivers didn't care” they hadn't seen this error. What do you think is better: remove this check completely or replace it to checking of dpcTriCaps.dwShadeCaps?

Last edited by VEG on 2015-06-03, 17:52. Edited 2 times in total.

Best regards, Evgeny

Reply 835 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

I've removed this check. Works nice on Windows 7. 😎

If you compare menu with dx5 and dx6 drivers, you will see that menu in dx6 looks worse. Both of them uses 16-bit for menu. Maybe there is some dithering options? (D3DRENDERSTATE_DITHERENABLE? I'll try it later.) If I force 32-bit mode for menu, it looks ok, but intro video doesn't works in 32-bit mode for some case... Also when I run game in dx8 mode, it works a little smoother than in DX5/DX6 modes (but there is no video at all and one user reported that dashboard isn't displayed in dx8 mode).

Oh, maybe it's time to stop and release... Fog effect works with a D3D driver, it's fantastic! 😀

Best regards, Evgeny

Reply 836 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t
VEG wrote:

I've removed this check. Works nice on Windows 7. 😎

If you compare menu with dx5 and dx6 drivers, you will see that menu in dx6 looks worse. Both of them uses 16-bit for menu. Maybe there is some dithering options? (D3DRENDERSTATE_DITHERENABLE? I'll try it later.) If I force 32-bit mode for menu, it looks ok, but intro video doesn't works in 32-bit mode for some case... Also when I run game in dx8 mode, it works a little smoother than in DX5/DX6 modes (but there is no video at all and one user reported that dashboard isn't displayed in dx8 mode).

Oh, maybe it's time to stop and release... Fog effect works with a D3D driver, it's fantastic! 😀

Cool! When it will be released?

I can't see any difference between dx 5 and 6, I tried it natively, but my card doesn't support dithering (legacy feature that modern hw doesn't support (OK, it still works on Intel GPUs)). 😀
D3DRENDERSTATE_DITHERENABLE is always disabled by default for all versions of DX.
As for smoothness, it's fine for me with all APIs, but there is no dashboard with dx8.

Reply 837 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

I've tried to disable D3DRENDERSTATE_DITHERENABLE in the DX6 (in the original DX5 it's already disabled). Now it looks like DX5 😀
Now I'm contacting with one user which has this error in DX6 mode:
2015-06-03-15-17-46-49e22d90.png
I would like to understand what's wrong and fix it before release.

Best regards, Evgeny

Reply 838 of 3949, by Dege

User metadata
Rank l33t
Rank
l33t

Hmm.. Then D3DRENDERSTATE_DITHERENABLE is enabled by default? I will check it, DX doc doesn't always say true. 😀

That error comes because NFS creates more than one DirectDraw objects, first the exe itself then the dx6 driver later.
It's not a problem but exclusive cooperative level is set on two of them.
It works natively but not with current dgVoodoo. I'll fix it, as cooperative level seems to be bind to the process not a DirectDraw object instance.

Reply 839 of 3949, by VEG

User metadata
Rank Newbie
Rank
Newbie

Then D3DRENDERSTATE_DITHERENABLE is enabled by default?

No. DX6 thrash drivers sets it during init (with many of others render states). I'll read DirectX7 SDK about this states. Maybe it will be good to change some of them 😀 For example, D3DRENDERSTATE_ANTIALIAS (it it is not enabled in DX6 already).

That error comes because NFS creates more than one DirectDraw objects, first the exe itself then the dx6 driver later.

Yes, this is a strange thing. Maybe it's better to cut this code inside nfs3.exe. But it needs investigation why developers did it.

He says that he is not using dgVoodoo. I've sent him a little patched DLL which will display exactly error code.

Last edited by VEG on 2015-06-04, 10:52. Edited 2 times in total.

Best regards, Evgeny