void Material::SetUVTransform(const Vector2& offset, float rotation, const Vector2& repeat) { Matrix3x4 transform(Matrix3x4::IDENTITY); transform.m00_ = repeat.x_; transform.m11_ = repeat.y_; transform.m03_ = -0.5f * transform.m00_ + 0.5f; transform.m13_ = -0.5f * transform.m11_ + 0.5f; Matrix3x4 rotationMatrix(Matrix3x4::IDENTITY); rotationMatrix.m00_ = Cos(rotation); rotationMatrix.m01_ = Sin(rotation); rotationMatrix.m10_ = -rotationMatrix.m01_; rotationMatrix.m11_ = rotationMatrix.m00_; rotationMatrix.m03_ = 0.5f - 0.5f * (rotationMatrix.m00_ + rotationMatrix.m01_); rotationMatrix.m13_ = 0.5f - 0.5f * (rotationMatrix.m10_ + rotationMatrix.m11_); transform = rotationMatrix * transform; Matrix3x4 offsetMatrix = Matrix3x4::IDENTITY; offsetMatrix.m03_ = offset.x_; offsetMatrix.m13_ = offset.y_; transform = offsetMatrix * transform; SetShaderParameter("UOffset", Vector4(transform.m00_, transform.m01_, transform.m02_, transform.m03_)); SetShaderParameter("VOffset", Vector4(transform.m10_, transform.m11_, transform.m12_, transform.m13_)); }
void Material::ResetToDefaults() { // Needs to be a no-op when async loading, as this does a GetResource() which is not allowed from worker threads if (!Thread::IsMainThread()) return; SetNumTechniques(1); SetTechnique(0, GetSubsystem<ResourceCache>()->GetResource<Technique>("Techniques/NoTexture.xml")); textures_.Clear(); batchedParameterUpdate_ = true; shaderParameters_.Clear(); SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f)); SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f)); SetShaderParameter("MatDiffColor", Vector4::ONE); SetShaderParameter("MatEmissiveColor", Vector3::ZERO); SetShaderParameter("MatEnvMapColor", Vector3::ONE); SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f)); batchedParameterUpdate_ = false; cullMode_ = CULL_CCW; shadowCullMode_ = CULL_CCW; fillMode_ = FILL_SOLID; depthBias_ = BiasParameters(0.0f, 0.0f); RefreshShaderParameterHash(); RefreshMemoryUse(); }
void Material::ResetToDefaults() { for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i) textures_[i] = 0; shaderParameters_.Clear(); SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f)); SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f)); SetShaderParameter("MatDiffColor", Vector4::ONE); SetShaderParameter("MatEmissiveColor", Vector3::ZERO); SetShaderParameter("MatEnvMapColor", Vector3::ONE); SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f)); cullMode_ = CULL_CCW; shadowCullMode_ = CULL_CCW; depthBias_ = BiasParameters(0.0f, 0.0f); }
bool Material::Load(const XMLElement& source) { ResetToDefaults(); if (source.IsNull()) { LOGERROR("Can not load material from null XML element"); return false; } ResourceCache* cache = GetSubsystem<ResourceCache>(); XMLElement techniqueElem = source.GetChild("technique"); techniques_.Clear(); while (techniqueElem) { Technique* tech = cache->GetResource<Technique>(techniqueElem.GetAttribute("name")); if (tech) { TechniqueEntry newTechnique; newTechnique.technique_ = tech; if (techniqueElem.HasAttribute("quality")) newTechnique.qualityLevel_ = techniqueElem.GetInt("quality"); if (techniqueElem.HasAttribute("loddistance")) newTechnique.lodDistance_ = techniqueElem.GetFloat("loddistance"); techniques_.Push(newTechnique); } techniqueElem = techniqueElem.GetNext("technique"); } SortTechniques(); XMLElement textureElem = source.GetChild("texture"); while (textureElem) { TextureUnit unit = TU_DIFFUSE; if (textureElem.HasAttribute("unit")) { String unitName = textureElem.GetAttributeLower("unit"); if (unitName.Length() > 1) { unit = ParseTextureUnitName(unitName); if (unit >= MAX_MATERIAL_TEXTURE_UNITS) LOGERROR("Unknown or illegal texture unit " + unitName); } else unit = (TextureUnit)Clamp(ToInt(unitName), 0, MAX_MATERIAL_TEXTURE_UNITS - 1); } if (unit != MAX_MATERIAL_TEXTURE_UNITS) { String name = textureElem.GetAttribute("name"); // Detect cube maps by file extension: they are defined by an XML file if (GetExtension(name) == ".xml") SetTexture(unit, cache->GetResource<TextureCube>(name)); else SetTexture(unit, cache->GetResource<Texture2D>(name)); } textureElem = textureElem.GetNext("texture"); } XMLElement parameterElem = source.GetChild("parameter"); while (parameterElem) { String name = parameterElem.GetAttribute("name"); SetShaderParameter(name, ParseShaderParameterValue(parameterElem.GetAttribute("value"))); parameterElem = parameterElem.GetNext("parameter"); } XMLElement cullElem = source.GetChild("cull"); if (cullElem) SetCullMode((CullMode)GetStringListIndex(cullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement shadowCullElem = source.GetChild("shadowcull"); if (shadowCullElem) SetShadowCullMode((CullMode)GetStringListIndex(shadowCullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement depthBiasElem = source.GetChild("depthbias"); if (depthBiasElem) SetDepthBias(BiasParameters(depthBiasElem.GetFloat("constant"), depthBiasElem.GetFloat("slopescaled"))); // Calculate memory use unsigned memoryUse = sizeof(Material); memoryUse += techniques_.Size() * sizeof(TechniqueEntry); memoryUse += MAX_MATERIAL_TEXTURE_UNITS * sizeof(SharedPtr<Texture>); memoryUse += shaderParameters_.Size() * sizeof(MaterialShaderParameter); SetMemoryUse(memoryUse); CheckOcclusion(); return true; }
bool Material::Load(const XMLElement& source) { ResetToDefaults(); if (source.IsNull()) { LOGERROR("Can not load material from null XML element"); return false; } ResourceCache* cache = GetSubsystem<ResourceCache>(); XMLElement techniqueElem = source.GetChild("technique"); techniques_.Clear(); while (techniqueElem) { Technique* tech = cache->GetResource<Technique>(techniqueElem.GetAttribute("name")); if (tech) { TechniqueEntry newTechnique; newTechnique.technique_ = tech; if (techniqueElem.HasAttribute("quality")) newTechnique.qualityLevel_ = techniqueElem.GetInt("quality"); if (techniqueElem.HasAttribute("loddistance")) newTechnique.lodDistance_ = techniqueElem.GetFloat("loddistance"); techniques_.Push(newTechnique); } techniqueElem = techniqueElem.GetNext("technique"); } SortTechniques(); XMLElement textureElem = source.GetChild("texture"); while (textureElem) { TextureUnit unit = TU_DIFFUSE; if (textureElem.HasAttribute("unit")) unit = ParseTextureUnitName(textureElem.GetAttribute("unit")); if (unit < MAX_TEXTURE_UNITS) { String name = textureElem.GetAttribute("name"); // Detect cube maps by file extension: they are defined by an XML file /// \todo Differentiate with 3D textures by actually reading the XML content if (GetExtension(name) == ".xml") { #ifdef DESKTOP_GRAPHICS if (unit == TU_VOLUMEMAP) SetTexture(unit, cache->GetResource<Texture3D>(name)); else #endif SetTexture(unit, cache->GetResource<TextureCube>(name)); } else SetTexture(unit, cache->GetResource<Texture2D>(name)); } textureElem = textureElem.GetNext("texture"); } batchedParameterUpdate_ = true; XMLElement parameterElem = source.GetChild("parameter"); while (parameterElem) { String name = parameterElem.GetAttribute("name"); SetShaderParameter(name, ParseShaderParameterValue(parameterElem.GetAttribute("value"))); parameterElem = parameterElem.GetNext("parameter"); } batchedParameterUpdate_ = false; XMLElement parameterAnimationElem = source.GetChild("parameteranimation"); while (parameterAnimationElem) { String name = parameterAnimationElem.GetAttribute("name"); SharedPtr<ValueAnimation> animation(new ValueAnimation(context_)); if (!animation->LoadXML(parameterAnimationElem)) { LOGERROR("Could not load parameter animation"); return false; } String wrapModeString = parameterAnimationElem.GetAttribute("wrapmode"); WrapMode wrapMode = WM_LOOP; for (int i = 0; i <= WM_CLAMP; ++i) { if (wrapModeString == wrapModeNames[i]) { wrapMode = (WrapMode)i; break; } } float speed = parameterAnimationElem.GetFloat("speed"); SetShaderParameterAnimation(name, animation, wrapMode, speed); parameterAnimationElem = parameterAnimationElem.GetNext("parameteranimation"); } XMLElement cullElem = source.GetChild("cull"); if (cullElem) SetCullMode((CullMode)GetStringListIndex(cullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement shadowCullElem = source.GetChild("shadowcull"); if (shadowCullElem) SetShadowCullMode((CullMode)GetStringListIndex(shadowCullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement fillElem = source.GetChild("fill"); if (fillElem) SetFillMode((FillMode)GetStringListIndex(fillElem.GetAttribute("value").CString(), fillModeNames, FILL_SOLID)); XMLElement depthBiasElem = source.GetChild("depthbias"); if (depthBiasElem) SetDepthBias(BiasParameters(depthBiasElem.GetFloat("constant"), depthBiasElem.GetFloat("slopescaled"))); RefreshShaderParameterHash(); RefreshMemoryUse(); CheckOcclusion(); return true; }
void Graphics::SetShaderParameter(StringHash param, const Variant& value) { switch (value.GetType()) { case VAR_BOOL: SetShaderParameter(param, value.GetBool()); break; case VAR_INT: SetShaderParameter(param, value.GetInt()); break; case VAR_FLOAT: case VAR_DOUBLE: SetShaderParameter(param, value.GetFloat()); break; case VAR_VECTOR2: SetShaderParameter(param, value.GetVector2()); break; case VAR_VECTOR3: SetShaderParameter(param, value.GetVector3()); break; case VAR_VECTOR4: SetShaderParameter(param, value.GetVector4()); break; case VAR_COLOR: SetShaderParameter(param, value.GetColor()); break; case VAR_MATRIX3: SetShaderParameter(param, value.GetMatrix3()); break; case VAR_MATRIX3X4: SetShaderParameter(param, value.GetMatrix3x4()); break; case VAR_MATRIX4: SetShaderParameter(param, value.GetMatrix4()); break; case VAR_BUFFER: { const PODVector<unsigned char>& buffer = value.GetBuffer(); if (buffer.Size() >= sizeof(float)) SetShaderParameter(param, reinterpret_cast<const float*>(&buffer[0]), buffer.Size() / sizeof(float)); } break; default: // Unsupported parameter type, do nothing break; } }
bool Material::Load(Deserializer& source) { PROFILE(LoadMaterial); // In headless mode, do not actually load the material, just return success Graphics* graphics = GetSubsystem<Graphics>(); if (!graphics) return true; ResetToDefaults(); ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<XMLFile> xml(new XMLFile(context_)); if (!xml->Load(source)) return false; XMLElement rootElem = xml->GetRoot(); XMLElement techniqueElem = rootElem.GetChild("technique"); techniques_.Clear(); while (techniqueElem) { Technique* tech = cache->GetResource<Technique>(techniqueElem.GetAttribute("name")); if (tech) { TechniqueEntry newTechnique; newTechnique.technique_ = tech; if (techniqueElem.HasAttribute("quality")) newTechnique.qualityLevel_ = techniqueElem.GetInt("quality"); if (techniqueElem.HasAttribute("loddistance")) newTechnique.lodDistance_ = techniqueElem.GetFloat("loddistance"); techniques_.Push(newTechnique); } techniqueElem = techniqueElem.GetNext("technique"); } XMLElement textureElem = rootElem.GetChild("texture"); while (textureElem) { TextureUnit unit = TU_DIFFUSE; if (textureElem.HasAttribute("unit")) { String unitName = textureElem.GetAttributeLower("unit"); if (unitName.Length() > 1) { unit = ParseTextureUnitName(unitName); if (unit >= MAX_MATERIAL_TEXTURE_UNITS) LOGERROR("Unknown or illegal texture unit " + unitName); } else unit = (TextureUnit)Clamp(ToInt(unitName), 0, MAX_MATERIAL_TEXTURE_UNITS - 1); } if (unit != MAX_MATERIAL_TEXTURE_UNITS) { String name = textureElem.GetAttribute("name"); // Detect cube maps by file extension: they are defined by an XML file if (GetExtension(name) == ".xml") SetTexture(unit, cache->GetResource<TextureCube>(name)); else SetTexture(unit, cache->GetResource<Texture2D>(name)); } textureElem = textureElem.GetNext("texture"); } XMLElement parameterElem = rootElem.GetChild("parameter"); while (parameterElem) { String name = parameterElem.GetAttribute("name"); Variant value = parameterElem.GetVectorVariant("value"); SetShaderParameter(name, value); parameterElem = parameterElem.GetNext("parameter"); } XMLElement cullElem = rootElem.GetChild("cull"); if (cullElem) SetCullMode((CullMode)GetStringListIndex(cullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement shadowCullElem = rootElem.GetChild("shadowcull"); if (shadowCullElem) SetShadowCullMode((CullMode)GetStringListIndex(shadowCullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW)); XMLElement depthBiasElem = rootElem.GetChild("depthbias"); if (depthBiasElem) SetDepthBias(BiasParameters(depthBiasElem.GetFloat("constant"), depthBiasElem.GetFloat("slopescaled"))); // Calculate memory use unsigned memoryUse = sizeof(Material); memoryUse += techniques_.Size() * sizeof(TechniqueEntry); memoryUse += MAX_MATERIAL_TEXTURE_UNITS * sizeof(SharedPtr<Texture>); memoryUse += shaderParameters_.Size() * sizeof(MaterialShaderParameter); SetMemoryUse(memoryUse); CheckOcclusion(); return true; }