1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Resources/BsResource.h"
7
8namespace bs
9{
10 /** @addtogroup RenderAPI
11 * @{
12 */
13
14 /**
15 * Structure that describes blend states for a single render target. Used internally by BLEND_STATE_DESC for
16 * initializing a BlendState.
17 *
18 * @see BLEND_STATE_DESC
19 * @see BlendState
20 */
21 struct BS_CORE_EXPORT RENDER_TARGET_BLEND_STATE_DESC
22 {
23 bool operator==(const RENDER_TARGET_BLEND_STATE_DESC& rhs) const;
24
25 /**
26 * Queries is blending enabled for the specified render target. Blending allows you to combine the color from
27 * current and previous pixel based on some value.
28 */
29 bool blendEnable = false;
30
31 /**
32 * Determines what should the source blend factor be. This value determines what will the color being generated
33 * currently be multiplied by.
34 */
35 BlendFactor srcBlend = BF_ONE;
36
37 /**
38 * Determines what should the destination blend factor be. This value determines what will the color already in
39 * render target be multiplied by.
40 */
41 BlendFactor dstBlend = BF_ZERO;
42
43 /**
44 * Determines how are source and destination colors combined (after they are multiplied by their respective blend
45 * factors).
46 */
47 BlendOperation blendOp = BO_ADD;
48
49 /**
50 * Determines what should the alpha source blend factor be. This value determines what will the alpha value being
51 * generated currently be multiplied by.
52 */
53 BlendFactor srcBlendAlpha = BF_ONE;
54
55 /**
56 * Determines what should the alpha destination blend factor be. This value determines what will the alpha value
57 * already in render target be multiplied by.
58 */
59 BlendFactor dstBlendAlpha = BF_ZERO;
60
61 /**
62 * Determines how are source and destination alpha values combined (after they are multiplied by their respective
63 * blend factors).
64 */
65 BlendOperation blendOpAlpha = BO_ADD;
66
67 /**
68 * Render target write mask allows to choose which pixel components should the pixel shader output.
69 *
70 * Only the first four bits are used. First bit representing red, second green, third blue and fourth alpha value.
71 * Set bits means pixel shader will output those channels.
72 */
73 UINT8 renderTargetWriteMask = 0xFF;
74 };
75
76 /** Structure that describes render pipeline blend states. Used for initializing BlendState. */
77 struct BS_CORE_EXPORT BLEND_STATE_DESC
78 {
79 bool operator==(const BLEND_STATE_DESC& rhs) const;
80
81 /**
82 * Alpha to coverage allows you to perform blending without needing to worry about order of rendering like regular
83 * blending does. It requires multi-sampling to be active in order to work, and you need to supply an alpha texture
84 * that determines object transparency.
85 *
86 * Blending is then performed by only using sub-samples covered by the alpha texture for the current pixel and
87 * combining them with sub-samples previously stored.
88 *
89 * Be aware this is a limited technique only useful for certain situations. Unless you are having performance
90 * problems use regular blending.
91 */
92 bool alphaToCoverageEnable = false;
93
94 /**
95 * When not set, only the first render target blend descriptor will be used for all render targets. If set each
96 * render target will use its own blend descriptor.
97 */
98 bool independantBlendEnable = false;
99
100 RENDER_TARGET_BLEND_STATE_DESC renderTargetDesc[BS_MAX_MULTIPLE_RENDER_TARGETS];
101 };
102
103 /** Properties of a BlendState. Shared between sim and core thread versions of BlendState. */
104 class BS_CORE_EXPORT BlendProperties
105 {
106 public:
107 BlendProperties(const BLEND_STATE_DESC& desc);
108
109 /** @copydoc BLEND_STATE_DESC::alphaToCoverageEnable */
110 bool getAlphaToCoverageEnabled() const { return mData.alphaToCoverageEnable; }
111
112 /** @copydoc BLEND_STATE_DESC::independantBlendEnable */
113 bool getIndependantBlendEnable() const { return mData.independantBlendEnable; }
114
115 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::blendEnable */
116 bool getBlendEnabled(UINT32 renderTargetIdx) const;
117
118 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::srcBlend */
119 BlendFactor getSrcBlend(UINT32 renderTargetIdx) const;
120
121 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::dstBlend */
122 BlendFactor getDstBlend(UINT32 renderTargetIdx) const;
123
124 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::blendOp */
125 BlendOperation getBlendOperation(UINT32 renderTargetIdx) const;
126
127 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::srcBlendAlpha */
128 BlendFactor getAlphaSrcBlend(UINT32 renderTargetIdx) const;
129
130 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::dstBlendAlpha */
131 BlendFactor getAlphaDstBlend(UINT32 renderTargetIdx) const;
132
133 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::blendOpAlpha */
134 BlendOperation getAlphaBlendOperation(UINT32 renderTargetIdx) const;
135
136 /** @copydoc RENDER_TARGET_BLEND_STATE_DESC::renderTargetWriteMask */
137 UINT8 getRenderTargetWriteMask(UINT32 renderTargetIdx) const;
138
139 /** Returns the hash value generated from the blend state properties. */
140 UINT64 getHash() const { return mHash; }
141
142 protected:
143 friend class BlendState;
144 friend class ct::BlendState;
145 friend class BlendStateRTTI;
146
147 BLEND_STATE_DESC mData;
148 UINT64 mHash;
149 };
150
151 /**
152 * Render system pipeline state that allows you to modify how an object is rendered. More exactly this state allows to
153 * you to control how is a rendered object blended with any previously rendered objects.
154 *
155 * @note Blend states are immutable. Sim thread only.
156 */
157 class BS_CORE_EXPORT BlendState : public IReflectable, public CoreObject
158 {
159 public:
160 virtual ~BlendState();
161
162 /** Returns information about a blend state. */
163 const BlendProperties& getProperties() const;
164
165 /** Retrieves a core implementation of the sampler state usable only from the core thread. */
166 SPtr<ct::BlendState> getCore() const;
167
168 /** Creates a new blend state using the specified blend state description structure. */
169 static SPtr<BlendState> create(const BLEND_STATE_DESC& desc);
170
171 /** Returns the default blend state that you may use when no other is available. */
172 static const SPtr<BlendState>& getDefault();
173
174 /** Generates a hash value from a blend state descriptor. */
175 static UINT64 generateHash(const BLEND_STATE_DESC& desc);
176
177 protected:
178 friend class RenderStateManager;
179
180 BlendState(const BLEND_STATE_DESC& desc);
181
182 /** @copydoc CoreObject::createCore */
183 SPtr<ct::CoreObject> createCore() const override;
184
185 BlendProperties mProperties;
186 mutable UINT32 mId;
187
188 /************************************************************************/
189 /* RTTI */
190 /************************************************************************/
191
192 public:
193 friend class BlendStateRTTI;
194 static RTTITypeBase* getRTTIStatic();
195 RTTITypeBase* getRTTI() const override;
196 };
197
198 /** @} */
199
200 namespace ct
201 {
202 /** @addtogroup RenderAPI-Internal
203 * @{
204 */
205
206 /**
207 * Core thread version of bs::BlendState.
208 *
209 * @note Core thread.
210 */
211 class BS_CORE_EXPORT BlendState : public CoreObject
212 {
213 public:
214 virtual ~BlendState();
215
216 /** Returns information about the blend state. */
217 const BlendProperties& getProperties() const;
218
219 /** Returns a unique state ID. Only the lowest 10 bits are used. */
220 UINT32 getId() const { return mId; }
221
222 /** Creates a new blend state using the specified blend state description structure. */
223 static SPtr<BlendState> create(const BLEND_STATE_DESC& desc);
224
225 /** Returns the default blend state that you may use when no other is available. */
226 static const SPtr<BlendState>& getDefault();
227
228 protected:
229 friend class RenderStateManager;
230
231 BlendState(const BLEND_STATE_DESC& desc, UINT32 id);
232
233 /** @copydoc CoreObject::initialize */
234 void initialize() override;
235
236 /** Creates any API-specific state objects. */
237 virtual void createInternal() { }
238
239 BlendProperties mProperties;
240 UINT32 mId;
241 };
242
243 /** @} */
244 }
245
246 /** @cond SPECIALIZATIONS */
247 /** @addtogroup RTTI-Impl-Core
248 * @{
249 */
250
251 template<> struct RTTIPlainType<BLEND_STATE_DESC>
252 {
253 enum { id = TID_BLEND_STATE_DESC }; enum { hasDynamicSize = 1 };
254
255 static void toMemory(const BLEND_STATE_DESC& data, char* memory)
256 {
257 UINT32 size = getDynamicSize(data);
258
259 memcpy(memory, &size, sizeof(UINT32));
260 memory += sizeof(UINT32);
261 size -= sizeof(UINT32);
262 memcpy(memory, &data, size);
263 }
264
265 static UINT32 fromMemory(BLEND_STATE_DESC& data, char* memory)
266 {
267 UINT32 size;
268 memcpy(&size, memory, sizeof(UINT32));
269 memory += sizeof(UINT32);
270
271 UINT32 dataSize = size - sizeof(UINT32);
272 memcpy((void*)&data, memory, dataSize);
273
274 return size;
275 }
276
277 static UINT32 getDynamicSize(const BLEND_STATE_DESC& data)
278 {
279 UINT64 dataSize = sizeof(data) + sizeof(UINT32);
280
281#if BS_DEBUG_MODE
282 if(dataSize > std::numeric_limits<UINT32>::max())
283 {
284 BS_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
285 }
286#endif
287
288 return (UINT32)dataSize;
289 }
290 };
291
292 /** @} */
293 /** @endcond */
294}
295
296/** @cond STDLIB */
297/** @addtogroup RenderAPI
298 * @{
299 */
300
301namespace std
302{
303/** Hash value generator for BLEND_STATE_DESC. */
304template<>
305struct hash<bs::BLEND_STATE_DESC>
306{
307 size_t operator()(const bs::BLEND_STATE_DESC& value) const
308 {
309 return (size_t)bs::BlendState::generateHash(value);
310 }
311};
312}
313
314/** @} */
315/** @endcond */
316