#pragma once #include "BsCorePrerequisites.h" #include "BsResource.h" namespace BansheeEngine { /** * @brief Structure that describes blend states for a single render * target. Used internally by BLEND_STATE_DESC for initializing a BlendState. * * @see BLEND_STATE_DESC * @see BlendState */ struct BS_CORE_EXPORT RENDER_TARGET_BLEND_STATE_DESC { RENDER_TARGET_BLEND_STATE_DESC() : blendEnable(false) , srcBlend(BF_ONE) , dstBlend(BF_ZERO) , blendOp(BO_ADD) , srcBlendAlpha(BF_ONE) , dstBlendAlpha(BF_ZERO) , blendOpAlpha(BO_ADD) , renderTargetWriteMask(0xFF) { } bool operator==(const RENDER_TARGET_BLEND_STATE_DESC& rhs) const; bool blendEnable; BlendFactor srcBlend; BlendFactor dstBlend; BlendOperation blendOp; BlendFactor srcBlendAlpha; BlendFactor dstBlendAlpha; BlendOperation blendOpAlpha; // Enable write to RGBA channels separately by setting first four bits (0 - R, 1 - G, 2 - B, 3 - A) UINT8 renderTargetWriteMask; }; /** * @brief Structure that describes render pipeline blend states. Used for initializing * BlendState. * * @see BlendState. */ struct BS_CORE_EXPORT BLEND_STATE_DESC { BLEND_STATE_DESC() : alphaToCoverageEnable(false) , independantBlendEnable(false) { } bool operator==(const BLEND_STATE_DESC& rhs) const; bool alphaToCoverageEnable; bool independantBlendEnable; RENDER_TARGET_BLEND_STATE_DESC renderTargetDesc[BS_MAX_MULTIPLE_RENDER_TARGETS]; }; /** * @brief Information about a blend state. */ class BS_CORE_EXPORT BlendProperties { public: BlendProperties(const BLEND_STATE_DESC& desc); /** * @brief Alpha to coverage allows you to perform blending without needing to worry about order of * rendering like regular blending does. It requires multi-sampling to be active in order to * work, and you need to supply an alpha texture that determines object transparency. * * Blending is then performed by only using sub-samples covered by the alpha texture for the current * pixel and combining them with sub-samples previously stored. * * Be aware this is a limited technique only useful for certain situations. Unless you are having performance * problems use regular blending. */ bool getAlphaToCoverageEnabled() const { return mData.alphaToCoverageEnable; } /** * @brief When not set, only the first render target blend descriptor will be used for all * render targets. If set each render target will use its own blend descriptor. */ bool getIndependantBlendEnable() const { return mData.independantBlendEnable; } /** * @brief Queries is blending enabled for the specified render target. Blending * allows you to combine the color from current and previous pixel based on * some value. */ bool getBlendEnabled(UINT32 renderTargetIdx) const; /** * @brief Determines what should the source blend factor be. This value determines * what will the color being generated currently be multiplied by. */ BlendFactor getSrcBlend(UINT32 renderTargetIdx) const; /** * @brief Determines what should the destination blend factor be. This value determines * what will the color already in render target be multiplied by. */ BlendFactor getDstBlend(UINT32 renderTargetIdx) const; /** * @brief Determines how are source and destination colors combined (after they are multiplied * by their respective blend factors). */ BlendOperation getBlendOperation(UINT32 renderTargetIdx) const; /** * @brief Determines what should the alpha source blend factor be. This value determines * what will the alpha value being generated currently be multiplied by. */ BlendFactor getAlphaSrcBlend(UINT32 renderTargetIdx) const; /** * @brief Determines what should the alpha destination blend factor be. This value determines * what will the alpha value already in render target be multiplied by. */ BlendFactor getAlphaDstBlend(UINT32 renderTargetIdx) const; /** * @brief Determines how are source and destination alpha values combined (after they are multiplied * by their respective blend factors). */ BlendOperation getAlphaBlendOperation(UINT32 renderTargetIdx) const; /** * @brief Render target write mask allows to choose which pixel components should the pixel shader * output. * * Only the first four bits are used. First bit representing red, second green, third blue and * fourth alpha value. Set bits means pixel shader will output those channels. */ UINT8 getRenderTargetWriteMask(UINT32 renderTargetIdx) const; /** * @brief Returns the hash value generated from the blend state properties. */ UINT64 getHash() const { return mHash; } protected: friend class BlendState; friend class BlendStateCore; friend class BlendStateRTTI; BLEND_STATE_DESC mData; UINT64 mHash; }; /** * @brief Core thread version of a blend state. * * @see BlendState * * @note Core thread. */ class BS_CORE_EXPORT BlendStateCore : public CoreObjectCore { public: virtual ~BlendStateCore(); /** * @brief Returns information about the blend state. */ const BlendProperties& getProperties() const; /** * @brief Returns a unique state ID. Only the lowest 10 bits are used. */ UINT32 getId() const { return mId; } /** * @brief Returns the default blend state that you may use * when no other is available. */ static const SPtr& getDefault(); protected: friend class RenderStateCoreManager; BlendStateCore(const BLEND_STATE_DESC& desc, UINT32 id); /** * @copydoc CoreObjectCore::initialize */ void initialize() override; /** * @brief Creates any API-specific state objects. */ virtual void createInternal() { } BlendProperties mProperties; UINT32 mId; }; /** * @brief Render system pipeline state that allows you to modify how an object is rendered. * More exactly this state allows to you to control how is a rendered * object blended with any previously renderer objects. * * @note Blend states are immutable. Sim thread only. */ class BS_CORE_EXPORT BlendState : public IReflectable, public CoreObject { public: virtual ~BlendState(); /** * @brief Returns information about a blend state. */ const BlendProperties& getProperties() const; /** * @brief Retrieves a core implementation of the sampler state usable only from the * core thread. */ SPtr getCore() const; /** * @brief Creates a new blend state using the specified blend state description structure. */ static BlendStatePtr create(const BLEND_STATE_DESC& desc); /** * @brief Returns the default blend state that you may use * when no other is available. */ static const BlendStatePtr& getDefault(); /** * @brief Generates a hash value from a blend state descriptor. */ static UINT64 generateHash(const BLEND_STATE_DESC& desc); protected: friend class RenderStateManager; BlendState(const BLEND_STATE_DESC& desc); /** * @copydoc CoreObjectCore::createCore */ SPtr createCore() const override; BlendProperties mProperties; mutable UINT32 mId; /************************************************************************/ /* RTTI */ /************************************************************************/ public: friend class BlendStateRTTI; static RTTITypeBase* getRTTIStatic(); virtual RTTITypeBase* getRTTI() const override; }; } /** * @brief Hash value generator for BLEND_STATE_DESC. */ template<> struct std::hash { size_t operator()(const BansheeEngine::BLEND_STATE_DESC& value) const { return (size_t)BansheeEngine::BlendState::generateHash(value); } };