Are tangents correctly passed to the HLSL shaders?

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Are tangents correctly passed to the HLSL shaders?

Post by Mel »

After making some experiments, i've come to a conclusion. Irrlicht still doesn't pass the tangents and the binormals to the shaders, even in a model with the tangents generated. Or else, they aren't placed in the expected semantics.

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 to initialize the tangent space on the shaders. Pretty straight.

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;
}
Shader Callback:

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);

}
These are the results

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?
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
The_Glitch
Competition winner
Posts: 523
Joined: Tue Jan 15, 2013 6:36 pm

Re: Are tangents correctly passed to the HLSL shaders?

Post by The_Glitch »

I know this is old my apologies but something that's always bothered me. Why is it things we create in RenderMonkey don't look as good when you put it in Irrlicht. Mainly Normal mapped objects also.

In Irrlicht they seem weak looking but in RendeMonkey the results look great even when I design the shader in RenderMonkey and load that same exact shader in Irrlicht it still doesn't look as well.
The_Glitch
Competition winner
Posts: 523
Joined: Tue Jan 15, 2013 6:36 pm

Re: Are tangents correctly passed to the HLSL shaders?

Post by The_Glitch »

Just want to do a follow I believe my issue was getting the dynamic light in the shader call back I made a few changes and normal maps on animated meshes seem to regain the composure and I clean up my shader quite a bit. So Irrlicht has seemed to fix this old issue.
Post Reply