Bump Mapping sample

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
Twada
DC Developer
DC Developer
Posts: 42
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Bump Mapping sample

Post by Twada »

Since there were few bump mapping samples, I created it.
Texture conversion was done with texconv.(https://github.com/tvspelsfreak/texconv)
test2.gif
test2.gif (1.43 MiB) Viewed 2771 times
Source code: (Bug fix)
bump02.rar
(1.23 MiB) Downloaded 88 times
The features of Dreamcast bump mapping are as follows.
  • Only flat shading is supported.
  • Convert the light vector to tangent space and assign it to the offset color for use.
  • Bump-mapped polygons change only in brightness, so overlay polygons to add color.
The procedure for bump mapping is as follows.
  • Convert the light vector to local space and find the elevation (T) and azimuth (Q) by the three inner products.

Code: Select all

T = clamp(dot(Normal, LightVector), 0, 1) * (π * 0.5)
Q = atan2(dot(Binormal, LightVector), dot(Tangent, LightVector)) + π

K1 = (1.0 - H) * 255
K2 = sin(T) * H * 255
K3 = cos(T) * H * 255
q= (Q / (2 * π)) * 255

OffsetColor = (K1 << 24) | (K2 << 16) | (K3 << 8) | q

Only flat shading is supported, so only one light vector can be received per face.
So, in this sample, the values ​​of the three vertices are averaged and used.
In addition, cheating is required when used in Gouraud shading.
Notice that the hardware expresses the elevation angle (T) in two terms, K2 and K3. It seems that K2 determines the brightness of the plane perpendicular to the light vector, and K3 determines the brightness of the plane parallel to the light vector.
In other words, by setting K2 to a fixed value, it can be made to appear without shading. Since K3 is calculated properly, the shadow orientation of the bump map is drawn.

Use it for you!

Unfortunately, this sample sometimes inverts the bump mapping. I can't think of a good solution. :(
Edit:Bug fix. It was a mistake at vertex, sorry.
-Tashi
These users thanked the author Twada for the post (total 2):
Ian Robinsonfreakdave
User avatar
Ian Robinson
DC Developer
DC Developer
Posts: 114
Joined: Mon Mar 11, 2019 7:12 am
Has thanked: 206 times
Been thanked: 41 times

Re: Bump Mapping sample

Post by Ian Robinson »

Really nice work thank you.. There was very little samples like this
Nice to see the use of Dream_hal math functions as well :)
Bravo!!
Twada
DC Developer
DC Developer
Posts: 42
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Re: Bump Mapping sample

Post by Twada »

Thank you!
For Gouraud shading, it's a good idea to comment out lines 254 to 255 and uncomment lines 258 to 259.
Since the commit_zclip_tristrip_bumpmap function uses the average value of the three vertices, the processing is heavy and the result is not beautiful.
After all simple is the best.
Dreamhal is very flexible and convenient!
These users thanked the author Twada for the post:
Ian Robinson
Twada
DC Developer
DC Developer
Posts: 42
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Re: Bump Mapping sample

Post by Twada »

This is the Power of Dreamcast!
bump03.gif
bump03.gif (2.32 MiB) Viewed 2077 times
bump21.rar
(946.9 KiB) Downloaded 52 times
Fix brightness.

After reading that the original Xbox game used a normal map of the object space, I tested it on the Dreamcast.
With static objects, you don't need a per-vertex inner product or atan2. The calculation is done only once per object!

This chair has 82 polygons and 53 vertices. It is drawn three times to give the highlights an atmosphere.
To create a normal map of the object space, we used 3DCoatTexture.
The z-directional channels were clamped in paint software for conversion in Texconv.

The Dreamcast normal map system cannot have negative Z values.
In the case of this test, it will go wrong if the lights move below the horizon.
If you separate the z-directional polygons from the negative z-directional polygons beforehand, and switch the values in software, you would have a 360-degree normal map representation.
These users thanked the author Twada for the post (total 2):
Ian Robinsonfreakdave
User avatar
bbmario
DCEmu Freak
DCEmu Freak
Posts: 88
Joined: Wed Feb 05, 2014 5:58 am
Has thanked: 9 times
Been thanked: 3 times

Re: Bump Mapping sample

Post by bbmario »

Holy crap that is kind of awesome. I wonder why no games used it.
Twada
DC Developer
DC Developer
Posts: 42
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Re: Bump Mapping sample

Post by Twada »

The intensity color mode allows per-pixel shading with almost no CPU load. However, it does put a load on the PVR.
I think it was only after Xbox that this technique became widely used. The Dreamcast disappeared a little too quickly. I would love to see it used for future homebrew.
User avatar
ThePerfectK
Insane DCEmu
Insane DCEmu
Posts: 147
Joined: Thu Apr 27, 2006 10:15 am
Has thanked: 27 times
Been thanked: 35 times

Re: Bump Mapping sample

Post by ThePerfectK »

bbmario wrote: Mon Jul 11, 2022 4:35 pm Holy crap that is kind of awesome. I wonder why no games used it.
A few games do in fact use it. The best known example is this coin in Shenmue 2:

Image

The technique is also outlined in the official Dreamcast development manuals:

Image
Twada wrote: Tue Jul 12, 2022 8:30 amI think it was only after Xbox that this technique became widely used.
Right, there are a few OG Xbox games that do normal mapping as well, but it wasn't really until the Xbox 360 that the technique became widely known in the mainstream. For better and worse, Perfect Dark Zero is basically the game that introduced bump mapping to the masses.
Still Thinking!~~
User avatar
Ian Robinson
DC Developer
DC Developer
Posts: 114
Joined: Mon Mar 11, 2019 7:12 am
Has thanked: 206 times
Been thanked: 41 times

Re: Bump Mapping sample

Post by Ian Robinson »

Twada wrote: Mon Jul 11, 2022 2:19 am This is the Power of Dreamcast!
bump03.gif

bump21.rar
Fix brightness.

After reading that the original Xbox game used a normal map of the object space, I tested it on the Dreamcast.
With static objects, you don't need a per-vertex inner product or atan2. The calculation is done only once per object!

This chair has 82 polygons and 53 vertices. It is drawn three times to give the highlights an atmosphere.
To create a normal map of the object space, we used 3DCoatTexture.
The z-directional channels were clamped in paint software for conversion in Texconv.

The Dreamcast normal map system cannot have negative Z values.
In the case of this test, it will go wrong if the lights move below the horizon.
If you separate the z-directional polygons from the negative z-directional polygons beforehand, and switch the values in software, you would have a 360-degree normal map representation.
Wonderful work on this .. and comments and details in the src code..
park
DCEmu Junior
DCEmu Junior
Posts: 46
Joined: Tue Jun 24, 2008 10:46 am
Has thanked: 0
Been thanked: 0

Re: Bump Mapping sample

Post by park »

Twada wrote: Tue Jul 12, 2022 8:30 am The intensity color mode allows per-pixel shading with almost no CPU load. However, it does put a load on the PVR.
I think it was only after Xbox that this technique became widely used. The Dreamcast disappeared a little too quickly. I would love to see it used for future homebrew.
Maybe this is a stupid question but maybe using a empty or special normal map applied to this would you be able to force something similar to phong shading ? ( lighting calculated per pixel across the entire surface instead of gouraud? )

And your example applied to skeletal animated would be possible?
User avatar
Ian Robinson
DC Developer
DC Developer
Posts: 114
Joined: Mon Mar 11, 2019 7:12 am
Has thanked: 206 times
Been thanked: 41 times

Re: Bump Mapping sample

Post by Ian Robinson »

https://streamable.com/a6otlo

Hardware 60fps capture
Twada
DC Developer
DC Developer
Posts: 42
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Re: Bump Mapping sample

Post by Twada »

ThePerfectK wrote: Fri Jul 15, 2022 7:08 am The technique is also outlined in the official Dreamcast development manuals:
As you say, Dreamcast has a great normal mapping system!
I think that the reason why it was used only a few times is that the amount of calculation was too large.
I also played Shenmue 2, but forgot about the coins.

normal.png
An overview of normal mapping. Please forgive me though the Y direction is different from the sample.

Ian Robinson wrote: Fri Jul 15, 2022 10:43 pm Wonderful work on this .. and comments and details in the src code..
Thanks for the video!
A brief description of the sample code.
render.c: Hijacking the KOS PVR. There is no problem with PVR. It supports multipath for the time being.
matrix.c: Matrix operation. Functions with "2" are functions for converting {x, y, z, w} to {z, x, y, 1 / z}.
mesh.c: Sorry, It's garbage.
vertex32.c: Send the triangle strip to TA. Z clipping using {z, x, y, 1 / z}.
chair.h: Chair data.
example.c: This is the main process.

draw_init() : Loads the texture and creates a polygon header. Arrange the UV and vertex color side by side.
draw_mesh() : Create a camera matrix for each frame and convert vertices to coordinates.
draw_frame() : This is the main loop. Updates the light vector in the polygon header.
vertex32_t vert_workbuffer [1024 * 128] : Vertex work buffer. Arrange the converted vertices here.

park wrote: Fri Jul 15, 2022 10:46 pm Maybe this is a stupid question but maybe using a empty or special normal map applied to this would you be able to force something similar to phong shading ? ( lighting calculated per pixel across the entire surface instead of gouraud? )
And your example applied to skeletal animated would be possible?
This is full pixel-by-pixel shading! You won't see polygon lines like Gouraud shading!
However, if you do bone deformation or morphing, you will get a seam in that area. Because it is really flat shading.
I'm thinking about doing Phong shading too. However, I cannot keep only specular highlights well. Please let me know if there is a good way!
These users thanked the author Twada for the post (total 2):
Ian Robinsonfreakdave
TapamN
DC Developer
DC Developer
Posts: 104
Joined: Sun Oct 04, 2009 11:13 am
Has thanked: 2 times
Been thanked: 88 times

Re: Bump Mapping sample

Post by TapamN »

park wrote: Fri Jul 15, 2022 10:46 pmMaybe this is a stupid question but maybe using a empty or special normal map applied to this would you be able to force something similar to phong shading ? ( lighting calculated per pixel across the entire surface instead of gouraud? )
I've worked a bit on trying to get something like that working, but then decided there were other things I should finish first. The PVR can't interpolate the light vector (or normals) they way it's normally done for phong shading, so just trying to add a flat normal map won't work.

My idea is to use a normal map of a sphere (like the center bottom sphere in this image, but smooth) as an environment map, then adjust the light direction relative to the camera. So the vertex X&Y normals are used to pick out parts of the sphere normal map.

While it's impossible for a PVR normal map to have a normal with negative Z, it's actually possible to have the light vector go below the horizon if you invert the blending. So instead of combining the texture and normal map with glBlendFunc(GL_DST_COLOR, GL_ZERO), when the light is below the horizon of the polygon, you instead use glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO) and invert the light direction and power value.

Here's a pseudo-code example:

Code: Select all

//Light vector in texture space, X is along U axis, Y is along V axis, Z is out of the texture
float lx, ly, lz;
unsigned int exponent = 0;	//PVR uses 0 for power of 1.0, and 255 is almost zero

if (lz < 0) {
	lx = -lx;
	ly = -ly;
	lz = -lz;
	exponent ^= 0xff;
	
	set_blend_mode(&t, PC_INV_SRC_ALPHA, PC_ZERO);
}

unsigned int azimuth  = fatan2(ly, lx) / (2*M_PI) * 255;
unsigned int toplight = lz * 255;
unsigned int sidelight = fsqrt(1-lz*lz) * 255;

colorpow &= 0xff; sidelight &= 0xff; toplight &= 0xff; azimuth &= 0xff;

offsetcolor = pack(exponent, toplight, sidelight, azimuth);
These users thanked the author TapamN for the post (total 3):
Ian RobinsonTwadafreakdave
park
DCEmu Junior
DCEmu Junior
Posts: 46
Joined: Tue Jun 24, 2008 10:46 am
Has thanked: 0
Been thanked: 0

Re: Bump Mapping sample

Post by park »

TapamN wrote: Sat Jul 16, 2022 6:09 am
park wrote: Fri Jul 15, 2022 10:46 pmMaybe this is a stupid question but maybe using a empty or special normal map applied to this would you be able to force something similar to phong shading ? ( lighting calculated per pixel across the entire surface instead of gouraud? )
I've worked a bit on trying to get something like that working, but then decided there were other things I should finish first. The PVR can't interpolate the light vector (or normals) they way it's normally done for phong shading, so just trying to add a flat normal map won't work.

My idea is to use a normal map of a sphere (like the center bottom sphere in this image, but smooth) as an environment map, then adjust the light direction relative to the camera. So the vertex X&Y normals are used to pick out parts of the sphere normal map.

While it's impossible for a PVR normal map to have a normal with negative Z, it's actually possible to have the light vector go below the horizon if you invert the blending. So instead of combining the texture and normal map with glBlendFunc(GL_DST_COLOR, GL_ZERO), when the light is below the horizon of the polygon, you instead use glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO) and invert the light direction and power value.

Here's a pseudo-code example:

Code: Select all

//Light vector in texture space, X is along U axis, Y is along V axis, Z is out of the texture
float lx, ly, lz;
unsigned int exponent = 0;	//PVR uses 0 for power of 1.0, and 255 is almost zero

if (lz < 0) {
	lx = -lx;
	ly = -ly;
	lz = -lz;
	exponent ^= 0xff;
	
	set_blend_mode(&t, PC_INV_SRC_ALPHA, PC_ZERO);
}

unsigned int azimuth  = fatan2(ly, lx) / (2*M_PI) * 255;
unsigned int toplight = lz * 255;
unsigned int sidelight = fsqrt(1-lz*lz) * 255;

colorpow &= 0xff; sidelight &= 0xff; toplight &= 0xff; azimuth &= 0xff;

offsetcolor = pack(exponent, toplight, sidelight, azimuth);
In another forum i was reading a old renderware material function the sdk had for ps2 to allow it to perform environment bumpmap. Ill quote it on the bottom. I dont understand it too well but it seems it somehow blends bumpmap with environment map to allow it to be perturbed. Is this possible on dc?
PlayStation 2
In RenderWare Graphics for PlayStation 2,
RpMatFXMaterialSetEnvMapFrameBufferAlpha() is used to modulate the environment
mapping by frame buffer alpha (for those video modes that support it). For the bumpenvironment
mapping effect, the frame buffer alpha contains the bump alpha value and
the result gives the appearance of the reflection being affected by the bumps.
Twada
DC Developer
DC Developer
Posts: 42
Joined: Wed Jan 20, 2016 4:55 am
Has thanked: 18 times
Been thanked: 53 times

Re: Bump Mapping sample

Post by Twada »

park wrote: Sun Jul 17, 2022 7:38 pm In another forum i was reading a old renderware material function the sdk had for ps2 to allow it to perform environment bumpmap. Ill quote it on the bottom. I dont understand it too well but it seems it somehow blends bumpmap with environment map to allow it to be perturbed. Is this possible on dc?
I believe it is possible to use a bump map to blend shadow colors and highlights into the render texture. Creating a refraction effect requires vertex movement.

Applying a bilinear filter to be un-twiddled textured is expensive, so I would suggest rendering to a reduced buffer and then be twiddled it using TapamN's method.
TapamN wrote: Tue Aug 06, 2013 12:42 pm One trick to applying fullscreen bilinear render-to-texture results to the main framebuffer on the PVR is having the PVR twiddle the texture. Untwiddled textures, like a render-to-texture result, have half speed bilinear filtering, so there's a big difference in fillrate consumed if you first twiddle the texture. It's possible to have the PVR twiddle the texture by taking advantage of the fact that the process to untwiddle a texture (which the PVR does when drawing from a twiddled texture) can generate the twiddled version of the texture if you repeat it 3 times. With this trick, I was able to get my bloom demo to reach 60 FPS.
These users thanked the author Twada for the post:
Ian Robinson
Post Reply