Problem binding CG to OpenGL program

Hi,

I was wondering if any CG gurus on the forum might be able to help me out. I’ve been coding in OpenGL for a while, but I’m a relative beginner to CG programming. What I’m trying to do right now is create a shader (and integrate it into my program) that implements a simple box or gaussian filter on the GPU in OpenGL under Linux. I’m using the cg_glow demo as a base, and simply having it work on a texture rectangle copied from the frame buffer into a texture (rather than blurring together bright areas). Unfortunately, since the cg_Glow example code from NVidia’s SDK is Direct3D (yuck) based, I can’t use it as an example on how I should set things up correctly. What is happing is that the vertex program gets a bind error any time it runs, while the fragment program, which is set up identically, binds without a problem. As you can imagine, I’m not EXACTLY sure what I’m doing cg wise, but I think that the program should basically work (or at least bind and then do the wrong thing). Anyone know what I’m doing wrong? I’ve barely changed the vertex or fragment code, but since the Direct3D code is impossible to understand, I’m not sure I’m making the proper CG and OpenGL calls where I should be… Here’s the error message:


CG ERROR : The program could not bind.

161 lines, 0 errors.


Cg error, exiting…

If I comment out the call to bind the vertex program, the error message disappears, although obviously the program doesn’t do anything. Since I have NO idea where the error may be, I’m including all the pertinent code involved. I’m sorry for the amount of lines involved, but I’d be extremely happy if someone could give it a glance and possibly help me out. Many thanks!!! Oh, also, if you spot any algorithmic problems in what I’m doing (implementation of the filter,) please let me know as well. Thanks!

Note: GW and GH are globals representing the resolution width and height.

My initialization:

// I’ve tried different vertex profiles
if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1)){
vertexProfile = CG_PROFILE_ARBVP1;
} else if (cgGLIsProfileSupported(CG_PROFILE_VP20)){
vertexProfile = CG_PROFILE_VP20;
} else {
printf("Vertex programming extensions (GL_ARB_vertex_program or "
"GL_NV_vertex_program) not supported, exiting…
");
exit(0);
}

if (cgGLIsProfileSupported(CG_PROFILE_FP20)){
    fragmentProfile = CG_PROFILE_FP20;

} else if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1)){
fragmentProfile = CG_PROFILE_ARBFP1;
} else {
printf("Fragment programming extensions (GL_ARB_fragment_program or "
"GL_NV_fragment_program) not supported, exiting…
");
exit(0);
}

data_path media;
media.path.push_back(“.”);
string filename = media.get_file(“blur_vertex.cg”);
if (filename == “”) {
printf("Unable to load blur_vertex.cg, exiting…
");
exit(0);
}

cgSetErrorCallback(cgErrorCallback);
shaderContext = cgCreateContext();

vertexProgram = cgCreateProgramFromFile(shaderContext,
    CG_SOURCE, filename.data(),
    vertexProfile, NULL, NULL);

cgGLLoadProgram(vertexProgram);

PositionParam = cgGetNamedParameter(vertexProgram, “IN.Position”);
T0_OffsetParam = cgGetNamedParameter(vertexProgram, “T0_Offset”);
T1_OffsetParam = cgGetNamedParameter(vertexProgram, “T1_Offset”);
T2_OffsetParam = cgGetNamedParameter(vertexProgram, “T2_Offset”);
T3_OffsetParam = cgGetNamedParameter(vertexProgram, “T3_Offset”);
WorldViewProjParam = cgGetNamedParameter(vertexProgram, “WorldViewProj”);
if (!PositionParam | | !T0_OffsetParam | | !T1_OffsetParam | | !T2_OffsetParam | | !T3_OffsetParam | | !WorldViewProjParam)
{
printf("Unable to retrieve vertex program parameters, exiting…
");
exit(0);
}
// END TODO

filename = media.get_file(“blur_fragment.cg”);
if (filename == “”)
{
printf("Unable to load blur_fragment.cg, exiting…
");
exit(0);
}

fragmentProgram = cgCreateProgramFromFile(shaderContext,
    CG_SOURCE, filename.data(),
    fragmentProfile, NULL, NULL);

cgGLLoadProgram(fragmentProgram);

// BEGIN TODO Fragment Program Params modify if stuff missing.
Texture0Param = cgGetNamedParameter(fragmentProgram, “Texture0”);
Texture1Param = cgGetNamedParameter(fragmentProgram, “Texture1”);
Texture2Param = cgGetNamedParameter(fragmentProgram, “Texture2”);
Texture3Param = cgGetNamedParameter(fragmentProgram, “Texture3”);
// Weight0Param = cgGetNamedParameter(fragmentProgram, “Weight0”);
// Weight1Param = cgGetNamedParameter(fragmentProgram, “Weight1”);
// Weight2Param = cgGetNamedParameter(fragmentProgram, “Weight2”);
// Weight3Param = cgGetNamedParameter(fragmentProgram, “Weight3”);

if (!Texture0Param | | !Texture1Param | | !Texture2Param | | !Texture3Param)

// | | !Weight0Param | | !Weight1Param | | !Weight2Param | | !Weight3Param)
{
printf("Unable to retrieve fragment program parameters, exiting…
");
exit(0);
}

// Texture copied from frame buffer and blurred using CG
glGenTextures(1, &BaseTex);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, BaseTex);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, GW, GH, 0, GL_RGB, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

cgGLSetTextureParameter(Texture0Param, BaseTex);
cgGLSetTextureParameter(Texture1Param, BaseTex);
cgGLSetTextureParameter(Texture2Param, BaseTex);
cgGLSetTextureParameter(Texture3Param, BaseTex);

Render loop code (after scene gets rendered:

glEnable(GL_TEXTURE_RECTANGLE_NV);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, BaseTex);
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0, GW, GH);

// Begin switch to Ortho mode
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, GW, GH, 0, -100, 100);
glMatrixMode(GL_MODELVIEW);
// End switch to Ortho mode

  cgGLEnableProfile(vertexProfile);
  cgGLBindProgram(vertexProgram);

  cgGLEnableProfile(fragmentProfile);
  cgGLBindProgram(fragmentProgram);

  // set vertex program inputs

  cgGLSetStateMatrixParameter(WorldViewProjParam, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

  // Enable Texture Params	

// All are bound to the same texture object.
cgGLEnableTextureParameter(Texture0Param);
cgGLEnableTextureParameter(Texture1Param);
cgGLEnableTextureParameter(Texture2Param);
cgGLEnableTextureParameter(Texture3Param);

// Offset parameters for the texture lookups to do a multisampling blur
cgGLSetParameter4f(T0_OffsetParam, offWTopLeft, offHTopLeft, 0.0f, 0.0f);
cgGLSetParameter4f(T1_OffsetParam, offWTopRight, offHTopRight, 0.0f, 0.0f);
cgGLSetParameter4f(T2_OffsetParam, offWBottomLeft, offHBottomLeft, 0.0f, 0.0f);
cgGLSetParameter4f(T3_OffsetParam, offWBottomRight, offHBottomRight, 0.0f, 0.0f);

// Not sure if the values I’m passing to position param are correct.
// it doesn’t make a difference what they are right now, as nothing
// happens.
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
cgGLSetParameter3f(PositionParam, -(float)GW, -(float)GH, 0.0f); ;
glTexCoord2f(0, GH);
cgGLSetParameter3f(PositionParam, -(float) GW, (float)GH, 0.0f);
glTexCoord2f(GW, GH);
cgGLSetParameter3f(PositionParam, (float)GW, (float)GH, 0.0f);
glTexCoord2f(GW, 0);
cgGLSetParameter3f(PositionParam, (float)GW, -(float)GH, 0.0f);

glEnd();

  // Disable Texture Params
  cgGLDisableTextureParameter(Texture0Param);
  cgGLDisableTextureParameter(Texture1Param);
  cgGLDisableTextureParameter(Texture2Param);
  cgGLDisableTextureParameter(Texture3Param);

  cgGLDisableProfile(vertexProfile);
  cgGLDisableProfile(fragmentProfile);

  glDisable(GL_TEXTURE_RECTANGLE_NV);

// Begin switch to Perspective mode
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// End switch to Perspective mode

Vertex Shader code (identical to cg_glow):

struct vertexin
{
float4 Position : POSITION;
float4 TexCoord0 : TEXCOORD0;
};

struct vertexout
{
float4 HPosition : POSITION;
float4 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
};

vertexout main( vertexin IN,
uniform float4x4 WorldViewProj : CG_WORLDVIEWPROJ_0,
uniform float4 T0_Offset : CG_T0_OFFSET,
uniform float4 T1_Offset : CG_T1_OFFSET,
uniform float4 T2_Offset : CG_T2_OFFSET,
uniform float4 T3_Offset : CG_T3_OFFSET
)
{
vertexout OUT;

// Transform position to HCLIP space
// Might not be needed in ortho mode ???
OUT.HPosition = mul( WorldViewProj, IN.Position );

// Add texture coordinate offsets to the single input
// vertex texture coordinate. This will cause
// a pattern of texels (for example, the nearest
// neighbors) to be sampled into the pixel shader
// texture sample registers t0 through t3.
// If the original texture coordinates are a one-to-one
// mapping of texels in the source to pixels of the
// render target, then these offsets will sample the
// same pattern of neighboring texels surrounding each
// pixel rendered.

OUT.TexCoord0 = IN.TexCoord0 + T0_Offset;
OUT.TexCoord1 = IN.TexCoord0 + T1_Offset;
OUT.TexCoord2 = IN.TexCoord0 + T2_Offset;
OUT.TexCoord3 = IN.TexCoord0 + T3_Offset;

return( OUT );
}

Fragment shader code (slightly modified from cg_glow, as I don’t want different weights for the averaging together of the frag colors from the different texture units, I just want their pure average):

struct v2f
{
float4 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
};

fragout main( v2f IN,
uniform sampler2D Texture0 : texunit0,
uniform sampler2D Texture1 : texunit1,
uniform sampler2D Texture2 : texunit2,
uniform sampler2D Texture3 : texunit3
// commented out as I don’t need different weights for the average
// uniform float4 Weight0 : MF0,
// uniform float4 Weight1 : MF1,
// uniform float4 Weight2 : MF2,
// uniform float4 Weight3 : MF3
)
{
fragout OUT;

// Get colors from all 4 texture stages

float4 t0 = tex2D( Texture0 );
float4 t1 = tex2D( Texture1 );
float4 t2 = tex2D( Texture2 );
float4 t3 = tex2D( Texture3 );

float4 r0;

// The frag program seems to have no problem with a straight add
// at least the compiler doesn’t complain…
r0 = t0 + t1 + t2 + t3;

// commented out old method.
// r0 = add(t0, t1);
// r0 = add(r0, t2);
// r0 = add(r0, t3);

// Don’t care about using different weights.
r0 = r0 * float(0.25);
// r0 = Weight0 * t0;
// r0 = mad( Weight1, t1, r0 );
// r0 = mad( Weight2, t2, r0 );
// r0 = mad( Weight3, t3, r0 );

OUT.col = r0;
return( OUT );
}

Thanks much for all your help!

Would you be able to post or email me the source to a demo that reproduces this problem? Nothing looks obviously wrong with your code so I’d like to be able to step through it and locate the problem.

You could try the cgShaders forums…

jra101: Thanks for the quick reply. The code’s on its way.

rgpc: Thanks for the suggestion. I actually already posted on it, but the forum itself isn’t as active as this one. I figured I had a better chance of getting the right person to read it sooner if I posted here as well.

Thanks again.

You need to use samplerRECT types and texRECT lookup functions since the texture you are using is a texture rectangle.