added linear, circular, angular gradient texture creation helpers
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<uint8_t> 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<uint8_t> data(width * height);
|
||||
|
||||
@@ -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<wi::texturehelper::GradientFlags> {
|
||||
static const bool enable = true;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user