So, I'm making the painful move from my beloved XNA to OpenTK, and I'm stuck:

Since I've got a LOT of existing shaders written in HLSL, NVidia's CG compiler seems like a natural way to minimize the impact on my existing code.

I'm confused, however, about how to compile shaders that use techniques and passes rather than separate vertex and fragment shader programs. The cgc compiler seems to require that one specify an entry point for a shader. However, it's unclear what this means in terms of a shader that has multiple potential entry points without a main() function. For instance, the simple CG effect (an off-the-shelf CG effect created in the ever-flakey FX Composer):


% Description of my shader.
% Second line of description for my shader.

keywords: material classic

date: YYMMDD


float4x4 WorldViewProj : WorldViewProjection;

float4 mainVS(float3 pos : POSITION) : POSITION{
    return mul(WorldViewProj, float4(pos.xyz, 1.0));

float4 mainPS() : COLOR {
    return float4(1.0, 0.0, 1.0, 1.0);

technique technique0 {
    pass p0 {
        CullFaceEnable = true;  
        VertexProgram = compile vp30 mainVS();
        FragmentProgram = compile f340 mainPS();

The only way I can get this to compile with the cgc command line compiler is:

cgc -noentry test.cgfx

And,of course, I get no output other than a statement that the program was compiled without errors.

The NVidia docs say that the CG compiler can output GLSL if the appropriate profile is passed to the compiler. However, all of the profiles I've seen are either vertex- or pixel/fragment-specific, which seems to contradict the idea of having both in a single file, linked by the technique and pass definitions.

What am I missing here?

Note that I've been able to build this effect using the Cg runtime via the Tao.Cg stuff, but using that appears to require including the Cg runtime in my app distribution, and I can't see a way to make that work on OSX and Linux.

Update I've noticed that by specifying the vertex shader or pixel shader directly as an entry point, and including a -profile glslf' or-profile glslv`, that I can get GLSL output for either shader, but this obviously doesn't include setting the state or take into account multiple passes or multiple techniques. Do I really have to run the compiler once for each function defined in the shader source?

  • \$\begingroup\$ "So, I'm making the painful move from my beloved XNA to OpenTK" Is there any particular reason for that? \$\endgroup\$ Commented May 5, 2012 at 16:42
  • \$\begingroup\$ @NicolBolas Mostly Microsoft's lack of clarification on what's going to happen with XNA with Win8 and the next XBOX. Sure, it'll run in legacy mode and on the 360, but it's not exactly encouraging. And cross-platform development is kinda neat. \$\endgroup\$
    – 3Dave
    Commented May 5, 2012 at 17:19
  • \$\begingroup\$ @NicolBolas to put this in perspective: I once (circa 1998) loved an amazing tool called Delphi. Native code, REAL visual form designer,... Not really thrilled about getting stuck in the same boat with projects I do for fun. \$\endgroup\$
    – 3Dave
    Commented May 6, 2012 at 3:09

1 Answer 1


CgFX files are not shaders. They are FX files. Shaders are a lower-level construct; a shader is just the source code for a particular shading stage. Techniques, passes, etc are all higher level than Cg.

You cannot process CgFX's FX data into GLSL because GLSL has no equivalent constructs (just as Cg itself doesn't). You can process the files themselves with cgc, but you have to select whether you're getting the vertex shader, fragment shader, or whatever out of the CgFX file. That's why you need to specify an entrypoint.

  • \$\begingroup\$ Okay; if CG doesn't have equivalent constructs, why does it support technique and pass? Are those just there for HLSL compatibility? \$\endgroup\$
    – 3Dave
    Commented May 5, 2012 at 17:19
  • \$\begingroup\$ @DavidLively: Cg and CgFX are not the same thing. They're related, but they aren't the same. Cg does not support technique and pass; CgFX does. And quite frankly, HLSL doesn't support those either; it's the FX format that does. You're conflating two ideas that, while related, are indeed separate. \$\endgroup\$ Commented May 5, 2012 at 17:21
  • \$\begingroup\$ Fair enough. How, then, can I take advantage of those features of CGFX? Do I really need to write something to parse the CGFX and build separate GL programs for each technique? \$\endgroup\$
    – 3Dave
    Commented May 5, 2012 at 18:04
  • \$\begingroup\$ @DavidLively: GLSL has no FX format or runtime. And since you're only using Cg to translate the shaders to GLSL, the CgFX stuff is untranslatable. So if you want an FX-style runtime in OpenGL, you must write it yourself. \$\endgroup\$ Commented May 5, 2012 at 18:38
  • \$\begingroup\$ This is starting to make sense. If I understand correctly, the FX runtime (DX or CG) takes care of building shader programs for each technique, compiling and linking the appropriate vs/ps/etc, but that's more of a preprocessing step in that the actual shader language - be it GLSL or HLSL - doesn't support that type of thing. Which would make techniques, passes, etc something akin to a makefile (cringe at crappy simile) \$\endgroup\$
    – 3Dave
    Commented May 6, 2012 at 2:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .