Page 1 of 1

Are tangents correctly passed to the HLSL shaders?

Posted: Sun Oct 10, 2010 2:42 pm
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?

Re: Are tangents correctly passed to the HLSL shaders?

Posted: Wed Nov 19, 2014 10:08 pm
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.

Re: Are tangents correctly passed to the HLSL shaders?

Posted: Sat Nov 22, 2014 9:47 am
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.