Exemple #1
0
// *************************************************************************************************
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);
	}
}