Project

General

Profile

Actions

Emulator Issues #12952

closed

Specular highlights and Z-Artifacts in Quake GX per-pixel lighting demo

Added by Luig over 2 years ago. Updated about 2 years ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
% Done:

0%

Operating system:
N/A
Issue type:
Bug
Milestone:
Regression:
No
Relates to usability:
No
Relates to performance:
No
Easy:
No
Relates to maintainability:
No
Regression start:
Fixed in:

Description

Game Name?

Quake GX per-pixel lighting Demo by DRS

What's the problem? Describe what went wrong.

A bunch of the graphical effects are broken in this demo, even on the software renderer. The viewmodel shadows are completely busted and seem to warp and z-fight all the time, and all the specular highlighting seems to be broken as well, also z-fighting with everything and generally just not showing up. In general, it seems to zfight much more than on real hardware.

What steps will reproduce the problem?

Download this; https://files.extremscorner.org/wii/apps/quakeGXSDshareware.zip . It's the shareware demo of quake. Put it on an SD card in the apps folder, and launch it on a modded wii. Then, make a virtual SD card for dolphin with the same setup, and launch that from the homebrew channel in dolphin. You should be able to see the difference, and I have also attached 2 videos showing it on hardware and on emulator.

Is the issue present in the latest development version? For future reference, please also write down the version number of the latest development version.

5.0-16655

Is the issue present in the latest stable version?

Yes

If your issue is a graphical issue, please attach screenshots and record a three frame fifolog of the issue if possible. Screenshots showing what it is supposed to look like from either console or older builds of Dolphin will help too. For more information on how to use the fifoplayer, please check here: https://wiki.dolphin-emu.org/index.php?title=FifoPlayer

3frame fifolog of the game on dolphin:
https://drive.google.com/file/d/1sWLH6PwUwwrdhCqkK2t_7K91sLdKsJmj/view?usp=sharing
recording on my wii:
https://cdn.discordapp.com/attachments/667188545475051541/985719256446541845/2022-06-12_20-26-23-1.webm
recording on dolphin:
https://cdn.discordapp.com/attachments/280095869825712128/985734362643452014/2022-06-12_21-34-27.mp4

What are your PC specifications? (CPU, GPU, Operating System, more)

Ryzen 3600
GTX 1060
16gb 3600mhz CL16 RAM

Is there anything else that can help developers narrow down the issue? (e.g. logs, screenshots,
configuration files, savefiles, savestates)

He never gave out his source code unfortunately, so it's technically a GPL violation. Nonetheless, it's fascinating, here's the link where he talked about it over 10 years ago. https://forum.beyond3d.com/threads/normal-mapping-wii-demo.46425/
More useful to you however, on the devkitpro forums, he posted his method and code for normal mapping, which you can find here.
https://devkitpro.org/viewtopic.php?t=1564#p3510
unfortunately I couldn't get into contact with him.


Files

real_hardware.png (627 KB) real_hardware.png image from the hardware fifoplayer pokechu22, 06/30/2022 10:28 PM
nmcube_new.dff (1.22 MB) nmcube_new.dff pokechu22, 07/01/2022 04:38 AM
Actions #1

Updated by pokechu22 over 2 years ago

The fifolog shows what you've described as z-fighting even when looping the same frame - which is odd, as normally that should be deterministic. For object 436, which is part of the wall, the fifo analyzer shows this:

Primitive GX_DRAW_TRIANGLE_FAN (4) VAT 2

c3f80000 (-496) 45180000 (2432) c2c00000 (-96)  3f800000 (1) 00000000 (0) 00000000 (0) 00000000 (0) 00000000 (0) be000000 (-0.125) 00000000 (0) 3e000000 (0.125) 00000000 (0)  41a30000 (20.375) 40080000 (2.125)  
c3f80000 (-496) 45140000 (2368) c2c00000 (-96)  3f800000 (1) 00000000 (0) 00000000 (0) 00000000 (0) 00000000 (0) be000000 (-0.125) 00000000 (0) 3e000000 (0.125) 00000000 (0)  419f0000 (19.875) 40080000 (2.125)  
c3f80000 (-496) 45140000 (2368) c2800000 (-64)  3f800000 (1) 00000000 (0) 00000000 (0) 00000000 (0) 00000000 (0) be000000 (-0.125) 00000000 (0) 3e000000 (0.125) 00000000 (0)  419f0000 (19.875) 3ff00000 (1.875)  
c3f80000 (-496) 45180000 (2432) c2800000 (-64)  3f800000 (1) 00000000 (0) 00000000 (0) 00000000 (0) 00000000 (0) be000000 (-0.125) 00000000 (0) 3e000000 (0.125) 00000000 (0)  41a30000 (20.375) 3ff00000 (1.875)  

but RenderDoc shows the following input vertex data:

0 x -496.00  2368.00 -96.00  1.00  0.00  0.00  0.00  0.125  0.00  2368.00 -64.00  1.00  19.875  2.125
1 x -496.00  2368.00 -64.00  1.00  0.00  0.00  0.00  0.125  0.00  2432.00 -64.00  1.00  19.875  1.875
2 x -496.00  2432.00 -96.00  1.00  0.00  0.00  0.00  0.125  0.00  2368.00 -96.00  1.00  20.375  2.125
3 x -496.00  2432.00 -64.00  1.00  0.00  0.00  0.00  0.125  0.00  0.00  0.00  0.00  20.375  1.875

or, on a later loop:

0 x -496.00  2368.00 -96.00  1.00  0.00  0.00  0.00  0.125  0.00  2368.00 -64.00  1.00  19.875  2.125
1 x -496.00  2368.00 -64.00  1.00  0.00  0.00  0.00  0.125  0.00  2432.00 -64.00  1.00  19.875  1.875
2 x -496.00  2432.00 -96.00  1.00  0.00  0.00  0.00  0.125  0.00  2368.00 -96.00  1.00  20.375  2.125
3 x -496.00  2432.00 -64.00  1.00  0.00  0.00  0.00  0.125  0.00  5.1115587490E+19 -1.6861106051E+34  1.2160093665E-16  20.375  1.875

It looks like the binormal and tangent are corrupted; they should be tangent=(0, 0, -.125) and binormal=(0, .125, 0) but instead we're getting tangent=(0, .125, 0) and binormal=garbage.

Since it's input the vertex data for the vertex shader that's getting corrupted, this is probably a vertex loader issue. And, I can easily test this: by uncommenting the COMPARE_VERTEXLOADERS define here, Dolphin checks the JITed vertex loader against the older software vertex loader (VertexLoader.cpp, which is not to be confused with the software renderer's vertex loader in SWVertexLoader.cpp, which serves a different purpose.) With that enabled, Dolphin logs "The two vertex loaders have loaded different data" a lot. And forcing the software vertex loader to be used by deleting the lines below results in (what seems to be) proper rendering.

My guess is that this is broken because it's supplying tangent and binormal vectors directly instead of using indices; tangent and binormal vectors are uncommon in general, and I guess other games just don't use them directly that often, so we have a bug in that case that went unnoticed. Though, an embossing demo I wrote also uses direct tangent and binormal vectors and doesn't have this issue.

I also took a screenshot with the hardware fifoplayer to see what that fifolog looks like on real hardware.


This also affects nmcube.dol from the same beyond3d post, (still) available at http://www.sd-engineering.nl/nmcube.dol or http://www.sd-engineering.nl/boot.zip (though both of these download weirdly). Here are some videos of it: on real hardware, on Dolphin broken, and on Dolphin using the software vertex loader.


Just as a note, there also is an issue with the fifo recorder regarding tangent and binormal vectors; in the NormalIndex3 mode, it doesn't record enough data to always save the tangent and binormal. It's fixed by PR 10676. That issue does not apply here, as quake and nmcube are using direct vertex components instead of indices. And a second note: recording nmcube.dol doesn't work due to the textures not being recorded. This also affects the original lesson7 and lesson8 demos, and has to do with them only using one texture and never changing it. This seems to be a regression (it works fine in 5.0), but it wouldn't affect quake.

Actions #2

Updated by Luig over 2 years ago

Thanks for the great response! I didn't even think to test nmcube on real hardware, I tested it on dolphin and thought it looked weird. It looks much better on hardware.

Actions #3

Updated by pokechu22 over 2 years ago

I've (hack-)fixed the fifo recorder issue (PR 10798), so here's a recording of that (which should play properly without that fix).

Actions #4

Updated by pokechu22 over 2 years ago

The difference between my embossing test and this broken one is that I have NormalIndex3 mode disabled, while the Quake GX demo and nmcube have it enabled. (I use GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_F32, 0) while they use GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT3, GX_F32, 0).) GX_NRM_NBT3 enables NormalIndex3 while GX_NRM_NBT disables it, though libogc doesn't explain this or the difference between those and GX_NRM_XYZ at all. (Libogc also has bad behavior if you mix GX_VA_NRM and GX_VA_NBT; see PR 10672.)

As far as I can tell, the problem is that NormalIndex3 mode should not do anything when direct vertex components are used, but currently the vertex loaders do something wrong. Unfortunately, these vertex loaders are in assembly, and their logic is hard to follow. (Part of that is that NormalIndex3 mode is jank in general with how it offsets things (see PR 10676. It apparently was added in a later development hardware revision based on e.g. table V of this patent, and even the documentation there is inconsistent about whether it biases by modifying the index or adding a number of bytes...)

I also confirmed that this also affects the ARM64 vertex loader used on Android.

Actions #5

Updated by pokechu22 over 2 years ago

  • Status changed from Accepted to Fix pending

Should be fixed by https://github.com/dolphin-emu/dolphin/pull/10808 (though I haven't tested the ARM version, and modifying assembly without testing it is not a recipe for success, so it'll probably need a bit more work).

Actions #6

Updated by JMC4789 about 2 years ago

  • Status changed from Fix pending to Fixed

The change has been merged.

Actions

Also available in: Atom PDF