// ************************************************************************************************* void makeInstanceTransparent(UInstance &inst, uint8 opacity, bool disableZWrite) { UShape shape= inst.getShape(); if(shape.empty()) return; uint numMats= shape.getNumMaterials(); if(numMats==0) return; if(numMats!=inst.getNumMaterials()) return; // instance transparent or not? if (opacity == 255) { // reset default shape opacity / transparency inst.setOpacity(shape.getDefaultOpacity()); inst.setTransparency(shape.getDefaultTransparency()); inst.setBypassLODOpacityFlag(false); } else { // Will have some blend material => sure not to be rendered in Opaque pass inst.setOpacity(false); inst.setTransparency(true); inst.setBypassLODOpacityFlag(true); // these flags prevails over the current lods flags for multi-lod objects } // set all materials for (uint32 j = 0; j < numMats; ++j) { NL3D::UInstanceMaterial matInst = inst.getMaterial(j); NL3D::UMaterial matShape= shape.getMaterial(j); // disalbe zwrite? if(disableZWrite) matInst.setZWrite(false); else matInst.setZWrite(matShape.getZWrite()); // if no more transparent if (opacity == 255) { // reset to default matInst.setBlend(matShape.getBlend()); matInst.setBlendFunc((NL3D::UInstanceMaterial::TBlend)matShape.getSrcBlend(), (NL3D::UInstanceMaterial::TBlend)matShape.getDstBlend()); // if orginal material is opaque or additif and has no alpha test, then ensure restore last tex env if needed CMaterial *destInternalMat = matInst.getObjectPtr(); if (!matShape.getBlend() && !matShape.getAlphaTest()) { if (destInternalMat->getShader() == CMaterial::Normal) { CMaterial *srcInternalMat = matShape.getObjectPtr(); uint numTex = 0; for (;numTex < 4 && srcInternalMat->getTexture(numTex) != NULL; ++numTex) {} if (numTex > 0) { if (srcInternalMat->getTexEnvMode(numTex - 1) != destInternalMat->getTexEnvMode(numTex - 1)) { destInternalMat->setTexEnvMode(numTex - 1, srcInternalMat->getTexEnvMode(numTex - 1)); } } } } if (destInternalMat->getShader() == CMaterial::Normal) { // if !lighted, restore color if (!destInternalMat->isLighted()) { CMaterial *srcInternalMat = matShape.getObjectPtr(); // restore alpha in color CRGBA color = destInternalMat->getColor(); color.A = srcInternalMat->getColor().A; destInternalMat->setColor(color); } } } else { // Enable blend matInst.setBlend(true); // If default is ???/one or , then use a srcalpha/one (eg: for Diamond-like weapons) if(matShape.getBlend() && (sint32)matShape.getDstBlend()==(sint32)NL3D::UInstanceMaterial::one) matInst.setBlendFunc(NL3D::UInstanceMaterial::srcalpha, NL3D::UInstanceMaterial::one); // else use a standard srcalpha/invsrcalpha else matInst.setBlendFunc(NL3D::UInstanceMaterial::srcalpha, NL3D::UInstanceMaterial::invsrcalpha); // if orginal material is opaque or additif and has no alpha test, then ensure that the alpha output is 'diffuse' CMaterial *internalMat = matInst.getObjectPtr(); if (!matShape.getBlend() && !matShape.getAlphaTest()) { if (internalMat->getShader() == CMaterial::Normal) { uint numTex = 0; for (;numTex < 4 && internalMat->getTexture(numTex) != NULL; ++numTex) {} if (numTex > 0) { internalMat->texEnvOpAlpha(numTex - 1, CMaterial::Replace); // if material is unlighted, then use the constant at this stage to set the alpha internalMat->texEnvArg0Alpha(numTex - 1, CMaterial::Diffuse, CMaterial::SrcAlpha); } } } if (internalMat->getShader() == CMaterial::Normal) { if (!internalMat->isLighted()) { // replace alpha in color CRGBA color = internalMat->getColor(); color.A = opacity; internalMat->setColor(color); } } } // suppose that default opacity is always 255 if (matInst.isLighted()) { matInst.setOpacity(opacity); } matInst.setAlphaTestThreshold(matShape.getAlphaTestThreshold()*((float)opacity)/255.0f); } }