Diligent Engine  v.2.4.g
FilteringTools.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
30 #include "../../Platforms/interface/PlatformDefinitions.h"
31 
32 #include "BasicMath.hpp"
33 
34 #include "../../Graphics/GraphicsEngine/interface/Sampler.h"
35 
36 namespace Diligent
37 {
38 
40 //
41 // w
42 // | - - - - - >|
43 // -----X-------|-------X-------|----*--X-------|-------X
44 // i0-1.5 i0+0.5 i1+0.5 i1+1.5
45 //
46 // T[*] = lerp(T[i0], T[i1], w)
47 //
49 {
50  union
51  {
52  struct
53  {
56 
59  };
60 
62  Int32 i[2];
63  };
64 
66  float w = 0.f;
67 
69  i0{0},
70  i1{0}
71  {}
72 
73  LinearTexFilterSampleInfo(Int32 _i0, Int32 _i1, float _w) noexcept :
74  i0{_i0},
75  i1{_i1},
76  w{_w}
77  {
78  }
79 
80  bool operator==(const LinearTexFilterSampleInfo& rhs) const
81  {
82  return i0 == rhs.i0 && i1 == rhs.i1 && w == rhs.w;
83  }
84 
85  bool operator!=(const LinearTexFilterSampleInfo& rhs) const
86  {
87  return !(*this == rhs);
88  }
89 };
90 
99 template <TEXTURE_ADDRESS_MODE AddressMode, bool IsNormalizedCoord>
101 {
102  float x = IsNormalizedCoord ? u * static_cast<float>(Width) : u;
103  float x0 = FastFloor(x - 0.5f);
104 
105  // clang-format off
106  LinearTexFilterSampleInfo SampleInfo
107  {
108  static_cast<Int32>(x0),
109  static_cast<Int32>(x0 + 1),
110  x - 0.5f - x0
111  };
112  // clang-format on
113 
114  auto WrapCoord = [](Int32 i, Uint32 Width) //
115  {
116  auto w = static_cast<Int32>(Width);
117 
118  // Note that the sign of a%b is implementation-dependent when one of the operands is negative.
119  // a/b, to the contrary, is always well-defined.
120  i = i - (i / w) * w;
121  return i < 0 ? i + w : i;
122  };
123 
124  auto MirrorCoord = [WrapCoord](Int32 i, Uint32 Width) //
125  {
126  i = WrapCoord(i, Width * 2);
127 
128  auto w = static_cast<Int32>(Width);
129  return i >= w ? (w * 2 - 1) - i : i;
130  };
131 
132  switch (AddressMode)
133  {
135  // do nothing
136  break;
137 
139  SampleInfo.i0 = WrapCoord(SampleInfo.i0, Width);
140  SampleInfo.i1 = WrapCoord(SampleInfo.i1, Width);
141  break;
142 
144  SampleInfo.i0 = MirrorCoord(SampleInfo.i0, Width);
145  SampleInfo.i1 = MirrorCoord(SampleInfo.i1, Width);
146  break;
147 
149  SampleInfo.i0 = clamp(SampleInfo.i0, 0, static_cast<Int32>(Width - 1));
150  SampleInfo.i1 = clamp(SampleInfo.i1, 0, static_cast<Int32>(Width - 1));
151  break;
152 
153  default:
154  UNEXPECTED("Unexpected texture address mode");
155  }
156 
157  return SampleInfo;
158 }
159 
160 #ifdef DILIGENT_DEBUG
161 template <TEXTURE_ADDRESS_MODE AddressMode>
162 void _DbgVerifyFilterInfo(const LinearTexFilterSampleInfo& FilterInfo, Uint32 Width, const char* Direction, float u)
163 {
164 }
165 
166 template <>
167 inline void _DbgVerifyFilterInfo<TEXTURE_ADDRESS_UNKNOWN>(const LinearTexFilterSampleInfo& FilterInfo, Uint32 Width, const char* Direction, float u)
168 {
169  VERIFY(FilterInfo.i0 >= 0 && FilterInfo.i0 < static_cast<Int32>(Width), "First ", Direction, " sample index (", FilterInfo.i0,
170  ") is out of allowed range [0, ", Width - 1, "]. Correct sample coordinate (", u, ") or use one of the texture address modes.");
171  VERIFY(FilterInfo.i1 >= 0 && FilterInfo.i1 < static_cast<Int32>(Width), "Second ", Direction, " sample index (", FilterInfo.i1,
172  ") is out of allowed range [0, ", Width - 1, "]. Correct sample coordinate (", u, ") or use one of the texture address modes.");
173 }
174 #endif
175 
191 template <typename SrcType,
192  typename DstType,
193  TEXTURE_ADDRESS_MODE AddressModeU,
194  TEXTURE_ADDRESS_MODE AddressModeV,
195  bool IsNormalizedCoord>
197  Uint32 Height,
198  const SrcType* pData,
199  size_t Stride,
200  float u,
201  float v)
202 {
203  auto UFilterInfo = GetLinearTexFilterSampleInfo<AddressModeU, IsNormalizedCoord>(Width, u);
204  auto VFilterInfo = GetLinearTexFilterSampleInfo<AddressModeV, IsNormalizedCoord>(Height, v);
205 
206 #ifdef DILIGENT_DEBUG
207  {
208  _DbgVerifyFilterInfo<AddressModeU>(UFilterInfo, Width, "horizontal", u);
209  _DbgVerifyFilterInfo<AddressModeV>(VFilterInfo, Height, "horizontal", v);
210  }
211 #endif
212 
213  auto S00 = static_cast<DstType>(pData[UFilterInfo.i0 + VFilterInfo.i0 * Stride]);
214  auto S10 = static_cast<DstType>(pData[UFilterInfo.i1 + VFilterInfo.i0 * Stride]);
215  auto S01 = static_cast<DstType>(pData[UFilterInfo.i0 + VFilterInfo.i1 * Stride]);
216  auto S11 = static_cast<DstType>(pData[UFilterInfo.i1 + VFilterInfo.i1 * Stride]);
217  return lerp(lerp(S00, S10, UFilterInfo.w), lerp(S01, S11, UFilterInfo.w), VFilterInfo.w);
218 }
219 
222 template <typename SrcType, typename DstType>
224  Uint32 Height,
225  const SrcType* pData,
226  size_t Stride,
227  float u,
228  float v)
229 
230 {
231  return FilterTexture2DBilinear<SrcType, DstType, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, true>(Width, Height, pData, Stride, u, v);
232 }
233 
236 template <typename SrcType, typename DstType>
238  Uint32 Height,
239  const SrcType* pData,
240  size_t Stride,
241  float u,
242  float v)
243 
244 {
245  return FilterTexture2DBilinear<SrcType, DstType, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, false>(Width, Height, pData, Stride, u, v);
246 }
247 
248 } // namespace Diligent
Diligent::LinearTexFilterSampleInfo::i
Int32 i[2]
Sample indices.
Definition: FilteringTools.hpp:62
Diligent::LinearTexFilterSampleInfo::LinearTexFilterSampleInfo
LinearTexFilterSampleInfo() noexcept
Definition: FilteringTools.hpp:68
Diligent::FilterTexture2DBilinearClampUC
DstType FilterTexture2DBilinearClampUC(Uint32 Width, Uint32 Height, const SrcType *pData, size_t Stride, float u, float v)
Specialization of FilterTexture2DBilinear function that uses CLAMP texture address mode and takes unn...
Definition: FilteringTools.hpp:237
Diligent::FilterTexture2DBilinear
DstType FilterTexture2DBilinear(Uint32 Width, Uint32 Height, const SrcType *pData, size_t Stride, float u, float v)
Samples 2D texture using bilinear filter.
Definition: FilteringTools.hpp:196
Diligent::TEXTURE_ADDRESS_MODE
TEXTURE_ADDRESS_MODE
Texture address mode.
Definition: GraphicsTypes.h:889
BasicMath.hpp
Diligent::LinearTexFilterSampleInfo::w
float w
Blend weight.
Definition: FilteringTools.hpp:66
UNEXPECTED
#define UNEXPECTED(...)
Definition: DebugUtilities.hpp:77
Diligent::LinearTexFilterSampleInfo::LinearTexFilterSampleInfo
LinearTexFilterSampleInfo(Int32 _i0, Int32 _i1, float _w) noexcept
Definition: FilteringTools.hpp:73
Diligent::clamp
T clamp(T val, T _min, T _max)
Definition: BasicMath.hpp:1700
Diligent::Int32
int32_t Int32
32-bit signed integer
Definition: BasicTypes.h:46
Diligent::FilterTexture2DBilinearClamp
DstType FilterTexture2DBilinearClamp(Uint32 Width, Uint32 Height, const SrcType *pData, size_t Stride, float u, float v)
Specialization of FilterTexture2DBilinear function that uses CLAMP texture address mode and takes nor...
Definition: FilteringTools.hpp:223
Diligent::LinearTexFilterSampleInfo::i0
Int32 i0
First sample index.
Definition: FilteringTools.hpp:55
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
Diligent::TEXTURE_ADDRESS_MIRROR
@ TEXTURE_ADDRESS_MIRROR
Flip the texture at every integer junction. Direct3D Counterpart: D3D11_TEXTURE_ADDRESS_MIRROR/D3D1...
Definition: GraphicsTypes.h:900
Diligent::lerp
T lerp(const T &Left, const T &Right, float w)
Definition: BasicMath.hpp:2023
Diligent::LinearTexFilterSampleInfo::i1
Int32 i1
Second sample index.
Definition: FilteringTools.hpp:58
Diligent::FastFloor
T FastFloor(T x)
Definition: BasicMath.hpp:2093
Diligent::TEXTURE_ADDRESS_UNKNOWN
@ TEXTURE_ADDRESS_UNKNOWN
Unknown mode.
Definition: GraphicsTypes.h:892
Diligent::GetLinearTexFilterSampleInfo
LinearTexFilterSampleInfo GetLinearTexFilterSampleInfo(Uint32 Width, float u)
Returns linear texture filter sample info, see Diligent::LinearTexFilterSampleInfo.
Definition: FilteringTools.hpp:100
Diligent::LinearTexFilterSampleInfo
Linear texture filter sample info.
Definition: FilteringTools.hpp:48
Diligent::TEXTURE_ADDRESS_CLAMP
@ TEXTURE_ADDRESS_CLAMP
Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0....
Definition: GraphicsTypes.h:905
VERIFY
#define VERIFY(...)
Definition: DebugUtilities.hpp:76
Diligent::LinearTexFilterSampleInfo::operator==
bool operator==(const LinearTexFilterSampleInfo &rhs) const
Definition: FilteringTools.hpp:80
Diligent::LinearTexFilterSampleInfo::operator!=
bool operator!=(const LinearTexFilterSampleInfo &rhs) const
Definition: FilteringTools.hpp:85
Diligent::TEXTURE_ADDRESS_WRAP
@ TEXTURE_ADDRESS_WRAP
Tile the texture at every integer junction. Direct3D Counterpart: D3D11_TEXTURE_ADDRESS_WRAP/D3D12_...
Definition: GraphicsTypes.h:896
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37