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; }
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; }
static void set_program_base_attrib(unsigned i) { CGparameter param = cgGetFirstParameter(prg[i].vprg, CG_PROGRAM); for (; param; param = cgGetNextParameter(param)) { if (cgGetParameterDirection(param) != CG_IN || cgGetParameterVariability(param) != CG_VARYING) continue; const char *semantic = cgGetParameterSemantic(param); if (!semantic) continue; RARCH_LOG("CG: Found semantic \"%s\" in prog #%u.\n", semantic, i); if (strcmp(semantic, "TEXCOORD") == 0 || strcmp(semantic, "TEXCOORD0") == 0) prg[i].tex = param; else if (strcmp(semantic, "COLOR") == 0 || strcmp(semantic, "COLOR0") == 0) prg[i].color = param; else if (strcmp(semantic, "POSITION") == 0) prg[i].vertex = param; else if (strcmp(semantic, "TEXCOORD1") == 0) prg[i].lut_tex = param; } if (!prg[i].tex) prg[i].tex = cgGetNamedParameter(prg[i].vprg, "IN.tex_coord"); if (!prg[i].color) prg[i].color = cgGetNamedParameter(prg[i].vprg, "IN.color"); if (!prg[i].vertex) prg[i].vertex = cgGetNamedParameter(prg[i].vprg, "IN.vertex_coord"); if (!prg[i].lut_tex) prg[i].lut_tex = cgGetNamedParameter(prg[i].vprg, "IN.lut_tex_coord"); }
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); } }
static void gl_cg_set_program_base_attrib(void *data, unsigned i) { cg_shader_data_t *cg = (cg_shader_data_t*)data; CGparameter param = cgGetFirstParameter( cg->prg[i].vprg, CG_PROGRAM); for (; param; param = cgGetNextParameter(param)) { uint32_t semantic_hash; const char *semantic = NULL; if (cgGetParameterDirection(param) != CG_IN || cgGetParameterVariability(param) != CG_VARYING) continue; semantic = cgGetParameterSemantic(param); if (!semantic) continue; RARCH_LOG("CG: Found semantic \"%s\" in prog #%u.\n", semantic, i); semantic_hash = djb2_calculate(semantic); switch (semantic_hash) { case SEMANTIC_TEXCOORD: case SEMANTIC_TEXCOORD0: cg->prg[i].tex = param; break; case SEMANTIC_COLOR: case SEMANTIC_COLOR0: cg->prg[i].color = param; break; case SEMANTIC_POSITION: cg->prg[i].vertex = param; break; case SEMANTIC_TEXCOORD1: cg->prg[i].lut_tex = param; break; } } if (!cg->prg[i].tex) cg->prg[i].tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.tex_coord"); if (!cg->prg[i].color) cg->prg[i].color = cgGetNamedParameter(cg->prg[i].vprg, "IN.color"); if (!cg->prg[i].vertex) cg->prg[i].vertex = cgGetNamedParameter(cg->prg[i].vprg, "IN.vertex_coord"); if (!cg->prg[i].lut_tex) cg->prg[i].lut_tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.lut_tex_coord"); }
/* 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); } }
static void gl_cg_set_program_base_attrib(void *data, unsigned i) { cg_shader_data_t *cg = (cg_shader_data_t*)data; CGparameter param = cgGetFirstParameter( cg->prg[i].vprg, CG_PROGRAM); for (; param; param = cgGetNextParameter(param)) { const char *semantic = NULL; if ( (cgGetParameterDirection(param) != CG_IN) || (cgGetParameterVariability(param) != CG_VARYING)) continue; semantic = cgGetParameterSemantic(param); if (!semantic) continue; RARCH_LOG("[CG]: Found semantic \"%s\" in prog #%u.\n", semantic, i); if ( string_is_equal(semantic, "TEXCOORD") || string_is_equal(semantic, "TEXCOORD0") ) cg->prg[i].tex = param; else if ( string_is_equal(semantic, "COLOR") || string_is_equal(semantic, "COLOR0") ) cg->prg[i].color = param; else if (string_is_equal(semantic, "POSITION")) cg->prg[i].vertex = param; else if (string_is_equal(semantic, "TEXCOORD1")) cg->prg[i].lut_tex = param; } if (!cg->prg[i].tex) cg->prg[i].tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.tex_coord"); if (!cg->prg[i].color) cg->prg[i].color = cgGetNamedParameter(cg->prg[i].vprg, "IN.color"); if (!cg->prg[i].vertex) cg->prg[i].vertex = cgGetNamedParameter(cg->prg[i].vprg, "IN.vertex_coord"); if (!cg->prg[i].lut_tex) cg->prg[i].lut_tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.lut_tex_coord"); }
// ========== cgfxEffect::attrsFromEffect ========== // // This function parses through an effect and builds a list of // cgfxAttrDef objects. // cgfxRCPtr<cgfxAttrDefList> cgfxEffect::attrsFromEffect() const { if (!fEffect) return cgfxRCPtr<cgfxAttrDefList>(); cgfxRCPtr<cgfxAttrDefList> list(new cgfxAttrDefList); CGparameter cgParameter = cgGetFirstEffectParameter(fEffect); int i = 0; while (cgParameter) { cgfxAttrDef* aDef = new cgfxAttrDef(cgParameter); list->add(aDef); cgParameter = cgGetNextParameter(cgParameter); ++i; } // end of for each parameter return list; }
cgfxPass::cgfxPass( CGpass pass, const cgfxProfile* profile ) : fPass( pass), fProgram( NULL), fParameters( NULL), fDefaultProfile("default", pass), fNext( NULL) { if( pass) { fName = cgGetPassName( pass); CGstateassignment stateAssignment = cgGetFirstStateAssignment( pass); cgfxVaryingParameter** nextParameter = &fParameters; while( stateAssignment ) { CGstate state = cgGetStateAssignmentState( stateAssignment); if( cgGetStateType( state) == CG_PROGRAM_TYPE && ( stricmp( cgGetStateName( state), "vertexProgram") == 0 || stricmp( cgGetStateName( state), "vertexShader") == 0)) { fProgram = cgGetProgramStateAssignmentValue( stateAssignment); if( fProgram) { CGparameter parameter = cgGetFirstParameter( fProgram, CG_PROGRAM); while( parameter) { cgfxVaryingParameter::addRecursive( parameter, nextParameter); parameter = cgGetNextParameter( parameter); } } } setProfile(profile); stateAssignment = cgGetNextStateAssignment( stateAssignment); } } }
inline void cgfxVaryingParameter::addRecursive( CGparameter parameter, cgfxVaryingParameter**& nextParameter ) { if( cgGetParameterVariability( parameter) == CG_VARYING) { if( cgGetParameterType( parameter) == CG_STRUCT) { CGparameter input = cgGetFirstStructParameter( parameter); while( input) { addRecursive( input, nextParameter); input = cgGetNextParameter( input); } } else if( cgIsParameterReferenced( parameter)) { *nextParameter = new cgfxVaryingParameter( parameter); nextParameter = &(*nextParameter)->fNext; } } }
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); } }
void CCgMaterialRenderer::getUniformList() { for(unsigned int i = 0; i < UniformInfo.size(); ++i) delete UniformInfo[i]; UniformInfo.clear(); for(unsigned int i = 0; i < 2; ++i) { CGenum Space = CG_GLOBAL; bool IsGlobal = 1; if(i == 1) { Space = CG_PROGRAM; IsGlobal = 0; } for(unsigned int j = 0; j < 3; ++j) { CGprogram* Program = 0; switch(j) { case 0: Program = &VertexProgram; break; case 1: Program = &FragmentProgram; break; case 2: Program = &GeometryProgram; break; } if(*Program) { CGparameter Parameter = cgGetFirstParameter(*Program, Space); while(Parameter) { if(cgGetParameterVariability(Parameter) == CG_UNIFORM && cgGetParameterDirection(Parameter) == CG_IN) { CCgUniform* Uniform = 0; CGtype Type = cgGetParameterType(Parameter); switch(Type) { case CG_FLOAT: case CG_FLOAT1: Uniform = new CCgUniform1f(Parameter, IsGlobal); break; case CG_FLOAT2: Uniform = new CCgUniform2f(Parameter, IsGlobal); break; case CG_FLOAT3: Uniform = new CCgUniform3f(Parameter, IsGlobal); break; case CG_FLOAT4: Uniform = new CCgUniform4f(Parameter, IsGlobal); break; case CG_INT: case CG_INT1: Uniform = new CCgUniform1i(Parameter, IsGlobal); break; case CG_INT2: Uniform = new CCgUniform2i(Parameter, IsGlobal); break; case CG_INT3: Uniform = new CCgUniform3i(Parameter, IsGlobal); break; case CG_INT4: Uniform = new CCgUniform4i(Parameter, IsGlobal); break; case CG_FLOAT4x4: Uniform = new CCgUniform4x4f(Parameter, IsGlobal); break; case CG_SAMPLER2D: Uniform = new CCgUniformSampler2D(Parameter, IsGlobal); break; } if(Uniform) UniformInfo.push_back(Uniform); } Parameter = cgGetNextParameter(Parameter); } } } } }
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); }
bool CgShaderProgramGL::setConstant(const io::stringc &Name, const f32* Buffer, s32 Count) { if (!Buffer) return false; /* Get top-level parameter */ CGparameter Param = cgGetNamedParameter(cgProgram_, Name.c_str()); if (!Param) return false; /* Get array parameter */ if (cgGetParameterType(Param) != CG_ARRAY) return false; s32 ArraySize = cgGetArraySize(Param, 0); for (s32 i = 0; i < ArraySize; ++i) { /* Get array element parameter */ CGparameter ElementParam = cgGetArrayParameter(Param, i); switch (cgGetParameterType(ElementParam)) { case CG_FLOAT: cgGLSetParameterArray1f(Param, 0, Count, Buffer); return true; case CG_FLOAT2: cgGLSetParameterArray2f(Param, 0, Count/2, Buffer); return true; case CG_FLOAT3: cgGLSetParameterArray3f(Param, 0, Count/3, Buffer); return true; case CG_FLOAT4: cgGLSetParameterArray4f(Param, 0, Count/4, Buffer); return true; case CG_FLOAT4x4: cgGLSetMatrixParameterArrayfc(Param, 0, Count/16, Buffer); return true; case CG_STRUCT: { /* Get structure field parameter */ CGparameter FieldParam = cgGetFirstStructParameter(ElementParam); while (FieldParam) { switch (cgGetParameterType(FieldParam)) { case CG_FLOAT: cgGLSetParameter1f(FieldParam, *Buffer); Buffer += 1; break; case CG_FLOAT2: cgGLSetParameter2fv(FieldParam, Buffer); Buffer += 2; break; case CG_FLOAT3: cgGLSetParameter3fv(FieldParam, Buffer); Buffer += 3; break; case CG_FLOAT4: cgGLSetParameter4fv(FieldParam, Buffer); Buffer += 4; break; case CG_FLOAT4x4: cgGLSetMatrixParameterfc(FieldParam, Buffer); Buffer += 16; break; case CG_INT: cgSetParameter1i(FieldParam, *((s32*)Buffer)); Buffer += 1; break; default: break; } FieldParam = cgGetNextParameter(FieldParam); } } break; default: break; } } return true; }
//--------------------------------------------------------------------- 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); } }
//---------------------------------------------------------------------------------------------------- // 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); }