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 "Reflection/BsIReflectable.h"
7#include "CoreThread/BsCoreObject.h"
8#include "Math/BsVector3.h"
9#include "Math/BsQuaternion.h"
10#include "Math/BsSphere.h"
11#include "Scene/BsSceneActor.h"
12
13namespace bs
14{
15 /** @addtogroup Renderer-Internal
16 * @{
17 */
18
19 /** Probe type that determines the shape of the probe and how is it interpreted by the renderer. */
20 enum BS_SCRIPT_EXPORT(m:Rendering) class ReflectionProbeType
21 {
22 /**
23 * Reflection probe cubemap is generated, and box extents are used for calculating influence ranges and box
24 * geometry.
25 */
26 Box,
27 /**
28 * Reflection probe cubemap is generated, but sphere is used for calculating the influence radius and
29 * proxy geometry.
30 */
31 Sphere
32 };
33
34 /** @} */
35
36 /** @addtogroup Implementation
37 * @{
38 */
39
40 /** Base class for both core and sim thread implementations of a reflection probe. */
41 class BS_CORE_EXPORT ReflectionProbeBase : public SceneActor
42 {
43 public:
44 ReflectionProbeBase() = default;
45 ReflectionProbeBase(ReflectionProbeType type, float radius, const Vector3& extents);
46 virtual ~ReflectionProbeBase() = default;
47
48 /** Returns the type of the probe. */
49 ReflectionProbeType getType() const { return mType; }
50
51 /** Changes the type of the probe. */
52 void setType(ReflectionProbeType type) { mType = type; _markCoreDirty(); updateBounds(); }
53
54 /** Returns the radius of a sphere reflection probe. Determines range of influence. */
55 float getRadius() const;
56
57 /** Sets the radius of a sphere reflection probe. */
58 void setRadius(float radius) { mRadius = radius; _markCoreDirty(); updateBounds(); }
59
60 /** Returns the extents of a box reflection probe. */
61 Vector3 getExtents() const { return mExtents * mTransform.getScale(); }
62
63 /** Sets the extents of a box reflection probe. Determines range of influence. */
64 void setExtents(const Vector3& extents) { mExtents = extents; _markCoreDirty(); updateBounds(); }
65
66 /** Returns world space bounds that completely encompass the probe's area of influence. */
67 Sphere getBounds() const { return mBounds; }
68
69 /**
70 * Sets a distance that will be used for fading out the box reflection probe with distance. By default it
71 * is equal to one, and can never be less than one. Only relevant for box probes.
72 */
73 void setTransitionDistance(float distance) { mTransitionDistance = std::max(1.0f, distance); }
74
75 /** Retrieves transition distance set by setTransitionDistance(). */
76 float getTransitionDistance() const { return mTransitionDistance; }
77
78 protected:
79 /** Updates the internal bounds for the probe. Call this whenever a property affecting the bounds changes. */
80 void updateBounds();
81
82 ReflectionProbeType mType = ReflectionProbeType::Box; /**< Type of probe that determines how are the rest of the parameters interpreted. */
83 float mRadius = 1.0f; /**< Radius used for sphere reflection probes. */
84 Vector3 mExtents = { 1.0f, 1.0f, 1.0f }; /**< Extents used by box reflection probe. */
85 float mTransitionDistance = 0.1f; /**< Extra distance to used for fading out box probes. */
86
87 Sphere mBounds = { Vector3::ZERO, 1.0f }; /**< Sphere that bounds the probe area of influence. */
88 };
89
90 /** Templated base class for both core and sim thread implementations of a reflection probe. */
91 template<bool Core>
92 class BS_CORE_EXPORT TReflectionProbe : public ReflectionProbeBase
93 {
94 public:
95 using TextureType = CoreVariantType<Texture, Core>;
96
97 TReflectionProbe() = default;
98 TReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents)
99 :ReflectionProbeBase(type, radius, extents)
100 { }
101 virtual ~TReflectionProbe() = default;
102
103 /**
104 * Returns a pre-filtered texture that is generated either from the provided custom texture, or from scene capture.
105 */
106 SPtr<TextureType> getFilteredTexture() const { return mFilteredTexture; }
107
108 /** Enumerates all the fields in the type and executes the specified processor action for each field. */
109 template<class P>
110 void rttiEnumFields(P p);
111
112 protected:
113 SPtr<TextureType> mFilteredTexture;
114 };
115
116 /** @} */
117 /** @addtogroup Renderer-Internal
118 * @{
119 */
120
121 namespace ct
122 {
123 class RendererTask;
124 class ReflectionProbe;
125 }
126
127 /**
128 * Specifies a location at which a pre-computed texture containing scene radiance will be generated. This texture will
129 * then be used by the renderer to provide specular reflections.
130 */
131 class BS_CORE_EXPORT ReflectionProbe : public IReflectable, public CoreObject, public TReflectionProbe<false>
132 {
133 public:
134 ~ReflectionProbe();
135
136 /**
137 * Allows you assign a custom texture to use as a reflection map. This will disable automatic generation of
138 * reflections. To re-enable auto-generation call this with a null parameter.
139 */
140 void setCustomTexture(const HTexture& texture) { mCustomTexture = texture; filter(); }
141
142 /** Gets the custom texture assigned through setCustomTexture(). */
143 HTexture getCustomTexture() const { return mCustomTexture; }
144
145 /**
146 * Captures the scene at the current location and generates a filtered reflection cubemap. No action is taken
147 * if a custom texture is set.
148 */
149 void capture();
150
151 /**
152 * Filters the custom texture, making it usable for rendering. Called automatically when custom texture changes. If
153 * no custom texture is set, no action is taken.
154 */
155 void filter();
156
157 /** Retrieves an implementation of the reflection probe usable only from the core thread. */
158 SPtr<ct::ReflectionProbe> getCore() const;
159
160 /**
161 * Creates a new sphere reflection probe.
162 *
163 * @param[in] radius Radius in which the reflection probe will be rendered within.
164 * @returns New reflection probe.
165 */
166 static SPtr<ReflectionProbe> createSphere(float radius);
167
168 /**
169 * Creates a new box reflection probe.
170 *
171 * @param[in] extents Extents of the box in which the reflection probe will be rendered within.
172 * @returns New reflection probe.
173 */
174 static SPtr<ReflectionProbe> createBox(const Vector3& extents);
175
176 protected:
177 ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents);
178
179 /** @copydoc CoreObject::createCore */
180 SPtr<ct::CoreObject> createCore() const override;
181
182 /** @copydoc ReflectionProbeBase::_markCoreDirty */
183 void _markCoreDirty(ActorDirtyFlag flags = ActorDirtyFlag::Everything) override;
184
185 /** @copydoc CoreObject::syncToCore */
186 CoreSyncData syncToCore(FrameAlloc* allocator) override;
187
188 /**
189 * Captures the scene color at current probe location and generates a filtered map. If a custom texture is set then
190 * it will be filtered, instead of capturing scene color.
191 */
192 void captureAndFilter();
193
194 /** Creates a probe with without initializing it. Used for serialization. */
195 static SPtr<ReflectionProbe> createEmpty();
196
197 HTexture mCustomTexture;
198 SPtr<ct::RendererTask> mRendererTask;
199
200 /************************************************************************/
201 /* RTTI */
202 /************************************************************************/
203 public:
204 friend class ReflectionProbeRTTI;
205 static RTTITypeBase* getRTTIStatic();
206 RTTITypeBase* getRTTI() const override;
207
208 protected:
209 ReflectionProbe() = default; // Serialization only
210 };
211
212 namespace ct
213 {
214 /** Core thread usable version of a bs::ReflectionProbe */
215 class BS_CORE_EXPORT ReflectionProbe : public CoreObject, public TReflectionProbe<true>
216 {
217 public:
218 ~ReflectionProbe();
219
220 /** Sets an ID that can be used for uniquely identifying this object by the renderer. */
221 void setRendererId(UINT32 id) { mRendererId = id; }
222
223 /** Retrieves an ID that can be used for uniquely identifying this object by the renderer. */
224 UINT32 getRendererId() const { return mRendererId; }
225
226 protected:
227 friend class bs::ReflectionProbe;
228
229 ReflectionProbe(ReflectionProbeType type, float radius, const Vector3& extents,
230 const SPtr<Texture>& filteredTexture);
231
232 /** @copydoc CoreObject::initialize */
233 void initialize() override;
234
235 /** @copydoc CoreObject::syncToCore */
236 void syncToCore(const CoreSyncData& data) override;
237
238 UINT32 mRendererId;
239 };
240 }
241
242 /** @} */
243}
244