Page 5 of 6

Posted: Sat Nov 20, 2010 9:11 am
by xirtamatrix
hi there,

Great work! Unfortunately I'm using DX but I'm terribly in need of this. Any chance you (or someone else) could write a DX (hlsl) version of this?

Many thanks in advance!

Posted: Sat Nov 20, 2010 1:40 pm
by wing64
Try this. :D

vertex program

Code: Select all

float4x4 matWorldInverse; 
float4x4 ModelViewMatrix;
float4x4 ModelViewProjectionMatrix;

float3 fvLightPosition1; 
float3 fvLightPosition2; 
float3 fvLightPosition3; 
float3 fvLightPosition4; 
 
float fLightStrength1; 
float fLightStrength2; 
float fLightStrength3; 
float fLightStrength4; 
 
struct VS_OUTPUT
{
	float4 Position				: POSITION0;
	float2 Texcoord				: TEXCOORD0;
	float3 ViewDirection		: TEXCOORD1; 
	float3 LightDirection1		: TEXCOORD2; 
	float3 LightDirection2		: TEXCOORD3; 
	float3 LightDirection3		: TEXCOORD4; 
	float3 LightDirection4		: TEXCOORD5; 
	float4 LightDistMultiplier  : TEXCOORD6;
};
    
float getLengthSQR (float3 vec) 
{ 
	return(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z); 
}  

struct VS_INPUT
{
	float3 Position         : POSITION0;
	float3 Normal           : NORMAL;
	float2 Texcoord         : TEXCOORD0;
};

VS_OUTPUT vertexMain( in VS_INPUT IN ) 
{    
	VS_OUTPUT OUT = (VS_OUTPUT)0;

	// common output
	OUT.Position = mul(float4(IN.Position,1.0), ModelViewProjectionMatrix);
	OUT.Texcoord = IN.Texcoord;

	float4x4 LightTransform= ModelViewMatrix; 
	LightTransform= mul(matWorldInverse, LightTransform);

	float4 fvObjectPosition = mul(float4(IN.Position,1.0), ModelViewProjectionMatrix);
	float4 fvLightPos1 = mul(float4(fvLightPosition1,1.0), LightTransform); 
	float4 fvLightPos2 = mul(float4(fvLightPosition2,1.0), LightTransform); 
	float4 fvLightPos3 = mul(float4(fvLightPosition3,1.0), LightTransform); 
	float4 fvLightPos4 = mul(float4(fvLightPosition4,1.0), LightTransform); 

	float3 fvViewDirection  =  - fvObjectPosition.xyz; 

	float3 fvLightDirection1 = (fvLightPos1.xyz - fvObjectPosition.xyz); 
	float3 fvLightDirection2 = (fvLightPos2.xyz - fvObjectPosition.xyz); 
	float3 fvLightDirection3 = (fvLightPos3.xyz - fvObjectPosition.xyz); 
	float3 fvLightDirection4 = (fvLightPos4.xyz - fvObjectPosition.xyz); 

	OUT.LightDistMultiplier[0]=1.0/(getLengthSQR (fvLightDirection1)/(fLightStrength1*10000.0)); 
	OUT.LightDistMultiplier[1]=1.0/(getLengthSQR (fvLightDirection2)/(fLightStrength2*10000.0)); 
	OUT.LightDistMultiplier[2]=1.0/(getLengthSQR (fvLightDirection3)/(fLightStrength3*10000.0)); 
	OUT.LightDistMultiplier[3]=1.0/(getLengthSQR (fvLightDirection4)/(fLightStrength4*10000.0)); 

	float3 fvTangent	= -float3(abs(IN.Normal.y) + abs(IN.Normal.z), abs(IN.Normal.x), 0); 
	float3 fvBinormal	= cross(fvTangent,IN.Normal);
	float3 fvNormal     = mul(IN.Normal, ModelViewMatrix); 

	fvTangent			= mul( cross(fvBinormal, IN.Normal), ModelViewMatrix ); 
	fvBinormal			= mul( fvBinormal, ModelViewMatrix ); 

	OUT.ViewDirection.x  = dot( fvTangent, fvViewDirection ); 
	OUT.ViewDirection.y  = dot( fvBinormal, fvViewDirection ); 
	OUT.ViewDirection.z  = dot( fvNormal, fvViewDirection ); 

	OUT.LightDirection1.x  = dot( fvTangent, fvLightDirection1.xyz ); 
	OUT.LightDirection1.y  = dot( fvBinormal, fvLightDirection1.xyz ); 
	OUT.LightDirection1.z  = dot( fvNormal, fvLightDirection1.xyz ); 

	OUT.LightDirection2.x  = dot( fvTangent, fvLightDirection2.xyz ); 
	OUT.LightDirection2.y  = dot( fvBinormal, fvLightDirection2.xyz ); 
	OUT.LightDirection2.z  = dot( fvNormal, fvLightDirection2.xyz ); 

	OUT.LightDirection3.x  = dot( fvTangent, fvLightDirection3.xyz ); 
	OUT.LightDirection3.y  = dot( fvBinormal, fvLightDirection3.xyz ); 
	OUT.LightDirection3.z  = dot( fvNormal, fvLightDirection3.xyz ); 

	OUT.LightDirection4.x  = dot( fvTangent, fvLightDirection4.xyz ); 
	OUT.LightDirection4.y  = dot( fvBinormal, fvLightDirection4.xyz ); 
	OUT.LightDirection4.z  = dot( fvNormal, fvLightDirection4.xyz ); 

	return OUT;
}
pixel program

Code: Select all

float4 fvAmbient;
float4 fvLight1Color; 
float4 fvLight2Color; 
float4 fvLight3Color; 
float4 fvLight4Color; 

float fSpecularPower; 
float fSpecularStrength; 
float fBumpStrength; 

sampler2D baseMap		: register(s0); 
sampler2D bumpMap		: register(s1); 

struct PS_INPUT
{	
	float2 Texcoord				: TEXCOORD0;
	float3 ViewDirection		: TEXCOORD1; 
	float3 LightDirection1		: TEXCOORD2; 
	float3 LightDirection2		: TEXCOORD3;
	float3 LightDirection3		: TEXCOORD4; 
	float3 LightDirection4		: TEXCOORD5; 
	float4 LightDistMultiplier  : TEXCOORD6;

};

float4 pixelMain( in PS_INPUT IN ) : COLOR
{
	float4 color = float4(0,0,0,0);

	float3  fvLightDirection1 = normalize( IN.LightDirection1 ); 
	float3  fvLightDirection2 = normalize( IN.LightDirection2 ); 
	float3  fvLightDirection3 = normalize( IN.LightDirection3 ); 
	float3  fvLightDirection4 = normalize( IN.LightDirection4 ); 

	float3  fvNormal         = tex2D( bumpMap, IN.Texcoord ).yxz; 
	fvNormal.xy*=2.0; 
	fvNormal.xy-=1.0; 

	fvNormal=(float3(0.0,0.0,1.0)-fvNormal)*fBumpStrength+fvNormal; 

	fvNormal=normalize(fvNormal); 

	float fNDotL1           = max(dot(fvNormal, fvLightDirection1),0.0)-0.1;  
	float fNDotL2           = max(dot(fvNormal, fvLightDirection2),0.0)-0.1;  
	float fNDotL3           = max(dot(fvNormal, fvLightDirection3),0.0)-0.1;  
	float fNDotL4           = max(dot(fvNormal, fvLightDirection4),0.0)-0.1;  

	float3  fvReflection1     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection1 );  
	float3  fvReflection2     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection2 );  
	float3  fvReflection3     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection3 );  
	float3  fvReflection4     = normalize( ( ( 2.0 * fvNormal )  ) - fvLightDirection4 );  

	float3  fvViewDirection  = normalize( IN.ViewDirection ); 

	float fRDotV1          = max( 0.0, dot( fvReflection1, fvViewDirection ) ); 
	float fRDotV2          = max( 0.0, dot( fvReflection2, fvViewDirection ) ); 
	float fRDotV3          = max( 0.0, dot( fvReflection3, fvViewDirection ) ); 
	float fRDotV4          = max( 0.0, dot( fvReflection4, fvViewDirection ) ); 

	float4  fvBaseColor      = tex2D( baseMap, IN.Texcoord ); 

	float4  fvTotalAmbient   = fvAmbient * fvBaseColor;  

	float4  fvTotalDiffuse   = fvLight1Color * fNDotL1* fvBaseColor*IN.LightDistMultiplier[0];  
	float4  fvTotalSpecular  = fNDotL1*fvLight1Color * ( pow( fRDotV1, fSpecularPower ) )*IN.LightDistMultiplier[0]; 

	fvTotalDiffuse   += fvLight2Color * fNDotL2* fvBaseColor*IN.LightDistMultiplier[1];  
	fvTotalSpecular  += fNDotL2*fvLight2Color * ( pow( fRDotV2, fSpecularPower ) )*IN.LightDistMultiplier[1];   

	fvTotalDiffuse   += fvLight3Color * fNDotL3* fvBaseColor*IN.LightDistMultiplier[2];  
	fvTotalSpecular  += fNDotL3*fvLight3Color * ( pow( fRDotV3, fSpecularPower ) )*IN.LightDistMultiplier[2];   

	fvTotalDiffuse   += fvLight4Color * fNDotL4* fvBaseColor*IN.LightDistMultiplier[3];  
	fvTotalSpecular  += fNDotL4*fvLight4Color * ( pow( fRDotV4, fSpecularPower ) )*IN.LightDistMultiplier[3];   

	color=( fvTotalAmbient + fvTotalDiffuse+ (fvTotalSpecular*fSpecularStrength)); 
	if(color.r>1.0){color.gb+=color.r-1.0;} 
	if(color.g>1.0){color.rb+=color.g-1.0;} 
	if(color.b>1.0){color.rg+=color.b-1.0;} 

	return color;
} 

Posted: Sun Jan 16, 2011 2:47 am
by kaliber
hello, please help me with the directx version callback

here is my code :

Code: Select all

virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  {
	//int var0=0;
 //   services->setPixelShaderConstant("baseMap", (float*)(&var0), 1); //the colormap
 //   int var1=1;
 //   services->setPixelShaderConstant("bumpMap", (float*)(&var1), 1); //the normalmap
   
    core::matrix4 invWorld = services->getVideoDriver()->getTransform(video::ETS_WORLD);
    invWorld.makeInverse();
    services->setVertexShaderConstant("matWorldInverse", (float*)(&invWorld), 16);

	core::matrix4 ModelViewMatrix = services->getVideoDriver()->getTransform(video::ETS_VIEW);
    ModelViewMatrix.makeInverse();
    services->setVertexShaderConstant("ModelViewMatrix", (float*)(&ModelViewMatrix), 16);

	core::matrix4 worldViewProj;
	worldViewProj = services->getVideoDriver()->getTransform(video::ETS_PROJECTION);
	worldViewProj *= services->getVideoDriver()->getTransform(video::ETS_VIEW);
	worldViewProj *= services->getVideoDriver()->getTransform(video::ETS_WORLD);
	
    services->setVertexShaderConstant("ModelViewProjectionMatrix", (float*)(&worldViewProj), 16);
   
    services->setVertexShaderConstant("fLightStrength1", (float*)(&fLightStrength[0]), 1);
    services->setVertexShaderConstant("fLightStrength2", (float*)(&fLightStrength[1]), 1);
    services->setVertexShaderConstant("fLightStrength3", (float*)(&fLightStrength[2]), 1);
    services->setVertexShaderConstant("fLightStrength4", (float*)(&fLightStrength[3]), 1);
   
    services->setVertexShaderConstant("fvLightPosition1", (float*)(&fvLightPosition[0]), 3);
    services->setVertexShaderConstant("fvLightPosition2", (float*)(&fvLightPosition[1]), 3);
    services->setVertexShaderConstant("fvLightPosition3", (float*)(&fvLightPosition[2]), 3);
    services->setVertexShaderConstant("fvLightPosition4", (float*)(&fvLightPosition[3]), 3);
   
    services->setPixelShaderConstant("fvAmbient", (float*)(&fvAmbient), 4);
    services->setPixelShaderConstant("fvLight1Color", (float*)(&fvLightColor[0]), 4);
    services->setPixelShaderConstant("fvLight2Color", (float*)(&fvLightColor[1]), 4);
    services->setPixelShaderConstant("fvLight3Color", (float*)(&fvLightColor[2]), 4);
    services->setPixelShaderConstant("fvLight4Color", (float*)(&fvLightColor[3]), 4);

    services->setPixelShaderConstant("fSpecularPower", (float*)(&fSpecularPower), 1);
    services->setPixelShaderConstant("fSpecularStrength", (float*)(&fSpecularStrength), 1);
    services->setPixelShaderConstant("fBumpStrength", (float*)(&fBumpStrength), 1);
		
   }

}; 
i dont know how to set the "ModelViewMatrix" and the "ModelViewProjectionMatrix" variable.

Posted: Sun Jan 16, 2011 3:59 am
by wing64

Code: Select all

		matrix4 ModelViewProjectionMatrix;
		ModelViewProjectionMatrix = driver->getTransform(ETS_PROJECTION);
		ModelViewProjectionMatrix *= driver->getTransform(ETS_VIEW);
		ModelViewProjectionMatrix *= driver->getTransform(ETS_WORLD);
		services->setVertexShaderConstant("ModelViewProjectionMatrix", ModelViewProjectionMatrix.pointer(), 16);

		matrix4 ModelViewMatrix;
		ModelViewMatrix = driver->getTransform(ETS_VIEW);
		ModelViewMatrix *= driver->getTransform(ETS_WORLD);
		services->setVertexShaderConstant("ModelViewMatrix", ModelViewMatrix.pointer(), 16);

Posted: Sun Jan 16, 2011 4:36 am
by kaliber
yay yay thx a lot :D :lol:

Posted: Wed Jan 19, 2011 11:10 am
by Mel
The shader in the first page should be marked as "deprecated"

The tangents and binormals are currently passed to the shaders, even in the animated meshes, and they are correctly calculated inside the engine.

They are passed in TEXCOORD1 (the tangent) and TEXCOORD2 (the binormal), instead of the expected semantics TANGENT0 and BINORMAL0, and they are also passed to animated meshes (though their processing isn't correct ATM, the tangents and binormals should be animated too, and they aren't)

IN HLSL, in the vertex definition the tangents and binormals are there:

Code: Select all

...
float3 tangent   :TEXCOORD1;
float3 binormal :TEXCOORD2;
...
So, this 4 lights shader would look like this in the vertex shader:

Code: Select all

float4x4 matWorldInverse;
float4x4 ModelViewMatrix;
float4x4 ModelViewProjectionMatrix;

float3 fvLightPosition1;
float3 fvLightPosition2;
float3 fvLightPosition3;
float3 fvLightPosition4;
 
float fLightStrength1;
float fLightStrength2;
float fLightStrength3;
float fLightStrength4;
 
struct VS_OUTPUT
{
   float4 Position            : POSITION0;
   float2 Texcoord            : TEXCOORD0;
   float3 ViewDirection      : TEXCOORD1;
   float3 LightDirection1      : TEXCOORD2;
   float3 LightDirection2      : TEXCOORD3;
   float3 LightDirection3      : TEXCOORD4;
   float3 LightDirection4      : TEXCOORD5;
   float4 LightDistMultiplier  : TEXCOORD6;
};
   
float getLengthSQR (float3 vec)
{
   return(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);
} 

struct VS_INPUT
{
   float3 Position         : POSITION0;
   float3 Normal           : NORMAL;
   float2 Texcoord         : TEXCOORD0;
   float3 Tangent          :TEXCOORD1;
   float3 Binormal         :TEXCOORD2;
};

VS_OUTPUT vertexMain( in VS_INPUT IN )
{   
   VS_OUTPUT OUT = (VS_OUTPUT)0;

   // common output
   OUT.Position = mul(float4(IN.Position,1.0), ModelViewProjectionMatrix);
   OUT.Texcoord = IN.Texcoord;

   float4x4 LightTransform= ModelViewMatrix;
   LightTransform= mul(matWorldInverse, LightTransform);

   float4 fvObjectPosition = mul(float4(IN.Position,1.0), ModelViewProjectionMatrix);
   float4 fvLightPos1 = mul(float4(fvLightPosition1,1.0), LightTransform);
   float4 fvLightPos2 = mul(float4(fvLightPosition2,1.0), LightTransform);
   float4 fvLightPos3 = mul(float4(fvLightPosition3,1.0), LightTransform);
   float4 fvLightPos4 = mul(float4(fvLightPosition4,1.0), LightTransform);

   float3 fvViewDirection  =  - fvObjectPosition.xyz;

   float3 fvLightDirection1 = (fvLightPos1.xyz - fvObjectPosition.xyz);
   float3 fvLightDirection2 = (fvLightPos2.xyz - fvObjectPosition.xyz);
   float3 fvLightDirection3 = (fvLightPos3.xyz - fvObjectPosition.xyz);
   float3 fvLightDirection4 = (fvLightPos4.xyz - fvObjectPosition.xyz);

   OUT.LightDistMultiplier[0]=1.0/(getLengthSQR (fvLightDirection1)/(fLightStrength1*10000.0));
   OUT.LightDistMultiplier[1]=1.0/(getLengthSQR (fvLightDirection2)/(fLightStrength2*10000.0));
   OUT.LightDistMultiplier[2]=1.0/(getLengthSQR (fvLightDirection3)/(fLightStrength3*10000.0));
   OUT.LightDistMultiplier[3]=1.0/(getLengthSQR (fvLightDirection4)/(fLightStrength4*10000.0));

   float3 fvTangent   = mul(IN.tangent,ModelViewMatrix);
   float3 fvBinormal   = mul(IN.binormal,ModelViewMatrix);
   float3 fvNormal     = mul(IN.Normal, ModelViewMatrix);

   OUT.ViewDirection.x  = dot( fvTangent, fvViewDirection );
   OUT.ViewDirection.y  = dot( fvBinormal, fvViewDirection );
   OUT.ViewDirection.z  = dot( fvNormal, fvViewDirection );

   OUT.LightDirection1.x  = dot( fvTangent, fvLightDirection1.xyz );
   OUT.LightDirection1.y  = dot( fvBinormal, fvLightDirection1.xyz );
   OUT.LightDirection1.z  = dot( fvNormal, fvLightDirection1.xyz );

   OUT.LightDirection2.x  = dot( fvTangent, fvLightDirection2.xyz );
   OUT.LightDirection2.y  = dot( fvBinormal, fvLightDirection2.xyz );
   OUT.LightDirection2.z  = dot( fvNormal, fvLightDirection2.xyz );

   OUT.LightDirection3.x  = dot( fvTangent, fvLightDirection3.xyz );
   OUT.LightDirection3.y  = dot( fvBinormal, fvLightDirection3.xyz );
   OUT.LightDirection3.z  = dot( fvNormal, fvLightDirection3.xyz );

   OUT.LightDirection4.x  = dot( fvTangent, fvLightDirection4.xyz );
   OUT.LightDirection4.y  = dot( fvBinormal, fvLightDirection4.xyz );
   OUT.LightDirection4.z  = dot( fvNormal, fvLightDirection4.xyz );

   return OUT;
}
And the pixel shader remains the same.

Posted: Wed Jan 19, 2011 12:39 pm
by bitplane
Cool stuff. Does it look much different from the current shader when two lights are used? If not, we should probably use this in the engine by default if the user supports HLSL/GLSL.

Posted: Wed Jan 19, 2011 1:00 pm
by shadowslair
Since you have:

Code: Select all

struct VS_INPUT
{
   (...)
   float3 Tangent          :TEXCOORD1;
   float3 Binormal         :TEXCOORD2;
};

Code: Select all

float3 fvTangent   = mul(IN.tangent,ModelViewMatrix);
float3 fvBinormal   = mul(IN.binormal,ModelViewMatrix); 
should be:

Code: Select all

float3 fvTangent   = mul(IN.Tangent,ModelViewMatrix);
float3 fvBinormal   = mul(IN.Binormal,ModelViewMatrix); 

Posted: Thu Jan 20, 2011 12:11 am
by Mel
You know what i mean, right? ;)

Posted: Thu Jan 20, 2011 12:54 am
by shadowslair
Sure. Just wanted to tell you to fix it if you wish, `cause some peeps are used to copy/paste without reading a thing, then they`d post here the errors they get etc. :D

Posted: Thu Jan 20, 2011 1:10 am
by Mel
Then some people should be ready also to correct minor errors due to fast coding :lol: But yeah, you are right.

Posted: Thu Jan 20, 2011 8:29 am
by Luben
Why do people still say binormal? It really ought to be bitangent, right?

Posted: Fri Jan 21, 2011 12:37 am
by Mel
Either name is correct :) at any case, it is a complementary vector to the tangent and the normal vectors to create the tangent space, so, it really doesn't matter how you name it. In spanish, for instance, the name is binormal, not bitangent.

Posted: Fri Jan 21, 2011 12:51 pm
by Luben
Is it really correct? Consider a plane; It consists of one normal and two tangents. Two normals for a plane just doesn't make any sense.
If we were to consider a line instead, there's one tangent and two normals. The name binormal makes sense then, but a bitangent would make no sense at all.
(I suppose there might be more normals for a surface in higher dimensions, don't know anything about that)

Posted: Fri Jan 21, 2011 5:56 pm
by Mel
According to wikipedia, this is a "bitangent"

http://en.wikipedia.org/wiki/Bitangent

But then, you find things like this:

http://mathworld.wolfram.com/BitangentVector.html

So i am really confused now... :lol: