Esempio n. 1
0
ShaderVariation* Shader::GetVariation(ShaderType type, const char* defines)
{
    StringHash definesHash(defines);
    
    if (type == VS)
    {
        HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = vsVariations_.Find(definesHash);
        if (i == vsVariations_.End())
        {
            // If shader not found, normalize the defines (to prevent duplicates) and check again. In that case make an alias
            // so that further queries are faster
            String normalizedDefines = NormalizeDefines(defines);
            StringHash normalizedHash(normalizedDefines);
            
            i = vsVariations_.Find(normalizedHash);
            if (i != vsVariations_.End())
                vsVariations_.Insert(MakePair(definesHash, i->second_));
            else
            {
                // No shader variation found. Create new
                i = vsVariations_.Insert(MakePair(normalizedHash, SharedPtr<ShaderVariation>(new ShaderVariation(this, VS))));
                if (definesHash != normalizedHash)
                    vsVariations_.Insert(MakePair(definesHash, i->second_));
                
                i->second_->SetName(GetFileName(GetName()));
                i->second_->SetDefines(normalizedDefines);
                ++numVariations_;
                RefreshMemoryUse();
            }
        }
        
        return i->second_;
    }
    else
    {
        HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = psVariations_.Find(definesHash);
        if (i == psVariations_.End())
        {
            String normalizedDefines = NormalizeDefines(defines);
            StringHash normalizedHash(normalizedDefines);
            
            i = psVariations_.Find(normalizedHash);
            if (i != psVariations_.End())
                psVariations_.Insert(MakePair(definesHash, i->second_));
            else
            {
                i = psVariations_.Insert(MakePair(normalizedHash, SharedPtr<ShaderVariation>(new ShaderVariation(this, PS))));
                if (definesHash != normalizedHash)
                    psVariations_.Insert(MakePair(definesHash, i->second_));
                
                i->second_->SetName(GetFileName(GetName()));
                i->second_->SetDefines(normalizedDefines);
                ++numVariations_;
                RefreshMemoryUse();
            }
        }
        
        return i->second_;
    }
}
Esempio n. 2
0
bool Shader::BeginLoad(Deserializer& source)
{
    Graphics* graphics = GetSubsystem<Graphics>();
    if (!graphics)
        return false;
    
    // Load the shader source code and resolve any includes
    timeStamp_ = 0;
    String shaderCode;
    if (!ProcessSource(shaderCode, source))
        return false;
    
    // Comment out the unneeded shader function
    vsSourceCode_ = shaderCode;
    psSourceCode_ = shaderCode;
    CommentOutFunction(vsSourceCode_, "void PS(");
    CommentOutFunction(psSourceCode_, "void VS(");
    
    // OpenGL: rename either VS() or PS() to main(), comment out vertex attributes in pixel shaders
    #ifdef URHO3D_OPENGL
    vsSourceCode_.Replace("void VS(", "void main(");
    psSourceCode_.Replace("void PS(", "void main(");
    psSourceCode_.Replace("attribute ", "// attribute ");
    #endif
    
    RefreshMemoryUse();
    return true;
}
Esempio n. 3
0
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();
}
Esempio n. 4
0
void Material::SetShaderParameter(const String& name, const Variant& value)
{
    MaterialShaderParameter newParam;
    newParam.name_ = name;
    newParam.value_ = value;
    StringHash nameHash(name);
    shaderParameters_[nameHash] = newParam;

    if (nameHash == PSP_MATSPECCOLOR)
    {
        VariantType type = value.GetType();
        if (type == VAR_VECTOR3)
        {
            const Vector3& vec = value.GetVector3();
            specular_ = vec.x_ > 0.0f || vec.y_ > 0.0f || vec.z_ > 0.0f;
        }
        else if (type == VAR_VECTOR4)
        {
            const Vector4& vec = value.GetVector4();
            specular_ = vec.x_ > 0.0f || vec.y_ > 0.0f || vec.z_ > 0.0f;
        }
    }

    if (!batchedParameterUpdate_)
    {
        RefreshShaderParameterHash();
        RefreshMemoryUse();
    }
}
Esempio n. 5
0
void Material::SetNumTechniques(unsigned num)
{
    if (!num)
        return;

    techniques_.Resize(num);
    RefreshMemoryUse();
}
Esempio n. 6
0
void Material::RemoveShaderParameter(const String& name)
{
    StringHash nameHash(name);
    shaderParameters_.Erase(nameHash);

    if (nameHash == PSP_MATSPECCOLOR)
        specular_ = false;

    RefreshShaderParameterHash();
    RefreshMemoryUse();
}
Esempio n. 7
0
bool Shader::Load(Deserializer& source)
{
    PROFILE(LoadShader);
    
    Graphics* graphics = GetSubsystem<Graphics>();
    if (!graphics)
        return false;
    
    // Load the shader source code and resolve any includes
    timeStamp_ = 0;
    String shaderCode;
    if (!ProcessSource(shaderCode, source))
        return false;
    
    // Comment out the unneeded shader function
    vsSourceCode_ = shaderCode;
    psSourceCode_ = shaderCode;
    CommentOutFunction(vsSourceCode_, "void PS(");
    CommentOutFunction(psSourceCode_, "void VS(");
    
    // OpenGL: rename either VS() or PS() to main(), comment out vertex attributes in pixel shaders
    #ifdef USE_OPENGL
    vsSourceCode_.Replace("void VS(", "void main(");
    psSourceCode_.Replace("void PS(", "void main(");
    psSourceCode_.Replace("attribute ", "// attribute ");
    #endif
    
    // If variations had already been created, release them and require recompile
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = vsVariations_.Begin(); i != vsVariations_.End(); ++i)
        i->second_->Release();
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = psVariations_.Begin(); i != psVariations_.End(); ++i)
        i->second_->Release();
    
    RefreshMemoryUse();
    return true;
}
Esempio n. 8
0
Shader::Shader(Context* context) :
    Resource(context),
    timeStamp_(0)
{
    RefreshMemoryUse();
}
Esempio n. 9
0
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;
}