diff --git a/WickedEngine/wiMath.h b/WickedEngine/wiMath.h index eb25de78d..5d19da123 100644 --- a/WickedEngine/wiMath.h +++ b/WickedEngine/wiMath.h @@ -115,6 +115,18 @@ namespace wi::math { return (pos - value1) / (value2 - value1); } + constexpr XMFLOAT2 InverseLerp(const XMFLOAT2& value1, const XMFLOAT2& value2, const XMFLOAT2& pos) + { + return XMFLOAT2(InverseLerp(value1.x, value2.x, pos.x), InverseLerp(value1.y, value2.y, pos.y)); + } + constexpr XMFLOAT3 InverseLerp(const XMFLOAT3& value1, const XMFLOAT3& value2, const XMFLOAT3& pos) + { + return XMFLOAT3(InverseLerp(value1.x, value2.x, pos.x), InverseLerp(value1.y, value2.y, pos.y), InverseLerp(value1.z, value2.z, pos.z)); + } + constexpr XMFLOAT4 InverseLerp(const XMFLOAT4& value1, const XMFLOAT4& value2, const XMFLOAT4& pos) + { + return XMFLOAT4(InverseLerp(value1.x, value2.x, pos.x), InverseLerp(value1.y, value2.y, pos.y), InverseLerp(value1.z, value2.z, pos.z), InverseLerp(value1.w, value2.w, pos.w)); + } constexpr float Lerp(float value1, float value2, float amount) { return value1 + (value2 - value1) * amount; diff --git a/WickedEngine/wiTextureHelper.cpp b/WickedEngine/wiTextureHelper.cpp index c4e7d2dc2..10154cc19 100644 --- a/WickedEngine/wiTextureHelper.cpp +++ b/WickedEngine/wiTextureHelper.cpp @@ -244,12 +244,12 @@ namespace wi::texturehelper bool CreateTexture( - wi::graphics::Texture& texture, + Texture& texture, const uint8_t* data, uint32_t width, uint32_t height, Format format, - wi::graphics::Swizzle swizzle + Swizzle swizzle ) { if (data == nullptr) @@ -275,12 +275,112 @@ namespace wi::texturehelper return device->CreateTexture(&desc, &InitData, &texture); } - wi::graphics::Texture CreateCircularProgressGradientTexture( + Texture CreateGradientTexture( + GradientType type, + uint32_t width, + uint32_t height, + const XMFLOAT2& uv_start, + const XMFLOAT2& uv_end, + GradientFlags flags, + Swizzle swizzle + ) + { + wi::vector data(width * height); + + switch (type) + { + default: + case GradientType::Linear: + { + const XMVECTOR a = XMLoadFloat2(&uv_start); + const XMVECTOR b = XMLoadFloat2(&uv_end); + const float distance = XMVectorGetX(XMVector3Length(b - a)); + for (uint32_t y = 0; y < height; ++y) + { + for (uint32_t x = 0; x < width; ++x) + { + const XMFLOAT2 uv = XMFLOAT2(float(x) / float(width - 1), float(y) / float(height - 1)); + const XMVECTOR point_on_line = wi::math::ClosestPointOnLineSegment(a, b, XMLoadFloat2(&uv)); + const float uv_distance = XMVectorGetX(XMVector3Length(point_on_line - a)); + float gradient = wi::math::saturate(wi::math::InverseLerp(0, distance, uv_distance)); + if (has_flag(flags, GradientFlags::Inverse)) + { + gradient = 1 - gradient; + } + if (has_flag(flags, GradientFlags::Smoothstep)) + { + gradient = wi::math::SmoothStep(0, 1, gradient); + } + data[x + y * width] = uint8_t(gradient * 255); + } + } + } + break; + + case GradientType::Circular: + { + const XMVECTOR a = XMLoadFloat2(&uv_start); + const XMVECTOR b = XMLoadFloat2(&uv_end); + const float distance = XMVectorGetX(XMVector3Length(b - a)); + for (uint32_t y = 0; y < height; ++y) + { + for (uint32_t x = 0; x < width; ++x) + { + const XMFLOAT2 uv = XMFLOAT2(float(x) / float(width - 1), float(y) / float(height - 1)); + const float uv_distance = wi::math::Clamp(XMVectorGetX(XMVector3Length(XMLoadFloat2(&uv) - a)), 0, distance); + float gradient = wi::math::saturate(wi::math::InverseLerp(0, distance, uv_distance)); + if (has_flag(flags, GradientFlags::Inverse)) + { + gradient = 1 - gradient; + } + if (has_flag(flags, GradientFlags::Smoothstep)) + { + gradient = wi::math::SmoothStep(0, 1, gradient); + } + data[x + y * width] = uint8_t(gradient * 255); + } + } + } + break; + + case GradientType::Angular: + { + XMFLOAT2 direction; + XMStoreFloat2(&direction, XMVector2Normalize(XMLoadFloat2(&uv_end) - XMLoadFloat2(&uv_start))); + for (uint32_t y = 0; y < height; ++y) + { + for (uint32_t x = 0; x < width; ++x) + { + const XMFLOAT2 uv = XMFLOAT2(float(x) / float(width - 1), float(y) / float(height - 1)); + const XMFLOAT2 coord = XMFLOAT2(uv.x - uv_start.x, uv.y - uv_start.y); + float gradient = wi::math::GetAngle(direction, coord) / XM_2PI; + if (has_flag(flags, GradientFlags::Inverse)) + { + gradient = 1 - gradient; + } + if (has_flag(flags, GradientFlags::Smoothstep)) + { + gradient = wi::math::SmoothStep(0, 1, gradient); + } + data[x + y * width] = uint8_t(gradient * 255); + } + } + } + break; + + } + + Texture texture; + CreateTexture(texture, data.data(), width, height, Format::R8_UNORM, swizzle); + return texture; + } + + Texture CreateCircularProgressGradientTexture( uint32_t width, uint32_t height, const XMFLOAT2& direction, bool counter_clockwise, - wi::graphics::Swizzle swizzle + Swizzle swizzle ) { wi::vector data(width * height); diff --git a/WickedEngine/wiTextureHelper.h b/WickedEngine/wiTextureHelper.h index 5c8432a72..9d56192aa 100644 --- a/WickedEngine/wiTextureHelper.h +++ b/WickedEngine/wiTextureHelper.h @@ -29,6 +29,29 @@ namespace wi::texturehelper wi::graphics::Swizzle swizzle = {} ); + enum class GradientType + { + Linear, + Circular, + Angular, + }; + enum class GradientFlags + { + None = 0, + Inverse = 1 << 0, // inverts resulting gradient + Smoothstep = 1 << 1 // applies smoothstep function to resulting gradient + }; + wi::graphics::Texture CreateGradientTexture( + GradientType type, + uint32_t width, + uint32_t height, + const XMFLOAT2& uv_start = XMFLOAT2(0, 0), + const XMFLOAT2& uv_end = XMFLOAT2(1, 0), + GradientFlags gradient_flags = GradientFlags::None, + wi::graphics::Swizzle swizzle = { wi::graphics::ComponentSwizzle::R, wi::graphics::ComponentSwizzle::R, wi::graphics::ComponentSwizzle::R, wi::graphics::ComponentSwizzle::R } + ); + + // Similar to CreateGradientTexture() with GradientType::Angular type but different parameters wi::graphics::Texture CreateCircularProgressGradientTexture( uint32_t width, uint32_t height, @@ -38,3 +61,7 @@ namespace wi::texturehelper ); }; +template<> +struct enable_bitmask_operators { + static const bool enable = true; +}; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b844b67bb..578185600 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 243; + const int revision = 244; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);