Home Technical Talk

Maya CgFx - 3dsMax Fx transition issues

polycounter lvl 20
Offline / Send Message
CrazyButcher polycounter lvl 20
while porting Brice's BRDF shader, I made some notes on the differences of each, so when the job needs to be done again, it would mean less work.
///////////////////////////
// GUI / Texture Init


// CgFx Maya:
// -------------

float4 LightPos : Position 
<
	string UIName	= "LightPosition";
	string Object	= "PointLight";
	//string Space	= "World";	// maya allows object/world space
								// (if not specified then object)
> = {-54.0f, 50.0f, 100.0f, 1.0f};

float3 LightColor
<
	string type		= "color";
	string UIName	= "LightColor";
	string UIWidget = "Color";
> = {1.0, 1.0, 1.0};


string UIWidget = "slider";

texture BRDF
<
	string Name = "brdf.tga";	// allows you to load stuff by default
	string UIName = "BRDF";
	string ResourceType = "2D";	
>;

sampler2D diffuseSampler = sampler_state 
{	
	Texture = &lt;diffuseTexture&gt;;
	MinFilter = LinearMipMapLinear;
	MagFilter = Linear;
	LODBias = -.5 ;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
	WrapR = ClampToEdge;
};

// Fx 3dsMax:
// -------------
float4 LightPos : Position 
<
	string UIName = "Light";
    string Object = "OmniLight";
    string Space = "World";		// max always feeds as world
    int RefID = 0;
> = {-54.0f, 50.0f, 100.0f, 1.0f};

float4 LightColor : LightColor &lt;
	int LightRef = 0;
> = float4( 1.0f, 1.0f, 1.0f, 1.0f );    // diffuse

string UIType = "FloatSpinner";

texture DetailTex : MapDetail <
	string UIName = "TextureDetail";
	string type = "CUBE";	// only needed for non 2D maps
	int Texcoord = 1;	// which texcoord gets which mapchannel, also creates spinner for user
	int MapChannel = 1;
>;

sampler2D diffuseSampler = sampler_state 
{	
	Texture = &lt;diffuseTexture&gt;;
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipMapLodBias = -.5 ;
	AddressU = Clamp;
	AddressV = Clamp;
	AddressW = Clamp;
};

///////////////////////////
// Input data

// CgFx Maya:
// -------------
// maya allows the user to script texcoord inputs

struct vIN
{
	float4 Position : POSITION;
	half3 Normal 	: NORMAL;
	half4 Color		: COLOR0;
	half2 TexCoord : TEXCOORD0;
	half3 Tangent  : TEXCOORD1;
	half3 Binormal : TEXCOORD2;
};

// Fx 3dsMax:
// -------------
// 3dsmax always computes tangent/binormal for channel 1

// Textures Enforce channel 1
int texcoord0 : Texcoord
<;
	int Texcoord = 0;
	int MapChannel = 1;
>;

// 3dsmax can only pass vertexcolor (without alpha) as texcoord
// Vertexcolor
int texcoord1 : Texcoord
<
	int Texcoord = 1;
	int MapChannel = 0; // -2 is valpha, -1 is illum
>;

// max feeds tangents via semantix (always for map channel 1)
struct vIN
{
	float4 Position : POSITION;
	half3 Normal 	: NORMAL;
	half2 TexCoord : TEXCOORD0;
	half4 Color		: TEXCOORD1;
	half3 Tangent  : TANGENT;
	half3 Binormal : BINORMAL;
};


///////////////////////////
// Shader Stuff

// CgFx Maya:
// -------------
// matrices stored column major

mul(wvpMatrix,  IN.Position)
half3 EyePos = wvMatrixIT[3].xyz 

// lightpos in objectspace
half3 LightDir = normalize(LightPos.xyz - IN.Position.xyz);
half3 wLightDir = mul(wMatrix, half4(LightDir.xyz, 0.0)).xyz;

// Fx 3dsMax:
// -------------
// all matrices are transposed form of Cg
// so reverse stuff (just putting "Transpose" at end of semantics, didnt work)

mul(float4(inpos, 1),(float4x4)World)
half3 EyePos = wvMatrixI[3].xyz;	// none transposed

// Lightpos in world space
half3 wPos = mul(IN.Position,wMatrix).xyz;
half3 wLightDir = normalize(LightPos.xyz - wPos);

// cubemaps need different lookup, 3dsmax is Z up
float3 texcoordCubeSwizzle(float3 ref){
	return float3(ref.x,ref.z,ref.y);
}

// (if x*Tangent, y*Binormal,z*Normal is used) normal maps need swizzle
float3 normalSwizzle(float3 ref){
	return float3(ref.y,ref.x,ref.z);
}

///////////////////////////
// Technique

// CgFx Maya:
// -------------
CullFaceEnable=false;
DepthTestEnable=true;
DepthMask = true;
DepthFunc = LEqual;

VertexProgram   = compile arbvp1 MainVS2();
FragmentProgram = compile fp40 Gloss2PS();

// Fx 3dsMax:
// -------------

AlphaBlendEnable = FALSE;
CullMode = CW;
ZWriteEnable = TRUE;
ZFunc = LESSEQUAL;
ZEnable = TRUE;

VertexShader   = compile vs_1_1 MainVS2();
PixelShader = compile ps_3_0 Gloss2PS();


///////////////////////////
// Compile Profiles
//
// In theory Cg can compile to GLSL, which then is compiled by driver
// however GLSL output is still buggy, and there are no "standards"
// on whether a program runs or not, it completely depends on the hardware
//
// Directx            OpenGL/Cg
//
// Vertex
//
//  for regular stuff, still fairly common, most work is done in pixelshaders
//  in todays games
//   vs_1_1           arbvp1
//
//  more complex (allows static flow control, ie uniform parameter 
//  "if switches" or for loops)
//  static means all vertices run thru the same thing
//  2_x also brought dynamic flow control, ie per-vertex/pixel 
//  different code paths) 
//
//   vs_2_0      
//   vs_2_x            vp30 (only nvidia)
//
//  recent stuff texture lookups in vertexshader
//   vs_3_0            vp40 (only nvidia)
//                     glslv (all, buggy)
// Pixel
//
//  old &lt;= GeForce4 stuff, still sufficient for simple normalmaps and 
//  texture combining
//
//   ps_1_0            fp20 (only nvidia)
//   ps_1_1
//   ps_1_2
//   ps_1_3
//   ps_1_4
//
//  what most hardware has today (Radeon 9600, GeforceFX and up)
//   ps_2_0            arbfp1
//   ps_2_a
//   ps_2_b
//  
//  fastly becoming popular (Radeon X1300, GeForce 6xxx)
//   ps_3_0            fp40 (only nvidia)
//                     glslf (might work not sure, buggy)

maybe it helps if someone else wants to provide shaders for both apps.

edit1: added normalmap swizzle for max (if x*Tangent, y*Binormal,z*Normal is used)

edit2: bug in max vertexcolor statement (channel 0 is vcolor)
Sign In or Register to comment.