Lighting gets off when cam rotates [GLSL]

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Lighting gets off when cam rotates [GLSL]

Post by ent1ty »

Hi!
Well, I'm experiencing a bug with shaders. The lighting get's off, as the camera rotates. See:

Screenshot1: lighting is ok
Image

Screenshot2: rotating the camera a bit upwards - the lighting get's off
Image

Screenshot3: rotating the camera a bit more - lighting is totally off by now.Image


Now, I suspect this problem might have to have something to do with normals. I store normals in a render texture, and then later reconstruct these normals on light volumes. (I do all lighting in view space)

How i store the normals in the vertex shader:

Code: Select all

Normal= normalize((gl_NormalMatrix * gl_Normal)).xy;
Normal*= 0.5;
Normal+= 0.5
The fragment shader just writes the Normal(vec2) into the texture.

I then reconstruct the normals as follows:

Code: Select all

vec4 vNormal= texture2D(NormalTex, projCoord.xy);
vNormal.xy*= 2.0;
vNormal.xy-= 1.0;
vNormal.z= -sqrt( -(vNormal.x*vNormal.x) - (vNormal.y*vNormal.y) + 1.0 );
vNormal= normalize(vNormal);
As you can see, I reconstruct the Z component from the X and Y ones, but I don't think the problem is there.


The other option is that the light position is transformed incorrectly from world to view space. Though i doubt it(cos the direction at spot lights gets rotated correctly), here is how I do this(irrlicht)

Code: Select all

irr::core::matrix4 viewMat= Smgr->getVideoDriver()->getTransform(irr::video::ETS_VIEW);
viewMat.transformVect(Pos);

Any ideas will be welcome, as I can't seem to be able to solve this.
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

C'mon, just say anything you can think of, it might lead me to the right path :arrow:
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Why won't you store in the texture also the Z component of the normals? There is room for it in the rendertarget, and that saves you the time of calculating the Z component after, and the posible errors of calculating it wrong.

Code: Select all

Normal = 0.5*(normalize((gl_NormalMatrix*gl_Normal)).xyz)+0.5;

Code: Select all

vec3 vNormal = 2*(texture2D(NormalTex,projCoord.xy).xyz) - 1;
I can't point to any other posible source of problems.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

I don't store the Z component, because the texture is only 2 - channel. I have 3 MRTs:
1. color: ECF_A8R8G8B8
2. normal.xy: ECF_G16R16F
3. depth + specular: ECF_G16R16F

I have(thanks to Luben) determined that the normals are most likely correct, instead of transforming them to the view space, i let them be in the world space and then in the light volume shader just simply showed them on the screen, and they didn't change with camera rotation changed.
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

Ok maybe this has something to do with how I calculate the view space depth?

Code: Select all

vec4 vVertex= gl_ModelViewMatrix * gl_Vertex;
Depth= vVertex.z/CamFar;
Or maybe how I recalculate view pixel position from the depth and view frustum corners:

Code: Select all

vec3 vProjPos= vec3(mix(FarLeftUp.x, FarRightUpX, projCoord.x),
                    mix(FarLeftDownY, FarLeftUp.y, projCoord.y),
                    FarLeftUp.z);
vec4 vPixelPos= vec4(vProjPos * vDepth, 0.0);
I'm just posting anything that I can think of :cry:
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I wouldn't ignore the normal's Z, but i don't know. Are you following any particular implementation?

Maybe losing some precission isn't that noticeable, not at least for the normals, haven't you considered using a A8R8G8B8 texture for the normals/specular buffer, and leave the last texture as an R32F for the depth? That way you save processing power at the cost of some precission in the normals, which isn't really that important when it comes to the lighting equation. But you gain more precission in the depth calculation, and the memory usage keeps the same.
Last edited by Mel on Sat May 07, 2011 4:15 pm, edited 1 time in total.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

Yes... the famous implementation by Mr. Pythagoras :wink:
http://en.wikipedia.org/wiki/Pythagorea ... d_geometry

(cos we know that the length of the normal is 1.0 at all times)


EDIT: I have plenty of time, so a more detailed clarification:

from the wiki ink, we can see that
length = x*x + y*y + z*z
As i already said, normals (normalized ones, to be more precise) have always the length of 1.0
1.0 = x*x + y*y + z*z
Now it's just a simple equation, as we only need to isolate z
z*z = x*x + y*y - 1.0
z = sqrt(x*x + y*y - 1.0)

We know that z component of all normals in view space is negative in GLSL, so
z = -sqrt(x*x + y*y - 1.0)
Now I admit, i don't recall why are the signs in the bracket inverted in my GLSL code, but that's the way it works :wink:
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

Mel wrote:Maybe losing some precission isn't that noticeable, not at least for the normals, haven't you considered using a A8R8G8B8 texture for the normals/specular buffer, and leave the last texture as an R32F for the depth? That way you save processing power at the cost of some precission in the normals, which isn't really that important when it comes to the lighting equation. But you gain more precission in the depth calculation, and the memory usage keeps the same.
Dunno, last time i tried using only 8 bits for normals, i got black artifacts. I will try it again, though.
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Say N= (0,0,1) is the result of the normalize(gl_NormalMatrix * gl_Normal) operation. It may happen since you are calculating the normals in world space. It is transformed to (0.5,0.5) by your shader and (0.5,0.5) becomes (0,0,-1).

(0,0,1) != (0,0,-1)

If you are doing all the lighting calculations in view space, maybe the normals should be done also in view space. As far as i know, gl_NormalMatrix calculates the normals in world space, not in view space.

I didn't know how to reconstruct the normal out of the vectors X and Y, now i understand how. Very interesting.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

As far as I recall, gl_Normal is in world space and by multyplicating gl_NormalMatrix you get normal in view space
lighthouse3D wrote: /* first transform the normal into eye space and normalize the result */
normal = normalize(gl_NormalMatrix * gl_Normal);
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Post by stefbuet »

ent1ty wrote:z component of all normals in view space is negative
Why?

Also I was wondering. Is there any advantage of doing this in view space rather than in world space? Because I've done everything in world space but I see a lot of people doing it like you.

Moreover, be aware that some not that good but not that old computers are supporting ARGB16 but don't support RG16, the color format you're using.

+ I thought when using MRT you had to keep the same color format for all RTT ? How can you have a ARGB8 with those two RG16 :o
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

Whoa WTF.. this is really a blow... first, it seems that storing all 3 components of normal in the texture fixes it.. but.. WHY? HOW? WHAT? I DON'T GET IT! BUGGER ME WITH A FISH FORK :!:


Ok, second blow: stefbufet hacking my thread with what could be called beastliness of forethought. But I like being superior to other people in terms of knowledge, so.. :P

1. Because all surfaces face the camera. Those which don't, won't get rendered. If you're wondering about why is it negative, please direct that question to the OpengGL team.

2. It's easier, cos camera is always at vec3(0.0). Also maybe a bit faster.

3. You just have to have the same amount of bits. ARGB8 - 32 bits RG16 - 32 bits.


Now, any idea at my WHY?
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Post by stefbuet »

my name only have 1 'f' :)
Thx for answering. But you won't be able to disable backface culling using this approch. I guess that's ok :p

For your "why" if it's working from the texture and not with your computation then your computation may fail, maybe it's because of the normal length? When interpolated, normal length can be > 1, did you normalize the normal in the pixel shader rather than in the vertex one ?
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

Hm.. doesn't seem to help.
stefbuet wrote:But you won't be able to disable backface culling using this approch.
You will.. either you see a frontface or a backface, doens't matter, if they're visible, they always have -z view space normal

About your name: sorry, I always get confused between buet and buffet :D
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

Sorry entity, was away longer than i planned :P good you managed to solve it though :)
If you don't have anything nice to say, don't say anything at all.
Post Reply