FX Composer

I had initially discounted FX Composer as being useful for editing shaders to use with Panda because it didn’t seem to support Cg, but tonight I just noticed this feature list:

developer.nvidia.com/object/fx_c … l#features

The very first item in the feature list refers to “COLLADA FX Cg”. Is that the shading language Panda uses, or is Collada FX something different?

ADDITION: Incidentally, I already found this thread when I searched the forum:
discourse.panda3d.org/viewtopic … t=composer

He’s pointing out the exact thing I’m asking about. Unfortunately that thread doesn’t really answer my question, as nobody posted to confirm that it works, just a couple people posted that they will be checking it out.

I believe it can export CgFX. But looking at this page:
http.developer.nvidia.com/CgTuto … dix_c.html

I don’t think Panda currently supports CgFX. It would be cool if someone would add support for it, though. I’d also add support for ColladaCgFX in my collada converter then.

colladaFX and cgFX are both really useful language that does about the same thing.
they are not shading language by themself.
They both include one (or more) shaders in a shading language. (can be glsl, hlsl, cg for collada FX, must be in cg for cgFX), the texture that goes with it and the shader inputs.

so, since the shader will be in cg, Panda3d can not use it.
It will be very cool that Panda3d could import Colladafx/cgfx
A way to understand pure cg will be very cool as it will simplify by a huge amount the work needed to get cgfx/colladafx work

As you may have guest, I’m trying to import some simplified ( one pass only) colladafx/cgfx to panda.

I can get all the shaderinput without problem and since I’m only use 1 pass, the only problem is finding a way to convert cg into .sha

Any idea ?

I think you did not realize that Panda actually uses Cg.

The extension of the shader file doesn’t matter. I have my shaders in the .cg extension, some people have them in .vp and .fp files.
It’s really the same Cg language.

Well, I know that Panda3D use cg. But I was thinking it used a ‘home version’ of cg, since the variable name are restricted, or since the declaration of in/out struture are not the same. or the fact that a .sha file take both vertexshader and fragmentshader ?

If you are saying that I can take a ‘normal’ cg file (like this) and use it directly in panda3d, then your my savior !

float Script : STANDARDSGLOBAL <
    string UIWidget = none ;
    string ScriptClass = object;
    string ScriptOrder = standard;
    string ScriptOutput = color;
    string Script = 0.8;

float4x4 WorldITXf : WorldInverseTranspose ;
float4x4 WvpXf : WorldViewProjection ;
float4x4 WorldXf : World ;
float4x4 ViewIXf : ViewInverse ;
[...other parameter here ...]

sampler2D ColorSampler ;

struct appdata {
    float3 Position	: POSITION;
    float4 UV		: TEXCOORD0;
    float4 Normal	: NORMAL;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;
};

struct vertexOutput {
    float4 HPosition	: POSITION;
    float2 UV		: TEXCOORD0;
    float3 LightVec	: TEXCOORD1;
    float3 WorldNormal	: TEXCOORD2;
    float3 WorldTangent	: TEXCOORD3;
    float3 WorldBinormal : TEXCOORD4;
    float3 WorldView	: TEXCOORD5;

};

vertexOutput std_VS(appdata IN) {
    vertexOutput OUT = (vertexOutput)0;
    OUT.WorldNormal = mul(WorldITXf,IN.Normal).xyz;
    OUT.WorldTangent = mul(WorldITXf,IN.Tangent).xyz;
    OUT.WorldBinormal = mul(WorldITXf,IN.Binormal).xyz;
    float4 Po = float4(IN.Position.xyz,1);
    float3 Pw = mul(WorldXf,Po).xyz;
    OUT.LightVec = (Lamp0Pos - Pw);
    OUT.UV = IN.UV.xy;
    OUT.WorldView = normalize(float3(ViewIXf[0].w,ViewIXf[1].w,ViewIXf[2].w) - Pw);
    OUT.HPosition = mul(WvpXf,Po);
    return OUT;
}

void phong_shading(vertexOutput IN,
		    float3 LightColor,
		    float3 Nn,
		    float3 Ln,
		    float3 Vn,
		    out float3 DiffuseContrib,
		    out float3 SpecularContrib)
{
    float3 Hn = normalize(Vn + Ln);
    float4 litV = lit(dot(Ln,Nn),dot(Hn,Nn),SpecExpon);
    DiffuseContrib = litV.y * LightColor;
    SpecularContrib = litV.y * litV.z * Ks * LightColor;
}
float4 std_PS(vertexOutput IN) : COLOR {
    float3 diffContrib;
    float3 specContrib;
    float3 Ln = normalize(IN.LightVec);
    float3 Vn = normalize(IN.WorldView);
    float3 Nn = normalize(IN.WorldNormal);
	phong_shading(IN,Lamp0Color,Nn,Ln,Vn,diffContrib,specContrib);
    float3 diffuseColor = tex2D(ColorSampler,IN.UV).rgb;
    float3 result = specContrib+(diffuseColor*(diffContrib+AmbiColor));
    return float4(result,1);
}

( this is the shader part of a colladafx file )

Yeah, the names are somewhat restricted. I know, it sucks. Its very easy to rewrite the names a bit, though.

And last time I tried, using structs for input and output worked. Functions work good, too. Maybe you’ve only seen the coding style of the samples, and are thinking that’s the only way to do it?

yeah. that’s true. I’m not proud of it :blush:

This is really, really good. :smiley:

Does it support include file ( function from other file) ?

Try it and see.

oo thanks for pointing that out, that’s a big fact I haven’t seen anywhere. I was wondering the exact same thing he was, how .sha files are converted to from cg. So you’re saying that .sha files ARE cg files, just renamed?

So between these two statements it sounds like cgfx files actually contain cg shaders as part of them, and that stripping out the shaders so panda can use them should be fairly easy. Is that what you guys are saying? Because if my understanding is correct, then that is highly encouraging. I’m a ways off from actually trying to do this myself, but just knowing that it’ll be relatively easy to do once I get to that point would be very helpful. There are tons of shaders in nvidia’s shader library that I’d love to drop into my projects.

Exactly. Its fairly easy to rewrite such a shader. I’ve even rewritten GLSL shaders to panda without much effort.

If you do 'by hand the conversion is not very complex, we just need to ‘rename’ the varaible according to what panda3D want.

It seems
I just got a problem, here is the code that I just cleaned: ( this shader is mosly useless, by the way

//Cg

float Script = 0.8;

float4x4 WorldITXf : WorldInverseTranspose ;
float4x4 WvpXf : WorldViewProjection;
float4x4 WorldXf : World ;
float4x4 ViewIXf : ViewInverse ;

float3 Lamp0Pos : Position ;
float3 Lamp0Color : Specular;

float3 AmbiColor : Ambient;
float Ks;
float SpecExpon : SpecularPower; 

sampler2D ColorSampler ; 

struct appdata {
    float3 vtx_position	: POSITION;
    float4 vtx_texcoord	: TEXCOORD0;
    float4 vtx_normal	: NORMAL;
    float4 vtx_tangent	: TANGENT0;
    float4 vtx_binormal	: BINORMAL0;
};

struct vertexOutput {
    float4 l_position	: POSITION;
    float2 l_texcoord0  : TEXCOORD0;

    float3 l_texcoord1	: TEXCOORD1;
    float3 l_texcoord2	: TEXCOORD2;
    float3 l_texcoord3	: TEXCOORD3;
    float3 l_texcoord4  : TEXCOORD4;
    float3 l_texcoord5	: TEXCOORD5;
};

vertexOutput vshader(appdata IN) {
    vertexOutput OUT = (vertexOutput)0;
    OUT.l_texcoord2 = mul(WorldITXf, IN.vtx_normal).xyz;
    OUT.l_texcoord3 = mul(WorldITXf, IN.vtx_tangent).xyz;
    OUT.l_texcoord4 = mul(WorldITXf, IN.vtx_binormal).xyz;
    float4 Po = float4(IN.vtx_position.xyz, 1);
    float3 Pw = mul(WorldXf, Po).xyz;
    OUT.l_texcoord1 = (Lamp0Pos - Pw);
    OUT.l_texcoord0 = IN.vtx_texcoord.xy;
    OUT.l_texcoord5 = normalize(float3(ViewIXf[0].w, ViewIXf[1].w, ViewIXf[2].w) - Pw);
    OUT.l_position  = mul(WvpXf, Po);
    return OUT;
}

void phong_shading(vertexOutput IN,
		    float3 LightColor,
		    float3 Nn,
		    float3 Ln,
		    float3 Vn,
		    out float3 DiffuseContrib,
		    out float3 SpecularContrib)
{
    float3 Hn = normalize(Vn + Ln);
    float4 litV = lit(dot(Ln, Nn), dot(Hn, Nn), SpecExpon);
    DiffuseContrib = litV.y * LightColor;
    SpecularContrib = litV.y * litV.z * Ks * LightColor;
}

float4 fshader(vertexOutput IN) : COLOR {
    float3 diffContrib;
    float3 specContrib;
    float3 Ln = normalize(IN.l_texcoord1);
    float3 Vn = normalize(IN.l_texcoord5);
    float3 Nn = normalize(IN.l_texcoord2);
	phong_shading(IN, Lamp0Color, Nn, Ln, Vn, diffContrib, specContrib);
    float3 diffuseColor = tex2D(ColorSampler, IN.l_texcoord0).rgb;
    float3 result = specContrib+(diffuseColor * (diffContrib + AmbiColor));
    return float4(result, 1);
}

on loading I have this error:
:gobj(error): newfile.cg: unrecognized parameter name (varying in float4 IN.l_position)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float2 IN.l_texcoord0)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float3 IN.l_texcoord1)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float3 IN.l_texcoord2)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float3 IN.l_texcoord3)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float3 IN.l_texcoord4)
:gobj(error): newfile.cg: unrecognized parameter name (varying in float3 IN.l_texcoord5)

I don’t understand. It seems to tell me that the vertexOutputStruct is somewhat declared ‘variable’ ?

Uh, dunno. Maybe it doesn’t work with structs as function input but does with return values. Try copying the stuff in the ‘appdata’ struct to the vshader line, replacing ; with , .

The shader system could use a rewrite.

thank that’s it:

vertexOutput vshader(    float3 vtx_position	: POSITION,
    float4 vtx_texcoord	: TEXCOORD0,
    float4 vtx_normal	: NORMAL,
    float4 vtx_tangent	: TANGENT0,
    float4 vtx_binormal	: BINORMAL0) {
float4 fshader(
    in float4 l_position	: POSITION,
    in float2 l_texcoord0  : TEXCOORD0,
    in float3 l_texcoord1	: TEXCOORD1,
    in float3 l_texcoord2	: TEXCOORD2,
    in float3 l_texcoord3	: TEXCOORD3,
    in float3 l_texcoord4  : TEXCOORD4,
    in float3 l_texcoord5	: TEXCOORD5) :COLOR {

with these parts, it compile.
Well that’s that more that I have to do in my parsing.

True ! True ! :stuck_out_tongue: :smiley:

to continue this topic a bit.

I finally have some shaders working this way.
I found a ‘bug’ ( maybe it’s feature I don’t know )

The result is always the same: the object become invisible, with no error announced if :

  • an uniform variable ( k_anything) has a name with a ‘_’, no error show but the object become invisible ( ex: k_tex_ratio)
  • I declare a uniform float k_anything ( not a float4 like the manual said )
  • a uniform variable is declared outside the vshader, fshader function

it’s not that annoying now that I know, but the lack of error is disturbing

file a bug about the _ name.

It’s a known bug:
bugs.launchpad.net/panda3d/+bug/293479

…which I’ve just fixed. 1.6.0 now allows you to use underscores in k-parameter names (the ones you supply using setShaderInput).

About your other ‘bugs’: I’m sure they do generate an error. Check the console.
k-parameters can’t be varying, they must always be uniform.

In my cases, the k_anything were always uniform:

like in this case:

uniform float3 k_bob;
void vshader(in... out...){....}
void fshder(in... out...) {....}

And for the other:

uniform float k_bob ; 

I know the manual tell that this one doesn’t work. But is there a reason for this ? I have a lot of parameter that I want to give to my shader as a float ( for now I send them as float4 with 3 zero, but it’s not very user friendly.)

Actually, if you pass a float4, panda translates that into a 4x4 matrix (where it only uses the third row of). So it doesn’t really matter if you pass float4(1, 0, 0, 0) or float(1), it all gets translated to float4x4 anyways.
I agree that this system could be made more flexible.

Works fine for me.

I’ve just checked:

void vshader(   in float4 vtx_position                    : POSITION,
                in float2 vtx_texcoord                    : TEXCOORD0,
                in float3 vtx_tangent0                    : TANGENT,
                in float3 vtx_binormal0                   : BINORMAL,
                in float3 vtx_normal                      : NORMAL,

                in uniform float4 mspos_view,
                in uniform float4 k_light0,
                in uniform float k_bob,
                in uniform float4x4 mat_modelproj,
                in uniform float4x4 trans_world_to_model,

                out float4 l_position                     : POSITION,
                out float2 l_texcoord                     : TEXCOORD0,
                out float3 l_light0                       : TEXCOORD1,
                out float3 l_pos0                         : TEXCOORD2
            )

or

in uniform float4x4 mat_modelproj;

void vshader(   in float4 vtx_position                    : POSITION,
                in float2 vtx_texcoord                    : TEXCOORD0,
                in float3 vtx_tangent0                    : TANGENT,
                in float3 vtx_binormal0                   : BINORMAL,
                in float3 vtx_normal                      : NORMAL,

                in uniform float4 mspos_view,
                in uniform float4 k_light0,
                in uniform float4x4 trans_world_to_model,

                out float4 l_position                     : POSITION,
                out float2 l_texcoord                     : TEXCOORD0,
                out float3 l_light0                       : TEXCOORD1,
                out float3 l_pos0                         : TEXCOORD2
            )

insead of

void vshader(   in float4 vtx_position                    : POSITION,
                in float2 vtx_texcoord                    : TEXCOORD0,
                in float3 vtx_tangent0                    : TANGENT,
                in float3 vtx_binormal0                   : BINORMAL,
                in float3 vtx_normal                      : NORMAL,

                in uniform float4 mspos_view,
                in uniform float4 k_light0,
                in uniform float4x4 mat_modelproj,
                in uniform float4x4 trans_world_to_model,

                out float4 l_position                     : POSITION,
                out float2 l_texcoord                     : TEXCOORD0,
                out float3 l_light0                       : TEXCOORD1,
                out float3 l_pos0                         : TEXCOORD2
            )

make my model disappear, even if I don’t use k_bob ( I still give it via setShaderInput)

In both case, no error are cast, but the mesh is not visible (exactly the same as if I declare a k_any_thing )

EDIT: I’m running on ubuntu 8.04, openGL, 8800GT ( 177.80 nvidia drivers)