diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/clipper.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/pica_types.h | 156 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 4 |
5 files changed, 82 insertions, 116 deletions
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp index 3a09d62f4..a385589d2 100644 --- a/src/video_core/clipper.cpp +++ b/src/video_core/clipper.cpp | |||
| @@ -59,12 +59,12 @@ static void InitScreenCoordinates(OutputVertex& vtx) | |||
| 59 | } viewport; | 59 | } viewport; |
| 60 | 60 | ||
| 61 | const auto& regs = g_state.regs; | 61 | const auto& regs = g_state.regs; |
| 62 | viewport.halfsize_x = float24::FromRawFloat24(regs.viewport_size_x); | 62 | viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x); |
| 63 | viewport.halfsize_y = float24::FromRawFloat24(regs.viewport_size_y); | 63 | viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y); |
| 64 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); | 64 | viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); |
| 65 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); | 65 | viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); |
| 66 | viewport.zscale = float24::FromRawFloat24(regs.viewport_depth_range); | 66 | viewport.zscale = float24::FromRaw(regs.viewport_depth_range); |
| 67 | viewport.offset_z = float24::FromRawFloat24(regs.viewport_depth_far_plane); | 67 | viewport.offset_z = float24::FromRaw(regs.viewport_depth_far_plane); |
| 68 | 68 | ||
| 69 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; | 69 | float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; |
| 70 | vtx.color *= inv_w; | 70 | vtx.color *= inv_w; |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 6540ccb26..5dfedfe31 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp | |||
| @@ -98,10 +98,10 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 98 | Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; | 98 | Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; |
| 99 | 99 | ||
| 100 | // NOTE: The destination component order indeed is "backwards" | 100 | // NOTE: The destination component order indeed is "backwards" |
| 101 | attribute.w = float24::FromRawFloat24(default_attr_write_buffer[0] >> 8); | 101 | attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8); |
| 102 | attribute.z = float24::FromRawFloat24(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF)); | 102 | attribute.z = float24::FromRaw(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF)); |
| 103 | attribute.y = float24::FromRawFloat24(((default_attr_write_buffer[1] & 0xFFFF) << 8) | ((default_attr_write_buffer[2] >> 24) & 0xFF)); | 103 | attribute.y = float24::FromRaw(((default_attr_write_buffer[1] & 0xFFFF) << 8) | ((default_attr_write_buffer[2] >> 24) & 0xFF)); |
| 104 | attribute.x = float24::FromRawFloat24(default_attr_write_buffer[2] & 0xFFFFFF); | 104 | attribute.x = float24::FromRaw(default_attr_write_buffer[2] & 0xFFFFFF); |
| 105 | 105 | ||
| 106 | LOG_TRACE(HW_GPU, "Set default VS attribute %x to (%f %f %f %f)", (int)setup.index, | 106 | LOG_TRACE(HW_GPU, "Set default VS attribute %x to (%f %f %f %f)", (int)setup.index, |
| 107 | attribute.x.ToFloat32(), attribute.y.ToFloat32(), attribute.z.ToFloat32(), | 107 | attribute.x.ToFloat32(), attribute.y.ToFloat32(), attribute.z.ToFloat32(), |
| @@ -418,10 +418,10 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 418 | uniform[3 - i] = float24::FromFloat32(*(float*)(&uniform_write_buffer[i])); | 418 | uniform[3 - i] = float24::FromFloat32(*(float*)(&uniform_write_buffer[i])); |
| 419 | } else { | 419 | } else { |
| 420 | // TODO: Untested | 420 | // TODO: Untested |
| 421 | uniform.w = float24::FromRawFloat24(uniform_write_buffer[0] >> 8); | 421 | uniform.w = float24::FromRaw(uniform_write_buffer[0] >> 8); |
| 422 | uniform.z = float24::FromRawFloat24(((uniform_write_buffer[0] & 0xFF)<<16) | ((uniform_write_buffer[1] >> 16) & 0xFFFF)); | 422 | uniform.z = float24::FromRaw(((uniform_write_buffer[0] & 0xFF) << 16) | ((uniform_write_buffer[1] >> 16) & 0xFFFF)); |
| 423 | uniform.y = float24::FromRawFloat24(((uniform_write_buffer[1] & 0xFFFF)<<8) | ((uniform_write_buffer[2] >> 24) & 0xFF)); | 423 | uniform.y = float24::FromRaw(((uniform_write_buffer[1] & 0xFFFF) << 8) | ((uniform_write_buffer[2] >> 24) & 0xFF)); |
| 424 | uniform.x = float24::FromRawFloat24(uniform_write_buffer[2] & 0xFFFFFF); | 424 | uniform.x = float24::FromRaw(uniform_write_buffer[2] & 0xFFFFFF); |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | LOG_TRACE(HW_GPU, "Set uniform %x to (%f %f %f %f)", (int)uniform_setup.index, | 427 | LOG_TRACE(HW_GPU, "Set uniform %x to (%f %f %f %f)", (int)uniform_setup.index, |
diff --git a/src/video_core/pica_types.h b/src/video_core/pica_types.h index a34421c5d..53f61f287 100644 --- a/src/video_core/pica_types.h +++ b/src/video_core/pica_types.h | |||
| @@ -4,35 +4,51 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstring> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | 10 | ||
| 9 | namespace Pica { | 11 | namespace Pica { |
| 10 | 12 | ||
| 11 | struct float24 { | 13 | /** |
| 12 | static float24 FromFloat32(float val) { | 14 | * Template class for converting arbitrary Pica float types to IEEE 754 32-bit single-precision |
| 13 | float24 ret; | 15 | * floating point. |
| 16 | * | ||
| 17 | * When decoding, format is as follows: | ||
| 18 | * - The first `M` bits are the mantissa | ||
| 19 | * - The next `E` bits are the exponent | ||
| 20 | * - The last bit is the sign bit | ||
| 21 | * | ||
| 22 | * @todo Verify on HW if this conversion is sufficently accurate. | ||
| 23 | */ | ||
| 24 | template<unsigned M, unsigned E> | ||
| 25 | struct Float { | ||
| 26 | public: | ||
| 27 | static Float<M, E> FromFloat32(float val) { | ||
| 28 | Float<M, E> ret; | ||
| 14 | ret.value = val; | 29 | ret.value = val; |
| 15 | return ret; | 30 | return ret; |
| 16 | } | 31 | } |
| 17 | 32 | ||
| 18 | // 16 bit mantissa, 7 bit exponent, 1 bit sign | 33 | static Float<M, E> FromRaw(u32 hex) { |
| 19 | // TODO: No idea if this works as intended | 34 | Float<M, E> res; |
| 20 | static float24 FromRawFloat24(u32 hex) { | 35 | |
| 21 | float24 ret; | 36 | const int width = M + E + 1; |
| 22 | if ((hex & 0xFFFFFF) == 0) { | 37 | const int bias = 128 - (1 << (E - 1)); |
| 23 | ret.value = 0; | 38 | const int exponent = (hex >> M) & ((1 << E) - 1); |
| 24 | } else { | 39 | const unsigned mantissa = hex & ((1 << M) - 1); |
| 25 | u32 mantissa = hex & 0xFFFF; | 40 | |
| 26 | u32 exponent = (hex >> 16) & 0x7F; | 41 | if (hex & ((1 << (width - 1)) - 1)) |
| 27 | u32 sign = hex >> 23; | 42 | hex = ((hex >> (E + M)) << 31) | (mantissa << (23 - M)) | ((exponent + bias) << 23); |
| 28 | ret.value = std::pow(2.0f, (float)exponent-63.0f) * (1.0f + mantissa * std::pow(2.0f, -16.f)); | 43 | else |
| 29 | if (sign) | 44 | hex = ((hex >> (E + M)) << 31); |
| 30 | ret.value = -ret.value; | 45 | |
| 31 | } | 46 | std::memcpy(&res.value, &hex, sizeof(float)); |
| 32 | return ret; | 47 | |
| 48 | return res; | ||
| 33 | } | 49 | } |
| 34 | 50 | ||
| 35 | static float24 Zero() { | 51 | static Float<M, E> Zero() { |
| 36 | return FromFloat32(0.f); | 52 | return FromFloat32(0.f); |
| 37 | } | 53 | } |
| 38 | 54 | ||
| @@ -41,27 +57,27 @@ struct float24 { | |||
| 41 | return value; | 57 | return value; |
| 42 | } | 58 | } |
| 43 | 59 | ||
| 44 | float24 operator * (const float24& flt) const { | 60 | Float<M, E> operator * (const Float<M, E>& flt) const { |
| 45 | if ((this->value == 0.f && !std::isnan(flt.value)) || | 61 | if ((this->value == 0.f && !std::isnan(flt.value)) || |
| 46 | (flt.value == 0.f && !std::isnan(this->value))) | 62 | (flt.value == 0.f && !std::isnan(this->value))) |
| 47 | // PICA gives 0 instead of NaN when multiplying by inf | 63 | // PICA gives 0 instead of NaN when multiplying by inf |
| 48 | return Zero(); | 64 | return Zero(); |
| 49 | return float24::FromFloat32(ToFloat32() * flt.ToFloat32()); | 65 | return Float<M, E>::FromFloat32(ToFloat32() * flt.ToFloat32()); |
| 50 | } | 66 | } |
| 51 | 67 | ||
| 52 | float24 operator / (const float24& flt) const { | 68 | Float<M, E> operator / (const Float<M, E>& flt) const { |
| 53 | return float24::FromFloat32(ToFloat32() / flt.ToFloat32()); | 69 | return Float<M, E>::FromFloat32(ToFloat32() / flt.ToFloat32()); |
| 54 | } | 70 | } |
| 55 | 71 | ||
| 56 | float24 operator + (const float24& flt) const { | 72 | Float<M, E> operator + (const Float<M, E>& flt) const { |
| 57 | return float24::FromFloat32(ToFloat32() + flt.ToFloat32()); | 73 | return Float<M, E>::FromFloat32(ToFloat32() + flt.ToFloat32()); |
| 58 | } | 74 | } |
| 59 | 75 | ||
| 60 | float24 operator - (const float24& flt) const { | 76 | Float<M, E> operator - (const Float<M, E>& flt) const { |
| 61 | return float24::FromFloat32(ToFloat32() - flt.ToFloat32()); | 77 | return Float<M, E>::FromFloat32(ToFloat32() - flt.ToFloat32()); |
| 62 | } | 78 | } |
| 63 | 79 | ||
| 64 | float24& operator *= (const float24& flt) { | 80 | Float<M, E>& operator *= (const Float<M, E>& flt) { |
| 65 | if ((this->value == 0.f && !std::isnan(flt.value)) || | 81 | if ((this->value == 0.f && !std::isnan(flt.value)) || |
| 66 | (flt.value == 0.f && !std::isnan(this->value))) | 82 | (flt.value == 0.f && !std::isnan(this->value))) |
| 67 | // PICA gives 0 instead of NaN when multiplying by inf | 83 | // PICA gives 0 instead of NaN when multiplying by inf |
| @@ -70,111 +86,61 @@ struct float24 { | |||
| 70 | return *this; | 86 | return *this; |
| 71 | } | 87 | } |
| 72 | 88 | ||
| 73 | float24& operator /= (const float24& flt) { | 89 | Float<M, E>& operator /= (const Float<M, E>& flt) { |
| 74 | value /= flt.ToFloat32(); | 90 | value /= flt.ToFloat32(); |
| 75 | return *this; | 91 | return *this; |
| 76 | } | 92 | } |
| 77 | 93 | ||
| 78 | float24& operator += (const float24& flt) { | 94 | Float<M, E>& operator += (const Float<M, E>& flt) { |
| 79 | value += flt.ToFloat32(); | 95 | value += flt.ToFloat32(); |
| 80 | return *this; | 96 | return *this; |
| 81 | } | 97 | } |
| 82 | 98 | ||
| 83 | float24& operator -= (const float24& flt) { | 99 | Float<M, E>& operator -= (const Float<M, E>& flt) { |
| 84 | value -= flt.ToFloat32(); | 100 | value -= flt.ToFloat32(); |
| 85 | return *this; | 101 | return *this; |
| 86 | } | 102 | } |
| 87 | 103 | ||
| 88 | float24 operator - () const { | 104 | Float<M, E> operator - () const { |
| 89 | return float24::FromFloat32(-ToFloat32()); | 105 | return Float<M, E>::FromFloat32(-ToFloat32()); |
| 90 | } | 106 | } |
| 91 | 107 | ||
| 92 | bool operator < (const float24& flt) const { | 108 | bool operator < (const Float<M, E>& flt) const { |
| 93 | return ToFloat32() < flt.ToFloat32(); | 109 | return ToFloat32() < flt.ToFloat32(); |
| 94 | } | 110 | } |
| 95 | 111 | ||
| 96 | bool operator > (const float24& flt) const { | 112 | bool operator > (const Float<M, E>& flt) const { |
| 97 | return ToFloat32() > flt.ToFloat32(); | 113 | return ToFloat32() > flt.ToFloat32(); |
| 98 | } | 114 | } |
| 99 | 115 | ||
| 100 | bool operator >= (const float24& flt) const { | 116 | bool operator >= (const Float<M, E>& flt) const { |
| 101 | return ToFloat32() >= flt.ToFloat32(); | 117 | return ToFloat32() >= flt.ToFloat32(); |
| 102 | } | 118 | } |
| 103 | 119 | ||
| 104 | bool operator <= (const float24& flt) const { | 120 | bool operator <= (const Float<M, E>& flt) const { |
| 105 | return ToFloat32() <= flt.ToFloat32(); | 121 | return ToFloat32() <= flt.ToFloat32(); |
| 106 | } | 122 | } |
| 107 | 123 | ||
| 108 | bool operator == (const float24& flt) const { | 124 | bool operator == (const Float<M, E>& flt) const { |
| 109 | return ToFloat32() == flt.ToFloat32(); | 125 | return ToFloat32() == flt.ToFloat32(); |
| 110 | } | 126 | } |
| 111 | 127 | ||
| 112 | bool operator != (const float24& flt) const { | 128 | bool operator != (const Float<M, E>& flt) const { |
| 113 | return ToFloat32() != flt.ToFloat32(); | 129 | return ToFloat32() != flt.ToFloat32(); |
| 114 | } | 130 | } |
| 115 | 131 | ||
| 116 | private: | 132 | private: |
| 117 | // Stored as a regular float, merely for convenience | 133 | static const unsigned MASK = (1 << (M + E + 1)) - 1; |
| 118 | // TODO: Perform proper arithmetic on this! | 134 | static const unsigned MANTISSA_MASK = (1 << M) - 1; |
| 119 | float value; | 135 | static const unsigned EXPONENT_MASK = (1 << E) - 1; |
| 120 | }; | ||
| 121 | |||
| 122 | static_assert(sizeof(float24) == sizeof(float), "Shader JIT assumes float24 is implemented as a 32-bit float"); | ||
| 123 | |||
| 124 | struct float16 { | ||
| 125 | // 10 bit mantissa, 5 bit exponent, 1 bit sign | ||
| 126 | // TODO: No idea if this works as intended | ||
| 127 | static float16 FromRawFloat16(u32 hex) { | ||
| 128 | float16 ret; | ||
| 129 | if ((hex & 0xFFFF) == 0) { | ||
| 130 | ret.value = 0; | ||
| 131 | } else { | ||
| 132 | u32 mantissa = hex & 0x3FF; | ||
| 133 | u32 exponent = (hex >> 10) & 0x1F; | ||
| 134 | u32 sign = (hex >> 15) & 1; | ||
| 135 | ret.value = std::pow(2.0f, (float)exponent - 15.0f) * (1.0f + mantissa * std::pow(2.0f, -10.f)); | ||
| 136 | if (sign) | ||
| 137 | ret.value = -ret.value; | ||
| 138 | } | ||
| 139 | return ret; | ||
| 140 | } | ||
| 141 | |||
| 142 | float ToFloat32() const { | ||
| 143 | return value; | ||
| 144 | } | ||
| 145 | 136 | ||
| 146 | private: | ||
| 147 | // Stored as a regular float, merely for convenience | 137 | // Stored as a regular float, merely for convenience |
| 148 | // TODO: Perform proper arithmetic on this! | 138 | // TODO: Perform proper arithmetic on this! |
| 149 | float value; | 139 | float value; |
| 150 | }; | 140 | }; |
| 151 | 141 | ||
| 152 | struct float20 { | 142 | using float24 = Float<16, 7>; |
| 153 | // 12 bit mantissa, 7 bit exponent, 1 bit sign | 143 | using float20 = Float<12, 7>; |
| 154 | // TODO: No idea if this works as intended | 144 | using float16 = Float<10, 5>; |
| 155 | static float20 FromRawFloat20(u32 hex) { | ||
| 156 | float20 ret; | ||
| 157 | if ((hex & 0xFFFFF) == 0) { | ||
| 158 | ret.value = 0; | ||
| 159 | } else { | ||
| 160 | u32 mantissa = hex & 0xFFF; | ||
| 161 | u32 exponent = (hex >> 12) & 0x7F; | ||
| 162 | u32 sign = (hex >> 19) & 1; | ||
| 163 | ret.value = std::pow(2.0f, (float)exponent - 63.0f) * (1.0f + mantissa * std::pow(2.0f, -12.f)); | ||
| 164 | if (sign) | ||
| 165 | ret.value = -ret.value; | ||
| 166 | } | ||
| 167 | return ret; | ||
| 168 | } | ||
| 169 | |||
| 170 | float ToFloat32() const { | ||
| 171 | return value; | ||
| 172 | } | ||
| 173 | |||
| 174 | private: | ||
| 175 | // Stored as a regular float, merely for convenience | ||
| 176 | // TODO: Perform proper arithmetic on this! | ||
| 177 | float value; | ||
| 178 | }; | ||
| 179 | 145 | ||
| 180 | } // namespace Pica | 146 | } // namespace Pica |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 6e7d6a40d..d70d62ede 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -810,8 +810,8 @@ void RasterizerOpenGL::SyncCullMode() { | |||
| 810 | } | 810 | } |
| 811 | 811 | ||
| 812 | void RasterizerOpenGL::SyncDepthModifiers() { | 812 | void RasterizerOpenGL::SyncDepthModifiers() { |
| 813 | float depth_scale = -Pica::float24::FromRawFloat24(Pica::g_state.regs.viewport_depth_range).ToFloat32(); | 813 | float depth_scale = -Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_range).ToFloat32(); |
| 814 | float depth_offset = Pica::float24::FromRawFloat24(Pica::g_state.regs.viewport_depth_far_plane).ToFloat32() / 2.0f; | 814 | float depth_offset = Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_far_plane).ToFloat32() / 2.0f; |
| 815 | 815 | ||
| 816 | // TODO: Implement scale modifier | 816 | // TODO: Implement scale modifier |
| 817 | uniform_block_data.data.depth_offset = depth_offset; | 817 | uniform_block_data.data.depth_offset = depth_offset; |
| @@ -948,9 +948,9 @@ void RasterizerOpenGL::SyncLightAmbient(int light_index) { | |||
| 948 | 948 | ||
| 949 | void RasterizerOpenGL::SyncLightPosition(int light_index) { | 949 | void RasterizerOpenGL::SyncLightPosition(int light_index) { |
| 950 | std::array<GLfloat, 3> position = { | 950 | std::array<GLfloat, 3> position = { |
| 951 | Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(), | 951 | Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(), |
| 952 | Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(), | 952 | Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(), |
| 953 | Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32() }; | 953 | Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32() }; |
| 954 | 954 | ||
| 955 | if (position != uniform_block_data.data.light_src[light_index].position) { | 955 | if (position != uniform_block_data.data.light_src[light_index].position) { |
| 956 | uniform_block_data.data.light_src[light_index].position = position; | 956 | uniform_block_data.data.light_src[light_index].position = position; |
| @@ -962,8 +962,8 @@ void RasterizerOpenGL::SyncDrawState() { | |||
| 962 | const auto& regs = Pica::g_state.regs; | 962 | const auto& regs = Pica::g_state.regs; |
| 963 | 963 | ||
| 964 | // Sync the viewport | 964 | // Sync the viewport |
| 965 | GLsizei viewport_width = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_x).ToFloat32() * 2; | 965 | GLsizei viewport_width = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_x).ToFloat32() * 2; |
| 966 | GLsizei viewport_height = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_y).ToFloat32() * 2; | 966 | GLsizei viewport_height = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_y).ToFloat32() * 2; |
| 967 | 967 | ||
| 968 | // OpenGL uses different y coordinates, so negate corner offset and flip origin | 968 | // OpenGL uses different y coordinates, so negate corner offset and flip origin |
| 969 | // TODO: Ensure viewport_corner.x should not be negated or origin flipped | 969 | // TODO: Ensure viewport_corner.x should not be negated or origin flipped |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 4e681f9ea..b9c1d61bd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -83,8 +83,8 @@ struct PicaShaderConfig { | |||
| 83 | res.lighting.light[light_index].directional = light.directional != 0; | 83 | res.lighting.light[light_index].directional = light.directional != 0; |
| 84 | res.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; | 84 | res.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; |
| 85 | res.lighting.light[light_index].dist_atten_enable = regs.lighting.IsDistAttenEnabled(num); | 85 | res.lighting.light[light_index].dist_atten_enable = regs.lighting.IsDistAttenEnabled(num); |
| 86 | res.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRawFloat20(light.dist_atten_bias).ToFloat32(); | 86 | res.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32(); |
| 87 | res.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRawFloat20(light.dist_atten_scale).ToFloat32(); | 87 | res.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | res.lighting.lut_d0.enable = regs.lighting.lut_enable_d0 == 0; | 90 | res.lighting.lut_d0.enable = regs.lighting.lut_enable_d0 == 0; |