The experiment is done with the same shader run in RenderMonkey and in an Irrlicht application.
While from some directions the normal map appears correctly, in other places it looks like "reversed"
These are the important parts of the used code:
code to initialize the model:
Code: Select all
scene::IAnimatedMesh* UniMesh = smgr->getMesh("universe.b3d");
UniMesh->setHardwareMappingHint(scene::EHM_STATIC);
scene::IMeshManipulator* mm = smgr->getMeshManipulator();
scene::IMeshSceneNode* UniNode =smgr->addMeshSceneNode(
mm->createMeshWithTangents(UniMesh),
smgr->getRootSceneNode(),10);
Code: Select all
struct VS_INPUT {
float4 position : POSITION0;
float2 texCoord : TEXCOORD0;
float3 normal : NORMAL0;
float3 binormal : BINORMAL0;
float3 tangent : TANGENT0;
};
struct VS_OUTPUT {
float4 position :POSITION0;
float2 texCoord :TEXCOORD0;
float3 normal :TEXCOORD1;
float3 binormal :TEXCOORD2;
float3 tangent :TEXCOORD3;
float3 viewDir1 :TEXCOORD4;
float3 lightDir1 :TEXCOORD5;
float3 lightDir2 :TEXCOORD6;
};
VS_OUTPUT vs_main(VS_INPUT IN){
VS_OUTPUT OUT;
OUT.texCoord = IN.texCoord;
OUT.position = mul(IN.position,worldViewProjection);
OUT.normal = mul(worldInverse,IN.normal);
OUT.normal = normalize(OUT.normal);
//OUT.tangent = float3(abs(OUT.normal.z+OUT.normal.y), 0 , OUT.normal.x);
OUT.tangent = mul(worldInverse,IN.tangent);
OUT.tangent = normalize(OUT.tangent);
//OUT.binormal = cross(OUT.normal,OUT.tangent);
OUT.binormal = mul(worldInverse,IN.binormal);
OUT.binormal = normalize(OUT.binormal);
float4 realPos = mul(IN.position,world);
float4 lightPos;
OUT.viewDir1 = viewPosition -realPos;
OUT.viewDir1 = normalize(OUT.viewDir1);
if(enableLight1>0.6){
lightPos = lightPosition1;
OUT.lightDir1 = lightPos-realPos;
OUT.lightDir1 = normalize(OUT.lightDir1);
}else{
OUT.lightDir1 = float4(0.0,0.0,0.0,1.0);
}
if(enableLight2>0.6){
lightPos = lightPosition2;
OUT.lightDir2 = lightPos-realPos;
OUT.lightDir2 = normalize(OUT.lightDir2);
}else{
OUT.lightDir2 = float4(0.0,0.0,0.0,1.0);
}
return OUT;
}
Code: Select all
void phongMaterial::OnSetConstants(video::IMaterialRendererServices* srv, irr::s32 userData){
register int i,j;
core::stringc varName;
video::IVideoDriver* drv = srv->getVideoDriver();
scene::ISceneManager* smgr = (scene::ISceneManager*) userData;
core::matrix4 worldViewProjection;
worldViewProjection = drv->getTransform(video::ETS_WORLD);
srv->setVertexShaderConstant("world",worldViewProjection.pointer(),16);
worldViewProjection.makeInverse();
srv->setVertexShaderConstant("worldInverse",worldViewProjection.pointer(),16);
worldViewProjection = drv->getTransform(video::ETS_PROJECTION);
worldViewProjection *= drv->getTransform(video::ETS_VIEW);
worldViewProjection *= drv->getTransform(video::ETS_WORLD);
srv->setVertexShaderConstant("worldViewProjection",worldViewProjection.pointer(),16);
core::vector3df CameraPosition = smgr->getActiveCamera()->getPosition();
srv->setVertexShaderConstant("viewPosition",&CameraPosition.X,4);
for(i=0; (i < drv->getDynamicLightCount()) && (i < 2); i++){
float enableOn = 1.0;
core::vector3df lightPosOn;
core::vector3df lightColorOn;
varName = "enableLight";
varName += core::stringc(i+1);
srv->setVertexShaderConstant(varName.c_str(),&enableOn,1);
srv->setPixelShaderConstant(varName.c_str(),&enableOn,1);
lightPosOn = drv->getDynamicLight(i).Position;
lightColorOn.X = drv->getDynamicLight(i).DiffuseColor.r;
lightColorOn.Y = drv->getDynamicLight(i).DiffuseColor.g;
lightColorOn.Z = drv->getDynamicLight(i).DiffuseColor.b;
//lightColorOn /= 255.0;
varName = "lightPosition";
varName += core::stringc(i+1);
srv->setVertexShaderConstant(varName.c_str(),&lightPosOn.X,4);
varName = "lightColor";
varName += core::stringc(i+1);
srv->setPixelShaderConstant(varName.c_str(),&lightColorOn.X,4);
}
for(j=i;j<2;j++){
float enableOff = 0.5;
core::vector3df lightPos = core::vector3df(0,0,0);
core::vector3df lightColor = core::vector3df(0,0,0);
varName = "enableLight";
varName += core::stringc(j+1);
srv->setVertexShaderConstant(varName.c_str(),&enableOff,1);
srv->setPixelShaderConstant(varName.c_str(),&enableOff,1);
varName = "lightPosition";
varName += core::stringc(j+1);
srv->setVertexShaderConstant(varName.c_str(),&lightPos.X,4);
varName = "lightColor";
varName += core::stringc(j+1);
srv->setPixelShaderConstant(varName.c_str(),&lightColor.X,4);
}
float inSpecularIntensity = 1;
srv->setPixelShaderConstant("specularIntensity",&inSpecularIntensity,1);
srv->setPixelShaderConstant("ambientColor",&ambientColor.r,4);
srv->setPixelShaderConstant("lighting",&lighting,1);
srv->setPixelShaderConstant("r_sh",RadianceMatrices->RedMatrix.pointer(),16);
srv->setPixelShaderConstant("g_sh",RadianceMatrices->GreenMatrix.pointer(),16);
srv->setPixelShaderConstant("b_sh",RadianceMatrices->BlueMatrix.pointer(),16);
}
http://i51.tinypic.com/2hzpyxc.jpg
Also, seems that the trick to generate the tangent space on the shaders isn't very useful, after all, it creates a tangent space indeed, but it is not correctly oriented, and thus this happens. And on the other hand, when trying to use the semantics, they don't work as expected.
So, are actually tangents and binormals pased to shaders?