🎉 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!

OpenGL 4 reflections

Started by
110 comments, last by taby 1 year, 7 months ago

taby said:
P.S. Your thinking is infectious. I think I see what you mean now… I must draw each cell once per neighbour, based on neighbour height. Correct?

I did not mean not draw once per neighbor. That's quite expensive and reflections would be still wrong on 2-ring neighbors. Also you'd have to do some complex masking to get reflection only on one certain neighbor.

I would look at the neighbors only to find some averaged reflection plane from their heights per cell. Then draw the cell reflected about this plane just once.
Won't be perfect, but it's the best you can do within the hack, i guess.

The filtered heightmap approach factoring in the current reflection vector should work better, but still drawing each cell just once.

I'll draw an image:

We want to get the reflection plane for the cell with the red circle.
We assume the reflection will appear mostly on the neighboring cell in the direction towards the eye.
So we sample our top down height map in this direction at a distance of one cells width, to see how high the ground at this location is. (green)

The result is then the ideal ‘best fit’ reflection plane for the red cell. And we do the same for all other cells, each having a unique reflection plane then.
But because all planes have the same direction, we can still render each cell just once using only one image for all reflections.

Advertisement

Oh yes, it'll be slow, if it even works.

taby said:
Oh yes, it'll be slow, if it even works.

It won't be slow. Why do you think so?
But i'm not sure if it's useful. Surely not in general, but basically it would extend the ancient planar reflection methods to enable some new applications, if the limitations are respected on level design.
Maybe others adopt it.
Then, beside ‘Carmack's reverse’, we also have ‘Tabys reflections’ and you're famous. :D


ROFL, taby and joej and warp's reflections!

OK, well, here's the deal… the reflecting surfaces have to be the same height. Like in Q-bert.

But yeah, it finally works!

without shadows
with shadows
better shadows

P.S. Are you sure that this method is novel? Would you like to write a short paper about it?

Very cool. I like the first shot the best. The shadows are a bit distracting.

Reminds me on this game:

I was fascinated from the ‘3D’ gfx back then. : )

How did you do it? It looks you just put the reflection plane down one step fro each column maybe? That's nice, because it gives a stable image.

taby said:
P.S. Are you sure that this method is novel?

I'm indeed pretty sure it's new.
So far, games always used environment map tricks to fake reflections. Planar was used mainly for water at constant height, but not much else. The recent Hitman game used multiple reflection planes, though.

This is my favorite environment map hack. It blew me away:

I still play this game til today.
Too bad they never make remakes for the games that i want.

taby said:
Would you like to write a short paper about it?

It's your idea, but maybe i can ‘review’ it then. ; )

Nice that you still play the old games. I got a copy of Thexder a few years ago. I played that game constantly. LOL

Well, I reduced the shadow effect by half, so they're not so distracting. This is all in the shader: https://github.com/sjhalayka/obj_ogl4/blob/main/point.fs.glsl​​

The relevant code is:


vec3 phong_contrib = phongModelDiffAndSpec(false, lightPositions[i], i);
vec3 shadow_contrib = s * phongModelDiffAndSpec(false, lightPositions[i], i);
diffAndSpec += mix(phong_contrib, shadow_contrib, 0.50);

reduced the effect of shadows

Looks better, yes. Though, there is a slight dirty yellowish tint at some spots. I would turn the yellow lights completely white to get rid of that (In case they are yellow at all).

I wonder how soft shadows would work. SM soft shadow approximations are expensive and complicated, but a simple hack would be to use PCF with a wider kernel.
I thought about a spiral shaped kernel. We start on the center and spiral outwards. While doing so, we accumulate the averaged occluder distance to the sampling point. The larger the distance, the larger steps we make on the spiral to get a larger kernel.
The problem is that this does not guarantee to give is the closest occluder to the shading point. Instead we get the closest occluder to the light, but for kind of top down games the depth complexity is low, so i think this could work pretty well.

But the cost for many samples would be pretty high, likely we get some noise, and i don't want to push you of doing further gfx research. ; )

Btw, looks you could optimize:

vec3 phong_contrib = phongModelDiffAndSpec(false, lightPositions[i], i);
vec3 shadow_contrib = s * phongModelDiffAndSpec(false, lightPositions[i], i);
diffAndSpec += mix(phong_contrib, shadow_contrib, 0.50);

is the same as:

vec3 phong_contrib = phongModelDiffAndSpec(false, lightPositions[i], i);
diffAndSpec += phong_contrib * (1+s)*.5;

If i'm right.

I would not really trust GPU compilers to figure this out.

Thanks for the ideas! I really appreciate all of your help. I think I'll skip writing a paper about it, for now anyway.

I also tried some PCF code and it worked OK, but a little bit slower: https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows

I added in some tall columns (to emulate palm trees or whatever). Still works great, except that the palm trees are not counted on the same cell. Hmm.

This topic is closed to new replies.

Advertisement