usage of <generator> element in profile_CG

Hi,

Looking at the scheme of the <surface>-parameter in profile_CG and profile_GLSL, I’m a bit puzzled about how the <generator>-element is intended to work.

I understand it’s thought to procedurally create surfaces, which later might be used as sampler, etc… The element has it’s own (and mandatory) <code> or <include>, so shader code is provided.

I guess the shader stage, is implicitly given to use FRAGMENTSTAGE (as there is no way to define such in <generator>-element), and we simply render a quad.

Also, there is no way of binding params to uniformSymbols (like with <bind> in <shader>-element)., and I don’t quite understand, why someone would need the possible <setparam>-elements.

My guess so far: it’s though to provide very simple procedural textures, which could be generated during some kind of setup-phase, everything that’s more complex and dependent of scene-information would use a <shader>-element with a rendertarget set.

Is that right?

Yes I agree with you (but we may both be wrong). Generated surfaces through the <generator> are meant for a pre-render setup, not for create each frame type of use. The use of renderTargets is much more suited for that purpose.

The one thing that I have to add is that <setparam> elements can be used to set shader variables. It is not the same as bind which can set shader variables and parameters. The resolution of setparam should first look in the effect scope (most likely in steps, technique scope, profile scope, effect scope) then look through the shader variables. Then if it still doesn’t find something it fails.

-Andy

The one thing that I have to add is that <setparam> elements can be used to set shader variables. It is not the same as bind which can set shader variables and parameters. The resolution of setparam should first look in the effect scope (most likely in steps, technique scope, profile scope, effect scope) then look through the shader variables.

That clears how to bind anything to a <generator>-shader. But this applies to the <setparam>'s in <generator>-element only, does it? So in <shader>-element you would still have to use the <bind>-element to bind anything to the runtime…

Browsing through the code of the cfxloader, I know understand how to use the setparams:

The referenced parameter can either be a <newparam> or a parameter that was
created by loading the shader code…

I originally thought, COLLADAFX completely wraps the parameter initialization. But it seems like you have the shader-src, and additionally the COLLADAFX, that
might wrap all components, but does not have to…

In the method “loadNewParamArray(…)” in the COLLADA_FX cfxLoader.cpp I found a comment saying

// the newParam array contains parameters that are not in the shader code

That’s a bit confusing, because the COLLADA-files using profile_CG I saw, always have all of their shader-uniforms also in the newparam.

Could someone clear my confusion about how the newparam-array, setparam-parray are related to the shader-source in detail?

I am no expert in shader coding and effect runtimes but I think I know why Tanya wrote that comment.

at the time of writing the CFXLoader we were loading in cgfx files. In a cgfx file you can have the shader code and some effect stuff. There are then two types of variables (same with COLLADA) shader variables and effect variables. In COLLADA, <newparam> creates effect variables. <setparam> sets variables (either kind). <bind> sets variables or shader parameters.

When loading a cgfx file, the runtime will create the effect variables declared in the file. Then in the COLLADA document you don’t need to/probably shouldn’t redeclare those variables. hence the comment.

With glsl, which I believe is your primary focus, you don’t have any existing effect format so you don’t have to worry about that. But when converting CFX-CG to CFX-GLSL you should probably check what type of shader is being loaded. A pure .cg shader file you don’t have to worry about this, but if referrencing a .cgfx file you will want to get the effect parameters declared in the file.

Thats my best guess for this. I could be all wrong if loading a cgfx file, the way the CFXLoder does mainly just for the shader code, doesn’t create the effect parameters. I don’t know those little details.

-Andy

Hello,

It’s been a while since I wrote that comment, but I think there were a few reasons behind that, some of which Andy has already given.

The newparam array should contain parameters that are intended to be exposed to the user. The initial implementation of the COLLADA FX content creation tools just exposed all the parameters by default which was a quick way to get things compliant and working with the system. As the software matures, we would like to have controls that can refine the set of parameters are to be exposed to the user.

Just to be clear, if you want to have a shader parameter be settable from a material, it must have a newparam in the COLLADA effect. With cg, when the setparam specifies the values in a material, the CGparameter is acquired through a call to cgGetNamedEffectParameter. In COLLADA FX, the only CGparameters that can be returned by that call are ones that were created with a call to cgCreateEffectParameter, which are only newparams.

Some of the other cool things that newparams enable are shader language independent parameter exposure, the capabillity to bind one newparam to many inputs, and I think you can even bind them to fixed pipeline state settings if you actually use the common profile (but I haven’t tried that personally).

Hope that clarifies things a bit.

-Tanya.

thanks for your time, tanya and andy…

After reading your comments on that issue, and also looking at the COLLADAFX output of FeelingSoftware’s Maya-Plugin and NVIDIA’s FXC2 Alpha, I concluded the following:

the <newparam> array defines some kind of an interface to shader variables (whatever scope), that exist in the runtime. It’s possible to have

1.) newparam’s defined which might not occur in the referenced code

as well as

2.) variables defined in the shader-code that are not exposed via the newparam array.

If you want the user of the effects to manipulate certain parameters, then you definitely should expose them via newparam.

For case 1.) the Cg API offers the cgCreateEffectParameter, in GLSL however it’s not possible to create parameters “on the fly” (except maybe generating source-code, and additionally linking it with the current program)

As GLSL has no effect-type, my converter is creating for each referenced-source/entry_name - pair it’s own <include>/<code> - element Fortunately the Cg-compiler picks out all necessary variables of the Cg/CGFX-file for compilation. So case 2.) won’t ever get any problem.

However, for Case 1.) I would have to create the Effect-Parameter, before compiling into GLSL, so we have that required reference in the GLSL-code. Until now, I just use normal Cg-programs which are built from any referenced Cg-source code and get built into GLSL afterwards. - note the referenced code could also be a CGFX file, it generates no error, the CGFX-stuff like techniques, etc… is simply ignored - in the end it’s the same compiler) But for correctly handling Case 1, I need to create a CGEffect, and not just a CGProgram, for being able to use the cgCreateEffectParameter to create the missing parameter reference.

I understand that the first COLLADAFX was written to be used next to the CGFX-runtime. That actually creates some way of redundancy in the effect definition, because the definition of an effect shouldn’t be a matter of the runtime itself anymore, but rather of the COLLADAFX.

Now I was just browsing through the output of NVIDIA’s FXC 2 Alpha and when converting to COLLADAFX-format they strip all of their CGFX-stuff in the source-reference before…resulting in clean Cg-Code. I hope I don’t break any NDA-agreements by posting this :wink:

The output of the COLLADAMAYA-plugin is directly referencing a cgfx file, but that reference is more or less just a container of source-code. The Vertex and Fragment Shader used in COLLADAFX are just referenced with the correct entry-function to this Cg-“container”

Both Apps expose all of their shader variables via the newparam-array, and bind them via the <bind>-array for each shader.
I think that’s the least confusing way of using COLLADAFX. You use the <bind>-array for each shader as the only connecting interface between the variables in you shader-src/runtime and the variable in your COLLADAFX-“runtime”. That’s the way I thought you should use COLLADAFX in first place…

So for now I implement the converter expecting the COLLADAFX to be used like COLLADAMAYA and FXC2 does. But I will additionally check for any “unbalances” between the setparam, newparam and the shader variables…

I’m really looking forward to the next FXC2-release, as this is by far the most complex app using COLLADAFX. When more people outside the walls of the big game companies start using COLLADAFX, things will get really interesting, and I guess with more mature COLLADAFX-examples, we will see how you conveniently expose your shaders via COLLADAFX…