std::shared_ptr EffectFactory::Impl::CreateEffect()

in Src/EffectFactory.cpp [115:367]


std::shared_ptr<IEffect> EffectFactory::Impl::CreateEffect(IEffectFactory* factory, const IEffectFactory::EffectInfo& info, ID3D11DeviceContext* deviceContext)
{
    if (info.enableSkinning)
    {
        if (info.enableNormalMaps && mUseNormalMapEffect)
        {
            // SkinnedNormalMapEffect
            if (mSharing && info.name && *info.name)
            {
                auto it = mEffectNormalMapSkinned.find(info.name);
                if (mSharing && it != mEffectNormalMapSkinned.end())
                {
                    return it->second;
                }
            }

            auto effect = std::make_shared<SkinnedNormalMapEffect>(mDevice.Get());

            SetMaterialProperties(effect.get(), info);

            if (info.diffuseTexture && *info.diffuseTexture)
            {
                ComPtr<ID3D11ShaderResourceView> srv;

                factory->CreateTexture(info.diffuseTexture, deviceContext, srv.GetAddressOf());

                effect->SetTexture(srv.Get());
            }

            if (info.specularTexture && *info.specularTexture)
            {
                ComPtr<ID3D11ShaderResourceView> srv;

                factory->CreateTexture(info.specularTexture, deviceContext, srv.GetAddressOf());

                effect->SetSpecularTexture(srv.Get());
            }

            if (info.normalTexture && *info.normalTexture)
            {
                ComPtr<ID3D11ShaderResourceView> srv;

                factory->CreateTexture(info.normalTexture, deviceContext, srv.GetAddressOf());

                effect->SetNormalTexture(srv.Get());
            }

            if (mSharing && info.name && *info.name)
            {
                std::lock_guard<std::mutex> lock(mutex);
                EffectCache::value_type v(info.name, effect);
                mEffectNormalMapSkinned.insert(v);
            }

            return std::move(effect);
        }
        else
        {
            // SkinnedEffect
            if (mSharing && info.name && *info.name)
            {
                auto it = mEffectCacheSkinning.find(info.name);
                if (mSharing && it != mEffectCacheSkinning.end())
                {
                    return it->second;
                }
            }

            auto effect = std::make_shared<SkinnedEffect>(mDevice.Get());

            SetMaterialProperties(effect.get(), info);

            if (info.diffuseTexture && *info.diffuseTexture)
            {
                ComPtr<ID3D11ShaderResourceView> srv;

                factory->CreateTexture(info.diffuseTexture, deviceContext, srv.GetAddressOf());

                effect->SetTexture(srv.Get());
            }

            if (mSharing && info.name && *info.name)
            {
                std::lock_guard<std::mutex> lock(mutex);
                EffectCache::value_type v(info.name, effect);
                mEffectCacheSkinning.insert(v);
            }

            return std::move(effect);
        }
    }
    else if (info.enableDualTexture)
    {
        // DualTextureEffect
        if (mSharing && info.name && *info.name)
        {
            auto it = mEffectCacheDualTexture.find(info.name);
            if (mSharing && it != mEffectCacheDualTexture.end())
            {
                return it->second;
            }
        }

        auto effect = std::make_shared<DualTextureEffect>(mDevice.Get());

        // Dual texture effect doesn't support lighting (usually it's lightmaps)

        effect->SetAlpha(info.alpha);

        if (info.perVertexColor)
        {
            effect->SetVertexColorEnabled(true);
        }

        XMVECTOR color = XMLoadFloat3(&info.diffuseColor);
        effect->SetDiffuseColor(color);

        if (info.diffuseTexture && *info.diffuseTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.diffuseTexture, deviceContext, srv.GetAddressOf());

            effect->SetTexture(srv.Get());
        }

        if (info.emissiveTexture && *info.emissiveTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.emissiveTexture, deviceContext, srv.GetAddressOf());

            effect->SetTexture2(srv.Get());
        }
        else if (info.specularTexture && *info.specularTexture)
        {
            // If there's no emissive texture specified, use the specular texture as the second texture
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.specularTexture, deviceContext, srv.GetAddressOf());

            effect->SetTexture2(srv.Get());
        }

        if (mSharing && info.name && *info.name)
        {
            std::lock_guard<std::mutex> lock(mutex);
            EffectCache::value_type v(info.name, effect);
            mEffectCacheDualTexture.insert(v);
        }

        return std::move(effect);
    }
    else if (info.enableNormalMaps && mUseNormalMapEffect)
    {
        // NormalMapEffect
        if (mSharing && info.name && *info.name)
        {
            auto it = mEffectNormalMap.find(info.name);
            if (mSharing && it != mEffectNormalMap.end())
            {
                return it->second;
            }
        }

        auto effect = std::make_shared<NormalMapEffect>(mDevice.Get());

        SetMaterialProperties(effect.get(), info);

        if (info.perVertexColor)
        {
            effect->SetVertexColorEnabled(true);
        }

        if (info.diffuseTexture && *info.diffuseTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.diffuseTexture, deviceContext, srv.GetAddressOf());

            effect->SetTexture(srv.Get());
        }

        if (info.specularTexture && *info.specularTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.specularTexture, deviceContext, srv.GetAddressOf());

            effect->SetSpecularTexture(srv.Get());
        }

        if (info.normalTexture && *info.normalTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.normalTexture, deviceContext, srv.GetAddressOf());

            effect->SetNormalTexture(srv.Get());
        }

        if (mSharing && info.name && *info.name)
        {
            std::lock_guard<std::mutex> lock(mutex);
            EffectCache::value_type v(info.name, effect);
            mEffectNormalMap.insert(v);
        }

        return std::move(effect);
    }
    else
    {
        // BasicEffect
        if (mSharing && info.name && *info.name)
        {
            auto it = mEffectCache.find(info.name);
            if (mSharing && it != mEffectCache.end())
            {
                return it->second;
            }
        }

        auto effect = std::make_shared<BasicEffect>(mDevice.Get());

        effect->SetLightingEnabled(true);

        SetMaterialProperties(effect.get(), info);

        if (info.perVertexColor)
        {
            effect->SetVertexColorEnabled(true);
        }

        if (info.diffuseTexture && *info.diffuseTexture)
        {
            ComPtr<ID3D11ShaderResourceView> srv;

            factory->CreateTexture(info.diffuseTexture, deviceContext, srv.GetAddressOf());

            effect->SetTexture(srv.Get());
            effect->SetTextureEnabled(true);
        }

        if (mSharing && info.name && *info.name)
        {
            std::lock_guard<std::mutex> lock(mutex);
            EffectCache::value_type v(info.name, effect);
            mEffectCache.insert(v);
        }

        return std::move(effect);
    }
}