static INLINE CGparameter d3d9_cg_find_param_from_semantic( CGparameter param, const char *sem) { for (; param; param = cgGetNextParameter(param)) { const char *semantic = NULL; if (cgGetParameterType(param) == CG_STRUCT) { CGparameter ret = d3d9_cg_find_param_from_semantic( cgGetFirstStructParameter(param), sem); if (ret) return ret; } if ( cgGetParameterDirection(param) != CG_IN || cgGetParameterVariability(param) != CG_VARYING) continue; semantic = cgGetParameterSemantic(param); if (!semantic) continue; if (string_is_equal(sem, semantic) && d3d9_cg_validate_param_name(cgGetParameterName(param))) return param; } return NULL; }
void csShaderGLCGCommon::DebugDumpParam (csString& output, CGparameter param) { output << "Parameter: " << cgGetParameterName (param) << "\n"; output << " Type: " << cgGetTypeString (cgGetParameterNamedType (param)) << "\n"; output << " Direction: " << cgGetEnumString (cgGetParameterDirection (param)) << "\n"; output << " Semantic: " << cgGetParameterSemantic (param) << "\n"; const CGenum var = cgGetParameterVariability (param); output << " Variability: " << cgGetEnumString (var) << "\n"; output << " Resource: " << cgGetResourceString (cgGetParameterResource (param)) << "\n"; output << " Resource index: " << cgGetParameterResourceIndex (param) << "\n"; // Cg 2.0 seems to not like CG_DEFAULT for uniforms if (/*(var == CG_UNIFORM) || */(var == CG_CONSTANT)) { int nValues; const double* values = cgGetParameterValues (param, (var == CG_UNIFORM) ? CG_DEFAULT : CG_CONSTANT, &nValues); if (nValues != 0) { output << " Values:"; for (int v = 0; v < nValues; v++) { output << ' ' << values[v]; } output << "\n"; } } if (!cgIsParameterUsed (param, program)) output << " not used\n"; if (!cgIsParameterReferenced (param)) output << " not referenced\n"; }
static INLINE CGparameter find_param_from_semantic( CGparameter param, const char *sem) { while (param) { if (cgGetParameterType(param) == CG_STRUCT) { CGparameter ret = find_param_from_semantic( cgGetFirstStructParameter(param), sem); if (ret) return ret; } else { if (cgGetParameterSemantic(param) && !strcmp(sem, cgGetParameterSemantic(param)) && cgGetParameterDirection(param) == CG_IN && cgGetParameterVariability(param) == CG_VARYING && validate_param_name(cgGetParameterName(param))) return param; } param = cgGetNextParameter(param); } return NULL; }
CCgUniform::CCgUniform(const CGparameter& parameter, bool global) : Parameter(parameter), Type(CG_UNKNOWN_TYPE) { Name = cgGetParameterName(Parameter); if(global) Space = CG_GLOBAL; else Space = CG_PROGRAM; }
void GLCgShader::FillParameters(const CGenum domain) { CGparameter param = cgGetFirstParameter(m_cgProgam, domain); while (param) { const char* name = cgGetParameterName(param); m_params[name] = param; param = cgGetNextParameter(param); } }
cgfxVaryingParameter::cgfxVaryingParameter(CGparameter parameter) : fParameter( parameter), fVertexAttribute( NULL), fVertexStructure( NULL), fNext( NULL) { if( parameter) { fName = cgGetParameterName( parameter); } }
/* iterate all parameters and record input variyings with their semantic and resource index */ void CD3DCG::fillParameterMap(std::vector<parameterEntry> &map, CGparameter param) { parameterEntry mapEntry; while (param) { if(cgGetParameterType(param)==CG_STRUCT) fillParameterMap(map,cgGetFirstStructParameter(param)); else if (cgGetParameterDirection(param) == CG_IN && cgGetParameterVariability(param) == CG_VARYING) { mapEntry.rIndex = cgGetParameterResourceIndex(param); mapEntry.semantic = cgGetParameterSemantic(param); mapEntry.isKnownParam = isKnownParameter(cgGetParameterName(param)); if(map.size()<mapEntry.rIndex+1) map.resize(mapEntry.rIndex+1); map[mapEntry.rIndex] = mapEntry; } param = cgGetNextParameter(param); } }
//--------------------------------------------------------------------- void CgProgram::recurseParams(CGparameter parameter, size_t contextArraySize) { while (parameter != 0) { // Look for uniform parameters only // Don't bother enumerating unused parameters, especially since they will // be optimised out and therefore not in the indexed versions CGtype paramType = cgGetParameterType(parameter); if (cgGetParameterVariability(parameter) == CG_UNIFORM && paramType != CG_SAMPLER1D && paramType != CG_SAMPLER2D && paramType != CG_SAMPLER3D && paramType != CG_SAMPLERCUBE && paramType != CG_SAMPLERRECT && cgGetParameterDirection(parameter) != CG_OUT && cgIsParameterReferenced(parameter)) { int arraySize; switch(paramType) { case CG_STRUCT: recurseParams(cgGetFirstStructParameter(parameter)); break; case CG_ARRAY: // Support only 1-dimensional arrays arraySize = cgGetArraySize(parameter, 0); recurseParams(cgGetArrayParameter(parameter, 0), (size_t)arraySize); break; default: // Normal path (leaf) String paramName = cgGetParameterName(parameter); size_t logicalIndex = cgGetParameterResourceIndex(parameter); // Get the parameter resource, to calculate the physical index CGresource res = cgGetParameterResource(parameter); bool isRegisterCombiner = false; size_t regCombinerPhysicalIndex = 0; switch (res) { case CG_COMBINER_STAGE_CONST0: // register combiner, const 0 // the index relates to the texture stage; store this as (stage * 2) + 0 regCombinerPhysicalIndex = logicalIndex * 2; isRegisterCombiner = true; break; case CG_COMBINER_STAGE_CONST1: // register combiner, const 1 // the index relates to the texture stage; store this as (stage * 2) + 1 regCombinerPhysicalIndex = (logicalIndex * 2) + 1; isRegisterCombiner = true; break; default: // normal constant break; } // Trim the '[0]' suffix if it exists, we will add our own indexing later if (StringUtil::endsWith(paramName, "[0]", false)) { paramName.erase(paramName.size() - 3); } GpuConstantDefinition def; def.arraySize = contextArraySize; mapTypeAndElementSize(paramType, isRegisterCombiner, def); if (def.constType == GCT_UNKNOWN) { LogManager::getSingleton().logMessage( "Problem parsing the following Cg Uniform: '" + paramName + "' in file " + mName); // next uniform parameter = cgGetNextParameter(parameter); continue; } if (isRegisterCombiner) { def.physicalIndex = regCombinerPhysicalIndex; } else { // base position on existing buffer contents if (def.isFloat()) { def.physicalIndex = mFloatLogicalToPhysical->bufferSize; } else { def.physicalIndex = mIntLogicalToPhysical->bufferSize; } } def.logicalIndex = logicalIndex; if( mParametersMap.find(paramName) == mParametersMap.end()) { mParametersMap.insert(GpuConstantDefinitionMap::value_type(paramName, def)); mParametersMapSizeAsBuffer += sizeof(size_t); mParametersMapSizeAsBuffer += paramName.size(); mParametersMapSizeAsBuffer += sizeof(GpuConstantDefinition); } // Record logical / physical mapping if (def.isFloat()) { OGRE_LOCK_MUTEX(mFloatLogicalToPhysical->mutex); mFloatLogicalToPhysical->map.insert( GpuLogicalIndexUseMap::value_type(def.logicalIndex, GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL))); mFloatLogicalToPhysical->bufferSize += def.arraySize * def.elementSize; } else { OGRE_LOCK_MUTEX(mIntLogicalToPhysical->mutex); mIntLogicalToPhysical->map.insert( GpuLogicalIndexUseMap::value_type(def.logicalIndex, GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize, GPV_GLOBAL))); mIntLogicalToPhysical->bufferSize += def.arraySize * def.elementSize; } break; } } // now handle uniform samplers. This is needed to fix their register positions // if delegating to a GLSL shader. if (mDelegate && cgGetParameterVariability(parameter) == CG_UNIFORM && ( paramType == CG_SAMPLER1D || paramType == CG_SAMPLER2D || paramType == CG_SAMPLER3D || paramType == CG_SAMPLERCUBE || paramType == CG_SAMPLERRECT) && cgGetParameterDirection(parameter) != CG_OUT && cgIsParameterReferenced(parameter)) { String paramName = cgGetParameterName(parameter); CGresource res = cgGetParameterResource(parameter); int pos = -1; switch (res) { case CG_TEXUNIT0: pos = 0; break; case CG_TEXUNIT1: pos = 1; break; case CG_TEXUNIT2: pos = 2; break; case CG_TEXUNIT3: pos = 3; break; case CG_TEXUNIT4: pos = 4; break; case CG_TEXUNIT5: pos = 5; break; case CG_TEXUNIT6: pos = 6; break; case CG_TEXUNIT7: pos = 7; break; case CG_TEXUNIT8: pos = 8; break; case CG_TEXUNIT9: pos = 9; break; case CG_TEXUNIT10: pos = 10; break; case CG_TEXUNIT11: pos = 11; break; case CG_TEXUNIT12: pos = 12; break; case CG_TEXUNIT13: pos = 13; break; case CG_TEXUNIT14: pos = 14; break; case CG_TEXUNIT15: pos = 15; break; #if(CG_VERSION_NUM >= 3000) case CG_TEXUNIT16: pos = 16; break; case CG_TEXUNIT17: pos = 17; break; case CG_TEXUNIT18: pos = 18; break; case CG_TEXUNIT19: pos = 19; break; case CG_TEXUNIT20: pos = 20; break; case CG_TEXUNIT21: pos = 21; break; case CG_TEXUNIT22: pos = 22; break; case CG_TEXUNIT23: pos = 23; break; case CG_TEXUNIT24: pos = 24; break; case CG_TEXUNIT25: pos = 25; break; case CG_TEXUNIT26: pos = 26; break; case CG_TEXUNIT27: pos = 27; break; case CG_TEXUNIT28: pos = 28; break; case CG_TEXUNIT29: pos = 29; break; case CG_TEXUNIT30: pos = 30; break; case CG_TEXUNIT31: pos = 31; break; #endif default: break; } if (pos != -1) { mSamplerRegisterMap.insert(std::make_pair(paramName, pos)); } } // Get next parameter = cgGetNextParameter(parameter); } }
static void AddParameter(JSON &json, CGparameter param) { const char * const parameterName = cgGetParameterName(param); if (sVerbose) { puts(parameterName); } json.AddObject(parameterName); const CGtype type = cgGetParameterType(param); const CGtype baseType = cgGetParameterBaseType(param); int numRows = cgGetParameterRows(param); const int numColumns = cgGetParameterColumns(param); if (CG_ARRAY == type) { const int totalArraySize = cgGetArrayTotalSize(param); numRows *= totalArraySize; } json.AddString("type", cgGetTypeString(baseType)); if (1 < numRows) { json.AddValue("rows", numRows); } if (1 < numColumns) { json.AddValue("columns", numColumns); } const int maxNumElements = (numColumns * numRows); int n; if (CG_FLOAT == baseType) { float * const values = (float *)malloc(maxNumElements * sizeof(float)); const int numValues = cgGetParameterValuefr(param, maxNumElements, values); if (numValues) { for (n = 0; n < numValues; n++) { if (values[n] != 0.0f) { break; } } if (n < numValues) { json.AddArray("values", true); json.BeginData(true); for (n = 0; n < numValues; n++) { json.AddData(values[n]); } json.EndData(); json.CloseArray(true); } } free(values); } else if (CG_INT == baseType) { int * const values = (int *)malloc(maxNumElements * sizeof(int)); const int numValues = cgGetParameterValueir(param, maxNumElements, values); if (numValues) { for (n = 0; n < numValues; n++) { if (values[n]) { break; } } if (n < numValues) { json.AddArray("values", true); json.BeginData(true); for (n = 0; n < numValues; n++) { json.AddData(values[n]); } json.EndData(); json.CloseArray(true); } } free(values); } else if (CG_BOOL == baseType) { int * const values = (int *)malloc(maxNumElements * sizeof(int)); const int numValues = cgGetParameterValueir(param, maxNumElements, values); if (numValues) { for (n = 0; n < numValues; n++) { if (values[n]) { break; } } if (n < numValues) { json.AddArray("values", true); json.BeginData(true); for (n = 0; n < numValues; n++) { json.AddData(values[n]); } json.EndData(); json.CloseArray(true); } } free(values); } json.CloseObject(); // parameter }
static bool AddPass(CGtechnique technique, JSON &json, CGpass pass, UniformsMap &uniformRemapping) { bool success = true; json.AddObject(NULL); const char * const passName = cgGetPassName(pass); if (NULL != passName) { json.AddString("name", passName); } bool firstParameter = true; #if CG_VERSION_NUM >= 3000 const int CG_NUMBER_OF_DOMAINS = (CG_TESSELLATION_EVALUATION_DOMAIN + 1); #endif for (int domain = CG_FIRST_DOMAIN; domain < CG_NUMBER_OF_DOMAINS; domain++) { const CGprogram program = cgGetPassProgram(pass, (CGdomain)domain); if (NULL != program) { const char * const programString = cgGetProgramString(program, CG_COMPILED_PROGRAM); CGparameter param = cgGetFirstParameter(program, CG_GLOBAL); while (NULL != param) { if (cgIsParameterUsed(param, program) && CG_UNIFORM == cgGetParameterVariability(param)) { if (firstParameter) { firstParameter = false; json.AddArray("parameters", true); json.BeginData(true); } const char * const paramName = cgGetParameterName(param); AddMappedParameter(json, paramName, programString, uniformRemapping); } param = cgGetNextParameter(param); } param = cgGetFirstParameter(program, CG_PROGRAM); while (NULL != param) { if (cgIsParameterUsed(param, program) && CG_UNIFORM == cgGetParameterVariability(param)) { if (firstParameter) { firstParameter = false; json.AddArray("parameters", true); json.BeginData(true); } const char * const paramName = cgGetParameterName(param); AddMappedParameter(json, paramName, programString, uniformRemapping); } param = cgGetNextParameter(param); } } } if (!firstParameter) { json.EndData(); json.CloseArray(true); // parameters } json.AddArray("semantics", true); json.BeginData(true); CGprogram vertexProgram = cgGetPassProgram(pass, CG_VERTEX_DOMAIN); CGparameter vertexInputParameter = cgGetFirstLeafParameter(vertexProgram, CG_PROGRAM); while (NULL != vertexInputParameter) { const CGenum variability = cgGetParameterVariability(vertexInputParameter); if (CG_VARYING == variability) { const CGenum direction = cgGetParameterDirection(vertexInputParameter); if (CG_IN == direction || CG_INOUT == direction) { const char * const semantic = cgGetParameterSemantic(vertexInputParameter); json.AddData(semantic, strlen(semantic)); } } vertexInputParameter = cgGetNextLeafParameter(vertexInputParameter); } json.EndData(); json.CloseArray(true); // semantics json.AddObject("states"); CGstateassignment state = cgGetFirstStateAssignment(pass); if (NULL != state) { do { success &= AddState(json, state); state = cgGetNextStateAssignment(state); } while (NULL != state); } json.CloseObject(); // states json.AddArray("programs", true); json.BeginData(true); for (int domain = CG_FIRST_DOMAIN; domain < CG_NUMBER_OF_DOMAINS; domain++) { const CGprogram program = cgGetPassProgram(pass, (CGdomain)domain); if (NULL != program) { const char * const entryPoint = cgGetProgramString(program, CG_PROGRAM_ENTRY); json.AddData(entryPoint, strlen(entryPoint)); } else if (domain == CG_VERTEX_DOMAIN) { ErrorMessage("%s : No vertex program.", cgGetTechniqueName(technique)); success = false; } else if(domain == CG_FRAGMENT_DOMAIN) { ErrorMessage("%s : No fragment program.", cgGetTechniqueName(technique)); success = false; } } json.EndData(); json.CloseArray(true); // programs json.CloseObject(); // pass return success; }
//--------------------------------------------------------------------- void CgProgram::recurseParams(CGparameter parameter, size_t contextArraySize) const { while (parameter != 0) { // Look for uniform (non-sampler) parameters only // Don't bother enumerating unused parameters, especially since they will // be optimised out and therefore not in the indexed versions CGtype paramType = cgGetParameterType(parameter); if (cgGetParameterVariability(parameter) == CG_UNIFORM && paramType != CG_SAMPLER1D && paramType != CG_SAMPLER2D && paramType != CG_SAMPLER3D && paramType != CG_SAMPLERCUBE && paramType != CG_SAMPLERRECT && cgGetParameterDirection(parameter) != CG_OUT && cgIsParameterReferenced(parameter)) { int arraySize; switch(paramType) { case CG_STRUCT: recurseParams(cgGetFirstStructParameter(parameter)); break; case CG_ARRAY: // Support only 1-dimensional arrays arraySize = cgGetArraySize(parameter, 0); recurseParams(cgGetArrayParameter(parameter, 0), (size_t)arraySize); break; default: // Normal path (leaf) String paramName = cgGetParameterName(parameter); size_t logicalIndex = cgGetParameterResourceIndex(parameter); // Get the parameter resource, to calculate the physical index CGresource res = cgGetParameterResource(parameter); bool isRegisterCombiner = false; size_t regCombinerPhysicalIndex = 0; switch (res) { case CG_COMBINER_STAGE_CONST0: // register combiner, const 0 // the index relates to the texture stage; store this as (stage * 2) + 0 regCombinerPhysicalIndex = logicalIndex * 2; isRegisterCombiner = true; break; case CG_COMBINER_STAGE_CONST1: // register combiner, const 1 // the index relates to the texture stage; store this as (stage * 2) + 1 regCombinerPhysicalIndex = (logicalIndex * 2) + 1; isRegisterCombiner = true; break; default: // normal constant break; } // Trim the '[0]' suffix if it exists, we will add our own indexing later if (StringUtil::endsWith(paramName, "[0]", false)) { paramName.erase(paramName.size() - 3); } GpuConstantDefinition def; def.arraySize = contextArraySize; mapTypeAndElementSize(paramType, isRegisterCombiner, def); if (def.constType == GCT_UNKNOWN) { LogManager::getSingleton().logMessage( "Problem parsing the following Cg Uniform: '" + paramName + "' in file " + mName); // next uniform continue; } if (isRegisterCombiner) { def.physicalIndex = regCombinerPhysicalIndex; } else { // base position on existing buffer contents if (def.isFloat()) { def.physicalIndex = mFloatLogicalToPhysical.bufferSize; } else { def.physicalIndex = mIntLogicalToPhysical.bufferSize; } } mConstantDefs.map.insert(GpuConstantDefinitionMap::value_type(paramName, def)); // Record logical / physical mapping if (def.isFloat()) { OGRE_LOCK_MUTEX(mFloatLogicalToPhysical.mutex) mFloatLogicalToPhysical.map.insert( GpuLogicalIndexUseMap::value_type(logicalIndex, GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize))); mFloatLogicalToPhysical.bufferSize += def.arraySize * def.elementSize; mConstantDefs.floatBufferSize = mFloatLogicalToPhysical.bufferSize; } else { OGRE_LOCK_MUTEX(mIntLogicalToPhysical.mutex) mIntLogicalToPhysical.map.insert( GpuLogicalIndexUseMap::value_type(logicalIndex, GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize))); mIntLogicalToPhysical.bufferSize += def.arraySize * def.elementSize; mConstantDefs.intBufferSize = mIntLogicalToPhysical.bufferSize; } // Deal with array indexing mConstantDefs.generateConstantDefinitionArrayEntries(paramName, def); break; } } // Get next parameter = cgGetNextParameter(parameter); } }
//---------------------------------------------------------------------------------------------------- // Standard windows mainline, this is the program entry point // CrtInt32 WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, CrtInt32 nCmdShow) { (void)hPrevInstance; // Avoid warnings (void)nCmdShow; // Avoid warnings (void)hInstance; // Avoid warnings #ifndef NO_DEVIL ilInit(); #endif MSG msg; BOOL done=FALSE; // Avoid warnings later msg.wParam = 0; // Turns on windows heap debugging #if HEAP_DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF /*| _CRTDBG_DELAY_FREE_MEM_DF*/); #endif // Ask The User Which Screen Mode They Prefer // if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; } // Set the default screen size _CrtRender.SetScreenWidth( 640); _CrtRender.SetScreenHeight( 480); // Create an OpenGL Window if (!CreateGLWindow("Collada Viewer for PC", _CrtRender.GetScreenWidth(), _CrtRender.GetScreenHeight(),32,fullscreen)) { return 0; } // Turn data dumping (debug) off //CrtBool dumpData = CrtFalse; // Initialize the renderer // !!!GAC for compatibility with the new COLLADA_FX code, Init now forces UsingCg and UsingVBOs to // !!!GAC false. It also calls CrtInitCg, creating the CG context and calling cgGLRegisterStates. // !!!GAC All these things are currently required for the cfx rendering path to work, changing them // !!!GAC may cause problems. This is work in progress and will be much cleaner when the refactor is done. _CrtRender.Init(); //_CrtRender.SetRenderDebug( CrtTrue ); // !!!GAC kept for reference, changing these may cause problems with the cfx include path //_CrtRender.SetUsingCg( CrtFalse ); // Turn off VBOs (the GL skinning path doesn't work with VBOs yet) _CrtRender.SetUsingVBOs( CrtTrue ); _CrtRender.SetUsingNormalMaps( CrtTrue ); //_CrtRender.SetRenderDebug( CrtTrue ); //_CrtRender.SetUsingShadowMaps(CrtTrue); // We might get a windows-style path on the command line, this can mess up the DOM which expects // all paths to be URI's. This block of code does some conversion to try and make the input // compliant without breaking the ability to accept a properly formatted URI. Right now this only // displays the first filename char file[512], *in = lpCmdLine, *out = file; *out = NULL; // If the first character is a ", skip it (filenames with spaces in them are quoted) if(*in == '\"') { in++; } if(*(in+1) == ':') { // Second character is a :, assume we have a path with a drive letter and add a slash at the beginning *(out++) = '/'; } int i; for(i =0; i<512; i++) { // If we hit a null or a quote, stop copying. This will get just the first filename. if(*in == NULL || *in == '\"') break; // Copy while swapping backslashes for forward ones if(*in == '\\') { *out = '/'; } else { *out = *in; } in++; out++; } // Should throw an error if i>= 512, but we don't have error dialongs in the code yet so just let it try to load and fail if(i < 511) *out = NULL; time_t seconds = time (NULL); clock_t clocka = clock (); cleaned_file_name = file; // Load the file name provided on the command line if ( !_CrtRender.Load( cleaned_file_name )) { exit(0); } time_t loadtime = time (NULL) - seconds; int clockload = (int) clock () - clocka; CrtPrint("\nLOAD TIME OF %s\n", file); CrtPrint("IS %d SECONDS\n", loadtime); CrtPrint("IS %d CLOCK TICKS\n\n", clockload); // This block of code shows how to enumerate all the effects, get their parameters and then // get their UI information. #if 1 { // Get the scene and setup to iterate over all the effects stored in the cfxLoader CrtScene *scene = _CrtRender.GetScene(); std::map<std::string, cfxEffect*>::iterator effectIterator; effectIterator = scene->cfxEffects.begin(); // Iterate over all the effects while(effectIterator != scene->cfxEffects.end()) { // This is the effect name you would use in a UI CrtPrint("Effect name %s\n", effectIterator->first.c_str()); cfxEffect *thiscfxEffect = effectIterator->second; CGeffect thisCGEffect = thiscfxEffect->getEffect(); CGparameter thisCGParameter = cgGetFirstEffectParameter(thisCGEffect); while(thisCGParameter != NULL) { // This is the parameter name you would use in the UI const char *parameterName = cgGetParameterName(thisCGParameter); // This is for the example of how to tweek a parameter (doesn't work yet) if(CrtCmp(parameterName, "Amplitude")) { // Capture the parameter and save it in a global, in a GUI you would // save this handle in the widget so it would know what to tweek. amplitudeGlobalParameter = thisCGParameter; } #if 0 // This is here for debugging, it iterates over all the annotations and prints them out // so you can see what's in them. Normally this code will be turned off. CrtPrint(" Parameter name %s\n",parameterName); CGannotation dbgCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); while(dbgCGAnnotation != NULL) { const char *annotationName = cgGetAnnotationName(dbgCGAnnotation); CrtPrint(" Annotation: %s",annotationName); if(cgGetAnnotationType(dbgCGAnnotation) == CG_STRING) { const char *annotationString = cgGetStringAnnotationValue(dbgCGAnnotation); CrtPrint(" value: %s\n",annotationString); } else if(cgGetAnnotationType(dbgCGAnnotation) == CG_FLOAT) { int nvalues; const float *value = cgGetFloatAnnotationValues(dbgCGAnnotation, &nvalues); CrtPrint(" value: %f\n",*value); // Assume there is one value } else { CrtPrint("\n"); } dbgCGAnnotation = cgGetNextAnnotation(dbgCGAnnotation); } #endif // This code looks at the parameter annotations to see if they specify some kind of UI // cgGetNamedParameterAnnotation isn't used for this because it is case sensitive and at // least some of the annotations FXcomposer uses for UI appear to NOT be case sensitive. // This method should collect the parameter values regardless of case, but it has to scan // ALL the parameters and do case-blind compares on each one, which is slower. // This code currently only collects the annotation values for defining sliders and color pickers. const char *UIName = "unknown"; const char *UIWidget = "unknown"; float UIMin = -99999.0f; float UIMax = 99999.0f; float UIStep = 0.0f; int nvalues; CGannotation thisCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); // Iterate over all the annotations while(thisCGAnnotation != NULL) { // Get the name of this annotation const char *annotationName = cgGetAnnotationName(thisCGAnnotation); // Do case-blind compares to see if the annotation is one of the ones used to make UI // and save the value if it is. if(CrtICmp("UIWidget",annotationName)) { // This is the widget type UIWidget = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIName",annotationName)) { // This is the name to attach to the widget UIName = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIMin",annotationName)) { // This is the minimum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMin = *value; } if(CrtICmp("UIMax",annotationName)) { // This is the maximum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMax = *value; } if(CrtICmp("UIStep",annotationName)) { // This is the step (minimum change) for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIStep = *value; } // Get the next annotation thisCGAnnotation = cgGetNextAnnotation(thisCGAnnotation); } // Is the UIWidget a type that we recognize? (just slider and color picker for now) // Replace the CrtPrint with the code that generates the UI, remember the UI needs to // store thisCGParameter someplace so it can use it to change the parameter later. if(CrtICmp("slider", UIWidget)) { CrtPrint("Parameter %s needs a slider named %s going from %f to %f with step %f\n",parameterName,UIName,UIMin,UIMax, UIStep ); } if(CrtICmp("color", UIWidget)) { CrtPrint("Parameter %s needs a color picker named %s\n",parameterName,UIName); } // Move on to the next parameter thisCGParameter = cgGetNextParameter(thisCGParameter); } // Move on to the next effect effectIterator++; } } #endif while(!done) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message==WM_QUIT) { done=TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received? { done=TRUE; } else { SwapBuffers(hDC); ProcessInput( keys ); } } } _CrtRender.Destroy(); // Shutdown #ifndef NO_DEVIL ilShutDown(); #endif DestroyGLWindow(); return (int)(msg.wParam); }
void csShaderGLCGCommon::DoDebugDump () { csString output; DumpProgramInfo (output); output << "CG program type: " << programType << "\n"; output << "CG profile: " << cgGetProgramString (program, CG_PROGRAM_PROFILE) << "\n"; output << "CG entry point: " << (entrypoint ? entrypoint : "main") << "\n"; output << "CG program valid: " << IsValid() << "\n"; output << "\n"; output << "Variable mappings:\n"; for (size_t v = 0; v < variablemap.GetSize (); v++) { const VariableMapEntry& vme = variablemap[v]; ShaderParameter* sparam = reinterpret_cast<ShaderParameter*> (vme.userVal); output << stringsSvName->Request (vme.name); output << '(' << vme.name << ") -> "; output << vme.destination << ' '; if (sparam == 0) { output << "(null)"; } else { if (sparam->paramType != 0) output << cgGetTypeString (sparam->paramType) << ' '; if (sparam->param != 0) output << cgGetParameterName (sparam->param) << " "; output << "baseslot " << sparam->baseSlot; if (sparam->assumeConstant) output << " assumed constant"; } output << '\n'; } output << "\n"; output << "Program leaf parameters:\n"; CGparameter param = cgGetFirstLeafParameter (program, CG_PROGRAM); while (param) { DebugDumpParam (output, param); param = cgGetNextLeafParameter (param); } output << "\n"; output << "Program global parameters:\n"; param = cgGetFirstLeafParameter (program, CG_GLOBAL); while (param) { DebugDumpParam (output, param); param = cgGetNextLeafParameter (param); } output << "\n"; output << "Program source:\n"; output << cgGetProgramString (program, CG_PROGRAM_SOURCE); output << "\n"; output << "Compiled program:\n"; output << cgGetProgramString (program, CG_COMPILED_PROGRAM); output << "\n"; csRef<iVFS> vfs = csQueryRegistry<iVFS> (objectReg); EnsureDumpFile(); csRef<iFile> debugFile = vfs->Open (debugFN, VFS_FILE_APPEND); if (!debugFile) { csReport (objectReg, CS_REPORTER_SEVERITY_WARNING, "crystalspace.graphics3d.shader.glcg", "Could not write %s", CS::Quote::Single (debugFN.GetData())); } else { debugFile->Write (output.GetData(), output.Length ()); csReport (objectReg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.graphics3d.shader.glcg", "Dumped Cg program info to %s", CS::Quote::Single (debugFN.GetData())); } }
void cgfxVaryingParameter::setupAttributes( cgfxRCPtr<cgfxVertexAttribute>& vertexAttributes, CGprogram program) { // Make sure our parameter name is acceptable is a Maya attribute name MString attrName = fName; int lastDot = attrName.rindex( '.'); if( lastDot >= 0) attrName = attrName.substring( lastDot + 1, attrName.length() - 1); MString semanticName = cgGetParameterSemantic( fParameter); MString semantic(semanticName); cgGetParameterSemantic( fParameter); semantic.toUpperCase(); // Is this varying parameter packed or atomic? CGtype type = cgGetNamedUserType( program, attrName.asChar()); if( type != CG_UNKNOWN_TYPE) { // It's packed: explode the inputs into the structure elements CGcontext context = cgGetProgramContext( program); CGparameter packing = cgCreateParameter( context, type); fVertexStructure = new cgfxVaryingParameterStructure(); fVertexStructure->fLength = 0; fVertexStructure->fSize = 0; CGparameter element = cgGetFirstStructParameter( packing); while( element) { MString elementName = cgGetParameterName( element); int lastDot = elementName.rindex( '.'); if( lastDot >= 0) elementName = elementName.substring( lastDot + 1, elementName.length() - 1); cgfxRCPtr<cgfxVertexAttribute> attr = setupAttribute( elementName, semantic, element, vertexAttributes); fVertexStructure->fElements[ fVertexStructure->fLength].fVertexAttribute = attr; int size = cgGetParameterRows( element) * cgGetParameterColumns( element); CGtype type = cgGetParameterBaseType( element); if( type == CG_FLOAT) size *= sizeof( GLfloat); else if( type == CG_INT) size *= sizeof( GLint); fVertexStructure->fElements[ fVertexStructure->fLength].fSize = size; fVertexStructure->fLength++; fVertexStructure->fSize += size; element = cgGetNextParameter( element); } cgDestroyParameter( packing); } else { // It's atomic - create a single, simple input fVertexAttribute = setupAttribute( attrName, semantic, fParameter, vertexAttributes); } // Now pull apart the semantic string to work out where to bind // this value in open GL (as the automagic binding through cgGL // didn't work so well when this was written) int radix = 1; fGLIndex = 0; unsigned int length = semantic.length(); const char* str = semantic.asChar(); // If sematic is NULL then stop here, bug 327649 if (length == 0) { fGLType = glRegister::kUnknown; return; } for(;;) { char c = str[ length - 1]; if( c < '0' || c > '9') break; fGLIndex += radix * (c - '0'); radix *= 10; --length; } if( semantic.length() != length) semantic = semantic.substring( 0, length - 1); // Determine the semantic and setup the gl binding type we should use // to set this parameter. If there's a sensible default value, set that // while we're here. // Note there is no need to set the source type, this gets determined // when the vertex attribute sources are analysed if( semantic == "POSITION") { fGLType = glRegister::kPosition; fVertexAttribute->fSourceName = "position"; } else if( semantic == "NORMAL") { fGLType = glRegister::kNormal; if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "normal"; } else if( semantic == "TEXCOORD") { fGLType = glRegister::kTexCoord; if( fVertexAttribute.isNull() == false ) { if( attrName.toLowerCase() == "tangent") fVertexAttribute->fSourceName = "tangent:map1"; else if( attrName.toLowerCase() == "binormal") fVertexAttribute->fSourceName = "binormal:map1"; else fVertexAttribute->fSourceName = "uv:map1"; } } else if( semantic == "TANGENT") { fGLType = glRegister::kTexCoord; fGLIndex += 6; // TANGENT is TEXCOORD6 if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "tangent:map1"; } else if( semantic == "BINORMAL") { fGLType = glRegister::kTexCoord; fGLIndex += 7; // BINORMAL is TEXCOORD7 if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "binormal:map1"; } else if( semantic == "COLOR") { fGLType = fGLIndex == 1 ? glRegister::kSecondaryColor : glRegister::kColor; } else if( semantic == "ATTR") { fGLType = glRegister::kVertexAttrib; if( fVertexAttribute.isNull() == false ) { fVertexAttribute->fSourceName = semanticName; } } else if( semantic == "PSIZE") { fGLType = glRegister::kVertexAttrib; fGLIndex = 6; } else { fGLType = glRegister::kUnknown; } }
//---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- int main(int LArgC, char** LArgV) { atexit(DestroyCrt); // Need this, because old GLUT never returns from glutMainLoop() // Create an OpenGL Window if (!CreateGLWindow(LArgC, LArgV, (char*)"COLLADA_DOM Sample Viewer", _CrtRender.GetScreenWidth(), _CrtRender.GetScreenHeight())) { return 0; } // Initialize the renderer // !!!GAC for compatibility with the new COLLADA_FX code, Init now forces UsingCg and UsingVBOs to // !!!GAC false. It also calls CrtInitCg, creating the CG context and calling cgGLRegisterStates. // !!!GAC All these things are currently required for the cfx rendering path to work, changing them // !!!GAC may cause problems. This is work in progress and will be much cleaner when the refactor is done. _CrtRender.Init(); _CrtRender.SetUsingVBOs( CrtTrue ); _CrtRender.SetUsingNormalMaps( CrtTrue ); // Load the file name provided on the command line if(LArgC > 1 && LArgV[1]) { printf("%s(): Loading %s...\n", __FUNCTION__, LArgV[1]); fflush(stdout); if ( !_CrtRender.Load( LArgV[1] )) { exit(0); } } else { printf("%s(): Loading default document cage.dae... \n", __FUNCTION__); fflush(stdout); if ( !_CrtRender.Load( "cage.dae" )) { exit(0); } } // This block of code shows how to enumerate all the effects, get their parameters and then // get their UI information. #if 1 if(_CrtRender.GetScene()) { // Get the scene and setup to iterate over all the effects stored in the cfxLoader CrtScene *scene = _CrtRender.GetScene(); std::map<std::string, cfxEffect*>::iterator effectIterator; effectIterator = scene->cfxEffects.begin(); // Iterate over all the effects while(effectIterator != scene->cfxEffects.end()) { // This is the effect name you would use in a UI CrtPrint("Effect name %s\n", effectIterator->first.c_str()); cfxEffect *thiscfxEffect = effectIterator->second; CGeffect thisCGEffect = thiscfxEffect->getEffect(); CGparameter thisCGParameter = cgGetFirstEffectParameter(thisCGEffect); while(thisCGParameter != NULL) { // This is the parameter name you would use in the UI const char *parameterName = cgGetParameterName(thisCGParameter); // This is for the example of how to tweek a parameter (doesn't work yet) if(CrtCmp(parameterName, "Amplitude")) { // Capture the parameter and save it in a global, in a GUI you would // save this handle in the widget so it would know what to tweek. amplitudeGlobalParameter = thisCGParameter; } #if 0 // This is here for debugging, it iterates over all the annotations and prints them out // so you can see what's in them. Normally this code will be turned off. CrtPrint(" Parameter name %s\n",parameterName); CGannotation dbgCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); while(dbgCGAnnotation != NULL) { const char *annotationName = cgGetAnnotationName(dbgCGAnnotation); CrtPrint(" Annotation: %s",annotationName); if(cgGetAnnotationType(dbgCGAnnotation) == CG_STRING) { const char *annotationString = cgGetStringAnnotationValue(dbgCGAnnotation); CrtPrint(" value: %s\n",annotationString); } else if(cgGetAnnotationType(dbgCGAnnotation) == CG_FLOAT) { int nvalues; const float *value = cgGetFloatAnnotationValues(dbgCGAnnotation, &nvalues); CrtPrint(" value: %f\n",*value); // Assume there is one value } else { CrtPrint("\n"); } dbgCGAnnotation = cgGetNextAnnotation(dbgCGAnnotation); } #endif // This code looks at the parameter annotations to see if they specify some kind of UI // cgGetNamedParameterAnnotation isn't used for this because it is case sensitive and at // least some of the annotations FXcomposer uses for UI appear to NOT be case sensitive. // This method should collect the parameter values regardless of case, but it has to scan // ALL the parameters and do case-blind compares on each one, which is slower. // This code currently only collects the annotation values for defining sliders and color pickers. const char *UIName = "unknown"; const char *UIWidget = "unknown"; float UIMin = -99999.0f; float UIMax = 99999.0f; float UIStep = 0.0f; int nvalues; CGannotation thisCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); // Iterate over all the annotations while(thisCGAnnotation != NULL) { // Get the name of this annotation const char *annotationName = cgGetAnnotationName(thisCGAnnotation); // Do case-blind compares to see if the annotation is one of the ones used to make UI // and save the value if it is. if(CrtICmp("UIWidget",annotationName)) { // This is the widget type UIWidget = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIName",annotationName)) { // This is the name to attach to the widget UIName = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIMin",annotationName)) { // This is the minimum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMin = *value; } if(CrtICmp("UIMax",annotationName)) { // This is the maximum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMax = *value; } if(CrtICmp("UIStep",annotationName)) { // This is the step (minimum change) for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIStep = *value; } // Get the next annotation thisCGAnnotation = cgGetNextAnnotation(thisCGAnnotation); } // Is the UIWidget a type that we recognize? (just slider and color picker for now) // Replace the CrtPrint with the code that generates the UI, remember the UI needs to // store thisCGParameter someplace so it can use it to change the parameter later. if(CrtICmp("slider", UIWidget)) { CrtPrint("Parameter %s needs a slider named %s going from %f to %f with step %f\n",parameterName,UIName,UIMin,UIMax, UIStep ); } if(CrtICmp("color", UIWidget)) { CrtPrint("Parameter %s needs a color picker named %s\n",parameterName,UIName); } // Move on to the next parameter thisCGParameter = cgGetNextParameter(thisCGParameter); } // Move on to the next effect effectIterator++; } } #endif glutMainLoop(); return(0); }
static int PubCGparam_func (PState pstate,PubFunction_t *fn, int n) { CGparameter cgparam = NULL; if ((int)fn->upvalue > PCG_GET && (n<1 || FunctionPublish_getArg(pstate,1,LUXI_CLASS_CGPARAM,(void*)&cgparam)<1)) return FunctionPublish_returnError(pstate,"1 cgparam required"); switch((int)fn->upvalue){ case PCG_NEW: { char *name; char *nametype; CGtype cgtype; CGtype basetype; int cnt = 1; if (n < 2 || FunctionPublish_getArg(pstate,3,LUXI_CLASS_STRING,(void*)&name,LUXI_CLASS_STRING,(void*)&nametype,LUXI_CLASS_INT,(void*)&cnt)<2) return FunctionPublish_returnError(pstate,"2 strings required"); cgtype = cgGetType(nametype); basetype = cgGetTypeBase(cgtype); if (VIDCg_getConnector(name) || cgtype==CG_UNKNOWN_TYPE || (basetype != CG_FLOAT && basetype != CG_INT && basetype != CG_BOOL)) return FunctionPublish_returnError(pstate,"name already in use, or illegal cg base type (float, bool, int)"); if (cgGetTypeClass(cgtype) == CG_PARAMETERCLASS_MATRIX && basetype != CG_FLOAT) return FunctionPublish_returnError(pstate,"only float matrix parameters allowed"); cgparam = cnt > 1 ? cgCreateParameterArray(g_VID.cg.context,cgtype,cnt) : cgCreateParameter(g_VID.cg.context,cgtype); VIDCg_setConnector(name,cgparam); return FunctionPublish_returnType(pstate,LUXI_CLASS_CGPARAM,(void*)cgparam); } break; case PCG_DELETE: { int linked = cgGetNumConnectedToParameters(cgparam); if (linked == 0){ VIDCg_setConnector(cgGetParameterName(cgparam),NULL); cgDestroyParameter(cgparam); } return FunctionPublish_returnInt(pstate,linked); } break; case PCG_GET: { char *name; if (n < 1 || !FunctionPublish_getArg(pstate,1,LUXI_CLASS_STRING,(void*)&name)) return FunctionPublish_returnError(pstate,"1 string required"); cgparam = VIDCg_getConnector(name); if (cgparam) return FunctionPublish_returnType(pstate,LUXI_CLASS_CGPARAM,(void*)cgparam); else return 0; } break; case PCG_VALUE: { CGtype cgtype = cgGetParameterType(cgparam); CGtype basetype = cgGetTypeBase(cgtype); CGtype classtype = cgGetTypeClass(cgtype); lxClassType ctype; Reference ref; float *matrix; StaticArray_t *starray; int read = 0; int offset = 0; int size; int into = (int)fn->upvalue == PCG_VALUEINTO; if (n==1 || into){ int vector[4]; switch(classtype){ case CG_PARAMETERCLASS_SCALAR: case CG_PARAMETERCLASS_VECTOR: switch(basetype){ case CG_FLOAT: ctype = LUXI_CLASS_FLOAT; read = cgGetParameterValuefc(cgparam,4,(float*)vector); break; case CG_BOOL: ctype = LUXI_CLASS_BOOLEAN; read = cgGetParameterValueic(cgparam,4,vector); break; case CG_INT: ctype = LUXI_CLASS_INT; read = cgGetParameterValueic(cgparam,4,vector); break; default: return 0; } return FunctionPublish_setRet(pstate,read,ctype,(void*)vector[0],ctype,(void*)vector[1],ctype,(void*)vector[2],ctype,(void*)vector[3]); break; case CG_PARAMETERCLASS_MATRIX: if (into){ // get matrix first if (!FunctionPublish_getNArg(pstate,1,LUXI_CLASS_MATRIX44,(void*)&ref) || !Reference_get(ref,matrix)) return FunctionPublish_returnError(pstate,"1 matrix4x4 required"); } else{ // create matrix matrix = PubMatrix4x4_alloc(); ref = Reference_new(LUXI_CLASS_MATRIX44,matrix); Reference_makeVolatile(ref); } cgGetMatrixParameterfc(cgparam,matrix); return FunctionPublish_returnType(pstate,LUXI_CLASS_MATRIX44,REF2VOID(ref)); break; case CG_PARAMETERCLASS_ARRAY: ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOATARRAY : LUXI_CLASS_INTARRAY; size = cgGetParameterColumns(cgparam)*cgGetParameterRows(cgparam)*cgGetArrayTotalSize(cgparam); if (into){ // get array first if (FunctionPublish_getArgOffset(pstate,1,3,ctype,(void*)&ref,LUXI_CLASS_INT,(void*)&offset)<1 || !Reference_get(ref,starray) || offset+size > starray->count) return FunctionPublish_returnError(pstate,"1 staticarray [1 int] required (with enough space)"); } else{ // create array starray = StaticArray_new(size,ctype,NULL,NULL); } offset = LUX_MIN(offset,(starray->count-1)); read = LUX_MIN(read,(starray->count-offset)); if (ctype == LUXI_CLASS_FLOATARRAY) cgGetParameterValuefc(cgparam,read,starray->floats); else cgGetParameterValueic(cgparam,read,starray->ints); return FunctionPublish_returnType(pstate,ctype,REF2VOID(starray->ref)); } } else { // set lxVector4 vector; switch(classtype){ case CG_PARAMETERCLASS_SCALAR: case CG_PARAMETERCLASS_VECTOR: ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOAT : LUXI_CLASS_INT; read = FunctionPublish_getArgOffset(pstate,1,n-1,ctype,(void*)&vector[0],ctype,(void*)&vector[1],ctype,(void*)&vector[2],ctype,(void*)&vector[3]); if (read > 0){ switch(basetype){ case CG_FLOAT: cgSetParameterValuefc(cgparam,n-1,vector); return 0; case CG_BOOL: case CG_INT: cgSetParameterValueic(cgparam,n-1,(int*)vector); return 0; default: return 0; } } break; case CG_PARAMETERCLASS_MATRIX: if (!FunctionPublish_getNArg(pstate,1,LUXI_CLASS_MATRIX44,(void*)&ref) || !Reference_get(ref,matrix)) return FunctionPublish_returnError(pstate,"1 matrix4x4 required"); cgSetMatrixParameterfc(cgparam,matrix); return 0; case CG_PARAMETERCLASS_ARRAY: ctype = basetype == CG_FLOAT ? LUXI_CLASS_FLOATARRAY : LUXI_CLASS_INTARRAY; size = cgGetParameterColumns(cgparam)*cgGetParameterRows(cgparam)*cgGetArrayTotalSize(cgparam); if (FunctionPublish_getArgOffset(pstate,1,3,ctype,(void*)&ref,LUXI_CLASS_INT,(void*)&offset) || !Reference_get(ref,starray) || offset+size > starray->count) return FunctionPublish_returnError(pstate,"1 staticarray [2 ints] required, with enough space"); offset = LUX_MIN(offset,(starray->count-1)); if (ctype == LUXI_CLASS_FLOATARRAY) cgSetParameterValuefc(cgparam,size,&starray->floats[offset]); else cgSetParameterValueic(cgparam,size,&starray->ints[offset]); return 0; default: return 0; } } } case PCG_SIZES: return FunctionPublish_setRet(pstate,3,LUXI_CLASS_INT,(void*)cgGetParameterColumns(cgparam),LUXI_CLASS_INT,(void*)cgGetParameterRows(cgparam),LUXI_CLASS_INT,(void*)cgGetArrayTotalSize(cgparam)); default: break; } return 0; }