void CompositeMat::PreShade(ShadeContext& sc, IReshadeFragment* pFrag) { int i(0); Mtl *submtl = NULL; // BOOL enabled(FALSE); char texLengths[12]; int lengthChan = pFrag->NTextures(); pFrag->AddIntChannel(0); pFrag->AddIntChannel(0); pFrag->AddIntChannel(0); int nPrevTex = 3 + lengthChan; // preshade any submaterials for (i=0; i<MAX_NUM_MTLS; i++) { pblock2->GetValue(compmat_mtls, sc.CurTime(), submtl, FOREVER, i); if (submtl){ IReshading* pReshading = (IReshading*)(submtl->GetInterface(IID_IReshading)); if( pReshading ){ pReshading->PreShade(sc, pFrag); int nTex = pFrag->NTextures(); texLengths[i] = char( nTex - nPrevTex); nPrevTex = nTex; } } } int* pI = (int*)&texLengths[0]; pFrag->SetIntChannel( lengthChan++, pI[0] ); pFrag->SetIntChannel( lengthChan++, pI[1] ); pFrag->SetIntChannel( lengthChan, pI[2] ); }
/** * @brief * Creates a material */ PLSceneMaterial *PLSceneMaterial::Create(PLScene &cScene, IGameMaterial *pParentIGameMaterial, IGameMaterial &cIGameMaterial, const String &sName) { // Get the 3ds Max material... I don't use IGame for this because I didn't get it working using it... Mtl *pMaxMaterial = cIGameMaterial.GetMaxMaterial(); if (pMaxMaterial) { // DxMaterial or extend? IDxMaterial2 *pFXMaterial = static_cast<IDxMaterial2*>(pMaxMaterial->GetInterface(IDXMATERIAL2_INTERFACE)); if (!pFXMaterial && pParentIGameMaterial) pFXMaterial = static_cast<IDxMaterial2*>(pParentIGameMaterial->GetMaxMaterial()->GetInterface(IDXMATERIAL2_INTERFACE)); if (pFXMaterial) { // Get information from the DirectX Shader material // Get effect filename #if MAX_RELEASE >= 12000 // For R12 release Url cUrl = pFXMaterial->GetEffectFile().GetFullFilePath().data(); #else Url cUrl = pFXMaterial->GetEffectFilename(); #endif String sEffectFilenameName = cUrl.GetFilename(); // Our effect? if (sEffectFilenameName == "PixelLight_SRShaderLighting.fx") return new PLSceneMaterialSRShaderLighting(cScene, pParentIGameMaterial, cIGameMaterial, sName); else return new PLSceneMaterialFX(cScene, pParentIGameMaterial, cIGameMaterial, sName); } else { // Is this a shell material used for 'backed texture'? if (pMaxMaterial->ClassID() == Class_ID(BAKE_SHELL_CLASS_ID, 0)) return new PLSceneMaterialBakeShell(cScene, pParentIGameMaterial, cIGameMaterial, sName); else return new PLSceneMaterialStandard(cScene, pParentIGameMaterial, cIGameMaterial, sName); } } // Error! return nullptr; }
void M3Mat::PreShade(ShadeContext& sc, IReshadeFragment* pFrag) { int i; IReshading* pReshading; TimeValue t = sc.CurTime(); Interval valid = FOREVER; // get the base material value into i pblockMat->GetValue(100, t, i, valid ); Mtl *sm1 = mTex[100]; // handle no base mat if(sm1 == NULL) { return; } if(i==0||(i==1&&inRender)) { for( i=0;i<100;i++) { float u; pblockMat->GetValue(i,t,u,valid); if(mTex[i]!=NULL && u!=0 && mapOn[i]) { Mtl *comb = mTex[i]; pReshading = (IReshading*)(comb->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PreShade(sc, pFrag); } } pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PreShade(sc, pFrag); } else { // i == 1 && not inRender pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PreShade(sc, pFrag); } }
void CompositeMat::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* ) { int i(0), type(2); Mtl* submtl = NULL; BOOL enabled(TRUE); ShadeOutput out1, out2; float amount(100.0f); // , gamount(0.0f); char texLengths[12]; int* pI = (int*)&texLengths[0]; pI[0] = pFrag->GetIntChannel(nextTexIndex++); pI[1] = pFrag->GetIntChannel(nextTexIndex++); pI[2] = pFrag->GetIntChannel(nextTexIndex++); // postshade any submaterials for ( i=0; i<MAX_NUM_MTLS; i++) { if( i>0 ) pblock2->GetValue(compmat_map_on, sc.CurTime(), enabled, FOREVER, i-1); else enabled = TRUE; pblock2->GetValue(compmat_mtls, sc.CurTime(), submtl, FOREVER, i); if ( enabled && submtl ){ if( i > 0 ){ pblock2->GetValue(compmat_amount, sc.CurTime(), amount, FOREVER, i-1); pblock2->GetValue(compmat_type, sc.CurTime(), type, FOREVER, i-1); } amount = amount * 0.01f; sc.ResetOutput(); IReshading* pReshading = (IReshading*)(submtl->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PostShade(sc, pFrag, nextTexIndex); // first check for base material if( i > 0 ) { // not base material, composite the next material out2 = sc.out; if (type == 0) // additive { out2.t.r += 1.0f-amount; out2.t.g += 1.0f-amount; out2.t.b += 1.0f-amount; out2.c *= amount; out2.t.ClampMinMax(); out2.ior *= amount; float f1 = 1.0f - (out1.t.r + out1.t.g + out1.t.b) / 3.0f; float f2 = 1.0f - (out2.t.r + out2.t.g + out2.t.b) / 3.0f; out1.c = out1.c * (1.0f-f2) + out2.c * f1; out1.t = out1.t - (1.0f-out2.t); out1.ior = out1.ior + out2.ior; out1.t.ClampMinMax(); } else if (type == 1) // subtractive { out2.t.r += 1.0f-amount; out2.t.g += 1.0f-amount; out2.t.b += 1.0f-amount; out2.c *= amount; out2.t.ClampMinMax(); out2.ior *= amount; float f1 = 1.0f - (out1.t.r + out1.t.g + out1.t.b) / 3.0f; float f2 = 1.0f - (out2.t.r + out2.t.g + out2.t.b) / 3.0f; out1.c = out1.c * (1.0f-f2) - out2.c * f1; out1.t = out1.t - (1.0f-out2.t); out1.ior = out1.ior + out2.ior; out1.t.ClampMinMax(); } else //mix { out1.MixIn(out2, 1.0f-amount); } }// end, not base mtl else { // base material. out1 = sc.out; out1.ior *= amount; } }// end, if has submtl & enabled else { nextTexIndex += texLengths[i]; } }// end, for each mtl sc.out = out1; }
//---------------------------------------------------------------------------- void SceneBuilder::ConvertMaterial (Mtl &mtl, MtlTree &mtlTree) { // 光照属性 PX2::Shine *shine = new0 PX2::Shine; Color color = mtl.GetAmbient(); float alpha = 1.0f - mtl.GetXParency(); shine->Ambient = PX2::Float4(color.r, color.g, color.b, 1.0f); color = mtl.GetDiffuse(); shine->Diffuse = PX2::Float4(color.r, color.g, color.b, alpha); color = mtl.GetSpecular(); float shininess = mtl.GetShininess()*2.0f; shine->Specular = PX2::Float4(color.r, color.g, color.b, shininess); const char *name = (const char*)mtl.GetName(); shine->SetName(name); mtlTree.SetShine(shine); bool IsDirect9Shader = false; if (mtl.ClassID() == Class_ID(CMTL_CLASS_ID, 0) || mtl.ClassID() == Class_ID(DMTL_CLASS_ID, 0)) { StdMat2 *stdMat2 = (StdMat2*)(&mtl); Interval valid = FOREVER; stdMat2->Update(mTimeStart, valid); std::string strName(stdMat2->GetName()); bool doubleSide = (stdMat2->GetTwoSided()==1); char strBitMapName[256]; memset(strBitMapName, 0, 256*sizeof(char)); std::string resourcePath; PX2::Shader::SamplerFilter filter = PX2::Shader::SF_LINEAR_LINEAR; PX2::Shader::SamplerCoordinate uvCoord = PX2::Shader::SC_REPEAT; PX2_UNUSED(uvCoord); if (stdMat2->MapEnabled(ID_DI)) { BitmapTex *tex = (BitmapTex*)stdMat2->GetSubTexmap(ID_DI); BitmapInfo bI; const char *mapName = tex->GetMapName(); TheManager->GetImageInfo(&bI, mapName); strcpy(strBitMapName, bI.Name()); std::string fullName = std::string(strBitMapName); std::string::size_type sizeT = fullName.find_first_not_of(mSettings->SrcRootDir); resourcePath = std::string(strBitMapName).substr(sizeT); StdUVGen* uvGen = tex->GetUVGen(); PX2_UNUSED(uvGen); int filType = tex->GetFilterType(); switch (filType) { case FILTER_PYR: filter = PX2::Shader::SF_LINEAR_LINEAR; break; case FILTER_SAT: filter = PX2::Shader::SF_NEAREST; break; default: break; } } else { sprintf(strBitMapName, "%s/%s", mSettings->SrcRootDir, PX2_DEFAULT_TEXTURE); resourcePath = PX2_DEFAULT_TEXTURE; } PX2::Texture2D *tex2d = PX2::DynamicCast<PX2::Texture2D>( PX2::ResourceManager::GetSingleton().BlockLoad(strBitMapName)); tex2d->SetResourcePath(resourcePath); if (tex2d) { PX2::Texture2DMaterial *tex2dMtl = new0 PX2::Texture2DMaterial(filter, uvCoord, uvCoord); if (doubleSide) { tex2dMtl->GetCullProperty(0, 0)->Enabled = false; } PX2::MaterialInstance *instance = tex2dMtl->CreateInstance(tex2d); mtlTree.SetMaterialInstance(instance); } else { PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material(); PX2::MaterialInstance *instance = vcMtl->CreateInstance(); mtlTree.SetMaterialInstance(instance); } } else if (mtl.ClassID() == Class_ID(MULTI_CLASS_ID, 0)) { } else if (mtl.ClassID() == DIRECTX_9_SHADER_CLASS_ID) { IsDirect9Shader = true; IDxMaterial* dxMtl = (IDxMaterial*)mtl.GetInterface(IDXMATERIAL_INTERFACE); char *effectName = dxMtl->GetEffectFilename(); IParamBlock2 *paramBlock = mtl.GetParamBlock(0); std::string outPath; std::string outBaseName; std::string outExtention; PX2::StringHelp::SplitFullFilename(effectName, outPath, outBaseName, outExtention); PX2::ShinePtr shineStandard = new0 PX2::Shine(); bool alphaVertex = false; PX2::Texture2DPtr diffTex; bool normalEnable = false; PX2::Texture2DPtr normalTex; float normalScale = 0.0f; bool specEnable = false; PX2::Texture2DPtr specTex; float specPower = 0.0f; bool reflectEnable = false; PX2::TextureCubePtr reflectTex; float reflectPower = 0.0f; bool doubleSide = false; int blendMode = 2; ParamBlockDesc2 *paramDesc = 0; int numParam = 0; if (paramBlock) { paramDesc = paramBlock->GetDesc(); numParam = paramBlock->NumParams(); ParamType2 paramType; for (int i=0; i<numParam; i++) { std::string parmName; PX2::Float4 color4 = PX2::Float4(0.0f, 0.0f, 0.0f, 0.0f); PX2::Float3 color3 = PX2::Float3(0.0f, 0.0f, 0.0f); float floatValue = 0.0f; bool boolValue = false; float *floatTable = 0; int intValue = 0; std::string str; PX2::Texture2D *tex2d = 0; paramType = paramBlock->GetParameterType((ParamID)i); if (TYPE_STRING == paramType) ConvertStringAttrib(paramBlock, i, parmName, str); else if (TYPE_FLOAT == paramType) ConvertFloatAttrib(paramBlock, i, parmName, floatValue); else if (TYPE_INT == paramType) ConvertIntAttrib(paramBlock, i, parmName, intValue); else if (TYPE_RGBA == paramType) ConvertColorAttrib(paramBlock, i, parmName, color4, i); else if (TYPE_POINT3 == paramType) ConvertPoint3Attrib(paramBlock, i, parmName, color3); else if (TYPE_POINT4 == paramType) ConvertPoint4Attrib(paramBlock, i, parmName, color4); else if (TYPE_BOOL == paramType) ConvertBoolAttrib(paramBlock, i, parmName, boolValue); else if (TYPE_FLOAT_TAB == paramType) ConvertFloatTabAttrib(paramBlock, i, parmName, floatTable); else if (TYPE_BITMAP == paramType) ConvertBitMapAttrib(paramBlock, i, parmName, tex2d); else if (TYPE_FRGBA ==paramType) ConvertFRGBAAttrib(paramBlock, i, parmName, color4); // shine if (parmName == "gBlendMode") { blendMode = intValue; } else if (parmName == "gShineEmissive") { shineStandard->Emissive = color4; } else if (parmName == "gShineAmbient") { shineStandard->Ambient = color4; } else if (parmName == "gShineDiffuse") { shineStandard->Diffuse = color4; } // alpha vertex else if (parmName == "gAlphaVertex") { alphaVertex = boolValue; } // diffuse else if (parmName == "gDiffuseTexture") { diffTex = tex2d; } // normal else if (parmName == "gNormalEnable") { normalEnable = boolValue; } else if (parmName == "gNormalTexture") { normalTex = tex2d; } else if (parmName == "gNormalScale") { normalScale = floatValue; } // specular else if (parmName == "gSpecularEnable") { specEnable = boolValue; } else if (parmName == "gSpecularTexture") { specTex = tex2d; } else if (parmName == "gSpecularPower") { specPower = floatValue; } // reflect else if (parmName == "gReflectionEnable") { reflectEnable = boolValue; } else if (parmName == "gReflectTexture") { //reflectTex = tex2d; } else if (parmName == "gReflectPower") { reflectPower = floatValue; } // other else if (parmName == "gDoubleSide") { doubleSide = boolValue; } } } PX2::MaterialInstance *inst = 0; PX2::StandardMaterial *standardMtl = 0; PX2::StandardESMaterial_Default *standardESMtl_D = 0; PX2::StandardESMaterial_Specular *standardESMtl_S = 0; if (outBaseName == "Standard") { char mtlName[256]; memset(mtlName, 0, 256*sizeof(char)); sprintf(mtlName, "%s/%s", mSettings->DstRootDir, "Data/mtls/Standard.pxfx"); standardMtl = new0 PX2::StandardMaterial(mtlName); } else if (outBaseName == "StandardES") { if (false == specEnable) { standardESMtl_D = new0 PX2::StandardESMaterial_Default(); if (0 == blendMode) { standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false; standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = false; } else if (1 == blendMode) { standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = true; } else if (2 == blendMode) { standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false; standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = true; standardESMtl_D->GetAlphaProperty(0, 0)->Compare = PX2::AlphaProperty::CM_GEQUAL; standardESMtl_D->GetAlphaProperty(0, 0)->Reference = 0.2f; } } else { char mtlName[256]; memset(mtlName, 0, 256*sizeof(char)); sprintf(mtlName, "%s/%s", mSettings->DstRootDir, "Data/mtls/StandardES_Specular.pxfx"); standardESMtl_S = new0 PX2::StandardESMaterial_Specular(mtlName); } } if (standardMtl && diffTex) { if (doubleSide) { standardMtl->GetCullProperty(0, 0)->Enabled = false; } inst = standardMtl->CreateInstance(diffTex, alphaVertex, normalEnable, normalTex, normalScale, specEnable, specTex, specPower, 0, shineStandard); } else if (standardESMtl_D && diffTex) { if (doubleSide) { standardESMtl_D->GetCullProperty(0, 0)->Enabled = false; } inst = standardESMtl_D->CreateInstance(diffTex, 0, shineStandard); } else if (standardESMtl_S && diffTex && specTex) { if (doubleSide) { standardESMtl_S->GetCullProperty(0, 0)->Enabled = false; } inst = standardESMtl_S->CreateInstance(diffTex, specTex, specPower, 0, shineStandard); } if (inst) { mtlTree.SetMaterialInstance(inst); } else { PX2::MaterialInstance *instance = PX2::VertexColor4Material::CreateUniqueInstance(); mtlTree.SetMaterialInstance(instance); } } else { PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material(); PX2::MaterialInstance *instance = vcMtl->CreateInstance(); mtlTree.SetMaterialInstance(instance); } // 对子材质进行处理 if (IsDirect9Shader) return; int mQuantity = mtl.NumSubMtls(); // Class_ID(MULTI_CLASS_ID, 0) if (mQuantity > 0) { mtlTree.SetMChildQuantity(mQuantity); for (int i=0; i<mQuantity; i++) { Mtl *subMtl = 0; subMtl = mtl.GetSubMtl(i); if (subMtl) { ConvertMaterial(*subMtl, mtlTree.GetMChild(i)); } } } }
void M3Mat::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* ip) { int i; IReshading* pReshading; TimeValue t = sc.CurTime(); Interval valid = FOREVER; pblockMat->GetValue(100,t,i,FOREVER); Mtl *sm1 = mTex[100]; float total(0.0f); ShadeOutput sDatabase[100]; float u[100]; ShadeOutput sFinal; // handle no base mat if(!sm1) { sc.ResetOutput(); sc.out.c = black; sc.out.t = black; return; } if(i==0 || (i==1 && inRender) ) { for( i=0; i<100; i++) { pblockMat->GetValue(i,t,u[i],valid); u[i] /= 100.0f; if( mTex[i]!=NULL && u[i]!=0 && mapOn[i] ) { Mtl *comb = mTex[i]; pReshading = (IReshading*)(comb->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PostShade(sc, pFrag, nextTexIndex, ip ); sDatabase[i] = sc.out; sc.ResetOutput(); total += u[i]; } } sc.ResetOutput(); pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PostShade(sc, pFrag, nextTexIndex, ip ); sFinal.c = black; sFinal.t = black; sFinal.ior = 0.0f; for( i=0;i<100;i++) { if(mTex[i]!=NULL && u[i]!=0 && mapOn[i]) { sc.out.flags |= sDatabase[i].flags; if(total>1.0f){ sFinal.c += u[i]/total * sDatabase[i].c; sFinal.t += u[i]/total * sDatabase[i].t; sFinal.ior += u[i]/total * sDatabase[i].ior; } else{ sFinal.c += u[i] * sDatabase[i].c; sFinal.t += u[i] * sDatabase[i].t; sFinal.ior += u[i] * sDatabase[i].ior; } } } if(total) { sc.out.MixIn(sFinal, 1.0f-total); } } else { pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading)); if( pReshading ) pReshading->PostShade(sc, pFrag, nextTexIndex, ip ); } }
//---------------------------------------------------------------------------------- void DumpMaterial(IGameMaterial *pGMaxMat) { m_material *pMat = NULL; if (!pGMaxMat->IsMultiType()) // check not a mix material { pMat = new m_material; // set the name of the material... pMat->name = pGMaxMat->GetMaterialName(); // add the new material to the TOC(Table Of Contants) and set its id... pMat->id = ExporterMAX::GetExporter()->AddMaterial(pGMaxMat, pMat); Mtl *pMaxMaterial = pGMaxMat->GetMaxMaterial(); if (pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0)) { StdMat *pStandardMaterial = (StdMat*)pMaxMaterial; Color col; // diffuse color... col = pStandardMaterial->GetDiffuse(ExporterMAX::GetExporter()->GetStaticFrame()); pMat->diffuse = Vector4f(col.r, col.g, col.b, 1.f); // ambient color... col = pStandardMaterial->GetAmbient(ExporterMAX::GetExporter()->GetStaticFrame()); pMat->ambient = Vector4f(col.r, col.g, col.b, 1.f); // specular color... col = pStandardMaterial->GetSpecular(ExporterMAX::GetExporter()->GetStaticFrame()); pMat->specular = Vector4f(col.r, col.g, col.b, 1.f); // emissive color... pMat->emission = Vector4f(0.f, 0.f, 0.f, 1.f); // level of transparency pMat->transparent = pStandardMaterial->GetOpacity(ExporterMAX::GetExporter()->GetStaticFrame()); // specular exponent... pMat->shininess = pStandardMaterial->GetShininess(ExporterMAX::GetExporter()->GetStaticFrame()); // transparency if (pMat->transparent < 1.f){ pMat->diffuse.z = pMat->transparent; } }// 3dsmax6 HLSL Material support. (IDxMaterial) else if (IsDynamicDxMaterial((MtlBase*)pMaxMaterial)) { IDxMaterial *idxm = (IDxMaterial*)pMaxMaterial->GetInterface(IDXMATERIAL_INTERFACE); int lightParams = idxm->GetNumberOfLightParams(); for (int i = 0; i < lightParams; ++i) { INode *pNode = idxm->GetLightNode(i); if (pNode){ TCHAR *paramName = idxm->GetLightParameterName(i); } } // Other attributes are located in paramblk 0... IParamBlock2 *pParamBlk2 = (IParamBlock2*)(pMaxMaterial->GetParamBlock(0)); TimeValue t0 = ExporterMAX::GetExporter()->GetIGame()->GetSceneStartTime(); TimeValue t1 = ExporterMAX::GetExporter()->GetIGame()->GetSceneEndTime(); TimeValue DeltaTime = ExporterMAX::GetExporter()->GetIGame()->GetSceneTicks(); const int SamplingRate = 1; int numkeys = (t1 - t0) / (DeltaTime * SamplingRate) + 1; for (int i = 0; i < pParamBlk2->NumParams(); ++i) { ParamID id = pParamBlk2->IndextoID(i); ParamDef paramDef = pParamBlk2->GetParamDef(id); // we want the variable name not the UI Name... OutputDebugString(paramDef.int_name); } } //do the textures if they are there DumpTexture(pMat, pGMaxMat); } }