mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
[Fix] (MG_Util/Texture): expand channels and convert component types on texture unpack to the internal shadow layout
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/RenderStateEnumConverter.h>
|
||||
#include <MG_Util/Math/HalfFloat.h>
|
||||
#include <MG_Util/Metrics/BufferMetrics.h>
|
||||
#include <MG_Util/Texture/PixelStoreProcessor.h>
|
||||
#include <Config.h>
|
||||
@@ -3270,62 +3271,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// wide RGBA format into scratch memory and repack into the caller's (format, type) layout on the CPU,
|
||||
// honoring the client-side PACK pixel-store parameters.
|
||||
|
||||
static Float DecodeHalfBitsToFloat(Uint16 half) {
|
||||
const Uint32 sign = static_cast<Uint32>(half & 0x8000u) << 16;
|
||||
const Uint32 exponent = (half >> 10) & 0x1Fu;
|
||||
const Uint32 mantissa = half & 0x3FFu;
|
||||
Uint32 bits;
|
||||
if (exponent == 0) {
|
||||
if (mantissa == 0) {
|
||||
bits = sign; // signed zero
|
||||
} else {
|
||||
// Subnormal half: renormalize into a float exponent.
|
||||
Uint32 e = 127 - 15 + 1;
|
||||
Uint32 m = mantissa;
|
||||
while ((m & 0x400u) == 0) {
|
||||
m <<= 1;
|
||||
--e;
|
||||
}
|
||||
bits = sign | (e << 23) | ((m & 0x3FFu) << 13);
|
||||
}
|
||||
} else if (exponent == 31) {
|
||||
bits = sign | 0x7F800000u | (mantissa << 13); // Inf / NaN
|
||||
} else {
|
||||
bits = sign | ((exponent + 112) << 23) | (mantissa << 13);
|
||||
}
|
||||
return std::bit_cast<Float>(bits);
|
||||
}
|
||||
|
||||
static Uint16 EncodeFloatToHalfBits(Float value) {
|
||||
const Uint32 bits = std::bit_cast<Uint32>(value);
|
||||
const auto sign = static_cast<Uint16>((bits >> 16) & 0x8000u);
|
||||
const Uint32 exponent = (bits >> 23) & 0xFFu;
|
||||
const Uint32 mantissa = bits & 0x7FFFFFu;
|
||||
if (exponent == 0xFF) { // Inf / NaN
|
||||
return static_cast<Uint16>(sign | 0x7C00u | (mantissa != 0 ? 0x200u : 0u));
|
||||
}
|
||||
const Int32 halfExponent = static_cast<Int32>(exponent) - 127 + 15;
|
||||
if (halfExponent >= 31) {
|
||||
return static_cast<Uint16>(sign | 0x7C00u); // overflow -> Inf
|
||||
}
|
||||
if (halfExponent <= 0) {
|
||||
if (halfExponent < -10) {
|
||||
return sign; // underflow -> signed zero
|
||||
}
|
||||
const Uint32 m = mantissa | 0x800000u;
|
||||
const Uint32 shift = static_cast<Uint32>(14 - halfExponent);
|
||||
Uint32 half = m >> shift;
|
||||
if ((m >> (shift - 1)) & 1u) {
|
||||
++half; // round to nearest
|
||||
}
|
||||
return static_cast<Uint16>(sign | half);
|
||||
}
|
||||
Uint32 half = (static_cast<Uint32>(halfExponent) << 10) | (mantissa >> 13);
|
||||
if (mantissa & 0x1000u) {
|
||||
++half; // round to nearest; a carry into the exponent is the correct result
|
||||
}
|
||||
return static_cast<Uint16>(sign | half);
|
||||
}
|
||||
using MG_Util::DecodeHalfBitsToFloat;
|
||||
using MG_Util::EncodeFloatToHalfBits;
|
||||
|
||||
struct ReadbackChannelMapping {
|
||||
Int sourceChannel[4]; // RGBA source channel feeding each destination channel
|
||||
|
||||
Reference in New Issue
Block a user