🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Cheap way to do paint job reflections?

Started by
5 comments, last by MJP 3 years, 8 months ago

I am working on a driving game and I have been thinking about how to do cheap environment reflections for the bodies of the cars. I cannot seem to wrap my head around how to do this, and no amount of googling seems to give me any good articles on the subject. I am not looking for “true” reflections off the surface of the car. That would require raytracing or some other similarly heavy operation. I just want a cheap, “good enough”, effect to make it look like the surface is reflective. These kinds of effects have been around since forever. Eg. here is Sega Rally 2 from 1998: https://www.youtube.com/watch?v=6IslY1X_3qs​ See the fake reflections in the windshields.

How are these typically done? My first idea was to use cube maps. I can already render cube maps, and I can even blend between multiple cube maps on the fly, but the more I think about it, the more it seems that cube maps are fundamentally the wrong thing here. If a part of the car body is mostly planar, that would make the system sample the same color from the (blended) cube map for the whole area of the body, while I would instead want it to look almost like a mirror. Any ideas?

Advertisement

Almost immediately after posting this I came up with a possible solution. Rather than using the surface normal to sample the cube map, I should instead specify a position somewhere inside the car body and use the direction from that point to the surface fragment as the cube map sample direction. There will be some warping, but it will most likely be “close enough” for my use case.

Cubemaps are still really popular for this sort of game. For a racing game it's quite common to render a dynamic cubemap every frame from roughly the position of the player car, and use that for the reflections on that car. You can then mix that with other static or dynamic cubemaps placed throughout the track to handle reflections on other cars or surfaces.

It's possible to add some amount of parallax to cubemap reflections with some shader code. Many games will intersect the reflection ray with a box or some other convex shape, which roughly approximates the parallax that you would get from true reflections. For a racing game many of your reflections will be of the sky, which has no visible parallax because it's very far away. For the ground, you can try intersecting your reflection ray with the ground plane to get approximate parallax. In general you don't need to be exact to make the reflections convincing, this is especially true for reflections on curved surfaces.

MJP said:

Cubemaps are still really popular for this sort of game. For a racing game it's quite common to render a dynamic cubemap every frame from roughly the position of the player car, and use that for the reflections on that car. You can then mix that with other static or dynamic cubemaps placed throughout the track to handle reflections on other cars or surfaces.

It's possible to add some amount of parallax to cubemap reflections with some shader code. Many games will intersect the reflection ray with a box or some other convex shape, which roughly approximates the parallax that you would get from true reflections. For a racing game many of your reflections will be of the sky, which has no visible parallax because it's very far away. For the ground, you can try intersecting your reflection ray with the ground plane to get approximate parallax. In general you don't need to be exact to make the reflections convincing, this is especially true for reflections on curved surfaces.

There's even a clever hack my google fu can't find of cheaply re-using the dynamic cubemap as diffuse GI for the hero car as well, looks great on there. I suppose it's probably just downsampling the cubemap a ton and estimating diffuse from that. Looks great though and afaik it's pretty much the gold standard for driving games still.

And there's the question of carpaint brdfs, but though I know it's a subject researched to death I can't find anything specific and 100% useful.

render a dynamic cubemap every frame from roughly the position of the player car

MJP, just out of interest, is this done by a single projection matrix that allows this kind of observing of scene from one single run of draw calls? (should be in my opinion)

There's no single projection that can cover an entire omnidirectional cubemap, as far as I'm aware. Traditional cubemap rasterization requires 6 projections, dual-paraboloid requires 2 (but has artifacts from linear rasterization if the geometry is not tessellated enough), and tetrahedron requires 4. There are various techniques that can potentially let you save draw calls with various tradeoffs, the most recent of which are handled by the multi-view functionality available in DX12 and Vulkan.

This topic is closed to new replies.

Advertisement