[SOLVED] Possible Camera Bug

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!
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

[SOLVED] Possible Camera Bug

Post by Kalango »

Hey there.
I'm having a problem with Irrlicht camera and shader computing.
The problem is that when i set the camera as the eye to calculate specular component in my shader the specular glow is placed wrongly. I noticed the same stuff happening on the shader example that come with the API.
The camera absolute position seem to be transposed in the Y and Z axes a little bit, the whole thing only work when i move the camera a bit....
Here are some screens to illustrate what i mean:

here the lighting seem wrong, there is no specular glow where it supposed to be
Image
here its all "fine", i moved the camera behind the object...
Image
here i put the camera afar the object and it seem ok too....
Image
The same stuff happens in the shader example as i said before. The only way i cound figure this problem out was ataching a cubenode to the camera and movind it so it could match the correct eye position.
I'm also sure its not a videocard problem, i experienced this problem in other pcs and its all the same.
My videocard is a GeForce GT 240...
Help anyone?

PS: sorry for the big images
Last edited by Kalango on Thu Dec 16, 2010 4:17 pm, edited 1 time in total.
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

Oh well i guess i have no luck here in the forums "/
*BUMP*
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No, you're just too impatient. This is an advanced question (which is why I moved the post) and will require some thinking. However, you have the shininess in both images. At least there's a light effect in both images. Are you sure that this should be different? What about the normals, are they correct? Did you normalize_normals in case you scaled the mesh? Try DirectX driver as comparison (or OpenGL if you use d3d as default)
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

The demo uses HLSL shader, so i cant swap between OpenGL and see if it works.
The diffuse light is ok, the problem is the specular light, wich i need the spectator/eye position in space to calculate the shiny red glow. I just normalized te normals(even tho the model has no scale) and its all the same.
The problem is with the camera position, as you can see in the images, there is still a glow, but the glow is positioned like the eye was somewhere else(up and forward).
The camera position dont seem to be correct, but it looks all fine when i set the camera as a parent of something else(a bug also happens using the camera BB for collisions... i posted years ago about it....i'll try to find the link later).
Weird thing is that the same bug happens in the irrlicht shader demo when using High Level Shaders. The lighting is not always updated to the cube vertices positions...
Maybe there is some sort of brok conversion between modelview space when we pass he matrix to the shader or something "/
Btw sorry for the rush... :lol:
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

It seems like it's just a shader math problem. How are you certain the issue isn't in your shader itself?
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

I think not, since the same problem happens in irrlicht shader example.
if you like i can post the source code....
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

BUMP
After i overlooked the problem i found out that the error lies in the light position.
Its odd since it seems to be all ok. But the light does not cast diffuse/specular in the right place as it should:
Image
Here is my shader code and my shader callback, sorry for the slopy code and comments, i'm testing stuff so most of the things in the shader and inside the callback are temporary...
Shader CallBack and structs:

Code: Select all

///Shader material structures
//material struct
struct ShaderMaterial
{
    video::SColorf Ambient;
    video::SColorf Emissive;
    video::SColorf Diffuse;
    video::SColorf Specular;
    float Shininess;
};
//light struct
struct ShaderLight
{
    core::vector3df Position;
    video::SColorf Color;
};

class MyShaderCallback : public video::IShaderConstantSetCallBack
{
public:

    scene::ISceneNode *eyeNode;
    scene::ISceneNode *lightNode;

    ShaderMaterial mat;
    ShaderLight light;

    MyShaderCallback(scene::ISceneNode *node, scene::ISceneNode *spectator)
    {
        mat.Ambient =  video::SColorf(0, 0, 0);
        mat.Emissive = video::SColorf(0, 0, 0);
        mat.Diffuse =  video::SColorf(0.5, 0.5, 0.9);
        mat.Specular = video::SColorf(1, 0, 0);
        mat.Shininess = 50;

        light.Color = video::SColorf(1, 1, 1);
        lightNode = node;
        eyeNode = spectator;
    }

    virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
    {
        video::IVideoDriver* driver = services->getVideoDriver();
        //quando uma variável é passada como argumento da função principal de tipo UNIFORM é necessário o '$' antes do nome no set constant

        ///Projecion X View X World
        core::matrix4 modelViewProj = driver->getTransform(video::ETS_PROJECTION);
        modelViewProj *= driver->getTransform(video::ETS_VIEW);
        modelViewProj *= driver->getTransform(video::ETS_WORLD);

        services->setVertexShaderConstant("modelViewProj", reinterpret_cast<f32*>(&modelViewProj), 16);

        //Colors
        video::SColorf ambient(0.0f, 0.0f, 1.0f, 0.0f);//RGBA
        services->setPixelShaderConstant("globalAmbient", reinterpret_cast<f32*>(&ambient), 3);

        services->setPixelShaderConstant("mat", reinterpret_cast<f32*>(&mat), 17);

        light.Position = lightNode->getAbsolutePosition();
        services->setPixelShaderConstant("light", reinterpret_cast<f32*>(&light), 6);

        //Camera position
        core::vector3df cameraPos = eyeNode->getAbsolutePosition();
        services->setPixelShaderConstant("eyePosition", reinterpret_cast<f32*>(&cameraPos), 3);

    }



};
Shader file

Code: Select all

//{Structs
///phong material struct
struct Material
{
    float4 Ambient;
    float4 Emissive;
    float4 Diffuse;
    float4 Specular;
    float  Shininess;
};

///light struct
struct Light
{
    float3 Position;
    float3 Color;
};
//}

//{
void computeLight(Light activeLight, float3 P, float3 N, float3 eyePos  , float shininess,
                  out float3 diffuseOutput, out float3 specularOutput)
{
    //calcula a cor difusa
    float3 L = normalize(activeLight.Position - P);
    float diffuseLight = max(dot(N, L), 0);
    diffuseOutput = activeLight.Color * diffuseLight;

    //calcula a cor specular
    float3 V = normalize(eyePos - P);
    float3 H = normalize(L + V);
    float specularLight = pow(max(dot(N, H), 0), shininess);
    if(diffuseLight <= 0)
    {
        specularLight = 0;
    }
    specularOutput = activeLight.Color * specularLight;
}
//}

//Constants cant be define as global, they get some sort of linking error when it happens
float4x4 modelViewProj;
float3 globalAmbient;
float3 eyePosition;
//material and light variables
Material mat;
Light light;

//{Vertex Shader
void mainVX( in float4 position : POSITION,   //posição de entrada
             in float4 normal : NORMAL,       //normal de entrada
             in float2 texCoord : TEXCOORD0,

             out float4 oPosition : POSITION, //posição de saída
             out float2 oTexCoord : TEXCOORD0,
             out float3 objectPos : TEXCOORD1,
             out float4 oNormal : TEXCOORD2 )
{
    ///Multiplicação linear de um vetor 1x4 e uma matriz 4x4, resulta em uma matriz 4x4
    oPosition = mul(position, modelViewProj);
    objectPos = position.xyz;
    oNormal = normal;
    oTexCoord = texCoord;
}
//}
//{Pixel Shader
void mainPX( float2 texCoord : TEXCOORD0,
             float3 position: TEXCOORD1,
             float3 normal: TEXCOORD2,

             uniform sampler2D decal,

             out float4 oColor: COLOR)
{
    float3 emissive = mat.Emissive;
    float3 ambient = mat.Ambient * globalAmbient;

    //--------------
    float3 diffuseLight;
    float3 specularLight;

    float3 diffuseSum = 0;
    float3 specularSum = 0;

    computeLight(light, position.xyz, normal, eyePosition, mat.Shininess, diffuseLight, specularLight);
    diffuseSum += diffuseLight;
    specularSum += specularLight;


    float3 diffuse = diffuseSum * mat.Diffuse;
    float3 specular = specularSum * mat.Specular;

    oColor.rgb = (emissive + ambient + diffuse + specular) * tex2D(decal, texCoord);
    oColor.a = 1;
}
//}
The light position is somehow inverted.... And the same problem happeens when i set the light position as the camera position..
Help please?
Thanks!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Show us also your light configuration code.
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

Oh well "/
Te light structs and setup are set above /\
Here is the lightSceneNode creation and pass to the shader callback:

Code: Select all

scene::ILightSceneNode* light = smgr->addLightSceneNode();
light->setPosition(core::vector3df(10, 10, 0));
scene::ISceneNode* lightBall = smgr->addSphereSceneNode(1, 4, light);
lightBall->setMaterialFlag(video::EMF_LIGHTING, false);
.
.
.
s32 newMat;
MyShaderCallback* cb = new MyShaderCallback(light, camera);//light node to retrieve positions, could be the sphere node as well, and camera to retrieve eye position
And if it helps, i'm using PS and VS 3.0
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

Try to use the position of the light directly from the shader, instead of passing it from irrLicht.

Like this OGL code:

Code: Select all

ecPos = gl_ModelViewMatrix * gl_Vertex;
aux = vec3(gl_LightSource[0].position-ecPos);
lightVector = normalize(aux);
Also, it might be a problem of coordinate system (left/right hand).
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

Thanks TCM.
It seem that the problem is the coordinate system. The X axis seem to be inverted.
I will try to fix that inside irrlicht since i dont want to make the shader specific to irrlicht. I'll make some tests, thanks again man.
BTW the diffuse is cool with the X inversion, but the specular is still with problems, maybe because of the camera X....anyway lets test stuff...

EDIT: i'll try to invert the world matrix.... see if it works...
EDIT2: guess what... didint work... let me check the shader example again..
EDIT3: i inverted the eyes X and lights X inside the shader. Thats an awfull solution... how can i fix this inside irrlicht? Already tried to buil a RH system and didnt worked... any thoughts?

Thanks in advance.
Last edited by Kalango on Wed Dec 15, 2010 11:20 pm, edited 1 time in total.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

Try using RenderMonkey. At least you can make sure that the shader works.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

I say is definitely a coordinate system problem. What might be missing is the camera angle. You invert the coordinates, but angles (rotation) are still backwards. There is the camera position will produce good ambiental and diffuse lighting. But specular light is calculated using the view angle and the normal. So if the coordinate system is backwards, the specular will look bad.



I might be mistaking here.... just an idea from my side.
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

Hmm i see...
Well the stuff above (shader X positions inversion)works untill you start moving the light with an animator...
Oh well i guess i will stop fixing this for now....thanks anyway... i will keep making/learning shaders...
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

But then again DirectX uses left handed coordinate system. The same as irrLicht does. OpenGL is right handed.

Also, check again how do you pass variables to the shader. This is part (passing vectors, textures to a shader) is almost undocumented in irrlicht.

works untill you start moving the light with an animator
And then what does it do ?

Try :

Code: Select all

services->setVertexShaderConstant("mWorldViewProj", &worldViewProj.M[0], 16);
instead of original code :

Code: Select all

services->setVertexShaderConstant("modelViewProj", reinterpret_cast<f32*>(&modelViewProj), 16); 
Post Reply