diff options
| author | 2017-01-28 12:13:21 -0800 | |
|---|---|---|
| committer | 2017-02-04 13:59:11 -0800 | |
| commit | f443c7e5b0721d706f80f3eab567b0b6abd4f14b (patch) | |
| tree | b188ae150a41860f519119ff82d639f71a776eb5 /src | |
| parent | VideoCore: Split framebuffer regs from Regs struct (diff) | |
| download | yuzu-f443c7e5b0721d706f80f3eab567b0b6abd4f14b.tar.gz yuzu-f443c7e5b0721d706f80f3eab567b0b6abd4f14b.tar.xz yuzu-f443c7e5b0721d706f80f3eab567b0b6abd4f14b.zip | |
VideoCore: Split lighting regs from Regs struct
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/pica.h | 278 | ||||
| -rw-r--r-- | src/video_core/regs_lighting.h | 292 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 72 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/pica_to_gl.h | 2 |
6 files changed, 341 insertions, 312 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 718c709e5..3c6ea42be 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -33,6 +33,7 @@ set(HEADERS | |||
| 33 | rasterizer.h | 33 | rasterizer.h |
| 34 | rasterizer_interface.h | 34 | rasterizer_interface.h |
| 35 | regs_framebuffer.h | 35 | regs_framebuffer.h |
| 36 | regs_lighting.h | ||
| 36 | regs_rasterizer.h | 37 | regs_rasterizer.h |
| 37 | regs_texturing.h | 38 | regs_texturing.h |
| 38 | renderer_base.h | 39 | renderer_base.h |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 50a549c42..371bcdb84 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "common/logging/log.h" | 19 | #include "common/logging/log.h" |
| 20 | #include "common/vector_math.h" | 20 | #include "common/vector_math.h" |
| 21 | #include "video_core/regs_framebuffer.h" | 21 | #include "video_core/regs_framebuffer.h" |
| 22 | #include "video_core/regs_lighting.h" | ||
| 22 | #include "video_core/regs_rasterizer.h" | 23 | #include "video_core/regs_rasterizer.h" |
| 23 | #include "video_core/regs_texturing.h" | 24 | #include "video_core/regs_texturing.h" |
| 24 | 25 | ||
| @@ -53,281 +54,7 @@ struct Regs { | |||
| 53 | RasterizerRegs rasterizer; | 54 | RasterizerRegs rasterizer; |
| 54 | TexturingRegs texturing; | 55 | TexturingRegs texturing; |
| 55 | FramebufferRegs framebuffer; | 56 | FramebufferRegs framebuffer; |
| 56 | 57 | LightingRegs lighting; | |
| 57 | enum class LightingSampler { | ||
| 58 | Distribution0 = 0, | ||
| 59 | Distribution1 = 1, | ||
| 60 | Fresnel = 3, | ||
| 61 | ReflectBlue = 4, | ||
| 62 | ReflectGreen = 5, | ||
| 63 | ReflectRed = 6, | ||
| 64 | SpotlightAttenuation = 8, | ||
| 65 | DistanceAttenuation = 16, | ||
| 66 | }; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Pica fragment lighting supports using different LUTs for each lighting component: | ||
| 70 | * Reflectance R, G, and B channels, distribution function for specular components 0 and 1, | ||
| 71 | * fresnel factor, and spotlight attenuation. Furthermore, which LUTs are used for each channel | ||
| 72 | * (or whether a channel is enabled at all) is specified by various pre-defined lighting | ||
| 73 | * configurations. With configurations that require more LUTs, more cycles are required on HW to | ||
| 74 | * perform lighting computations. | ||
| 75 | */ | ||
| 76 | enum class LightingConfig { | ||
| 77 | Config0 = 0, ///< Reflect Red, Distribution 0, Spotlight | ||
| 78 | Config1 = 1, ///< Reflect Red, Fresnel, Spotlight | ||
| 79 | Config2 = 2, ///< Reflect Red, Distribution 0/1 | ||
| 80 | Config3 = 3, ///< Distribution 0/1, Fresnel | ||
| 81 | Config4 = 4, ///< Reflect Red/Green/Blue, Distribution 0/1, Spotlight | ||
| 82 | Config5 = 5, ///< Reflect Red/Green/Blue, Distribution 0, Fresnel, Spotlight | ||
| 83 | Config6 = 6, ///< Reflect Red, Distribution 0/1, Fresnel, Spotlight | ||
| 84 | Config7 = 8, ///< Reflect Red/Green/Blue, Distribution 0/1, Fresnel, Spotlight | ||
| 85 | ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration | ||
| 86 | }; | ||
| 87 | |||
| 88 | /// Selects which lighting components are affected by fresnel | ||
| 89 | enum class LightingFresnelSelector { | ||
| 90 | None = 0, ///< Fresnel is disabled | ||
| 91 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel | ||
| 92 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel | ||
| 93 | Both = | ||
| 94 | PrimaryAlpha | | ||
| 95 | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | ||
| 96 | }; | ||
| 97 | |||
| 98 | /// Factor used to scale the output of a lighting LUT | ||
| 99 | enum class LightingScale { | ||
| 100 | Scale1 = 0, ///< Scale is 1x | ||
| 101 | Scale2 = 1, ///< Scale is 2x | ||
| 102 | Scale4 = 2, ///< Scale is 4x | ||
| 103 | Scale8 = 3, ///< Scale is 8x | ||
| 104 | Scale1_4 = 6, ///< Scale is 0.25x | ||
| 105 | Scale1_2 = 7, ///< Scale is 0.5x | ||
| 106 | }; | ||
| 107 | |||
| 108 | enum class LightingLutInput { | ||
| 109 | NH = 0, // Cosine of the angle between the normal and half-angle vectors | ||
| 110 | VH = 1, // Cosine of the angle between the view and half-angle vectors | ||
| 111 | NV = 2, // Cosine of the angle between the normal and the view vector | ||
| 112 | LN = 3, // Cosine of the angle between the light and the normal vectors | ||
| 113 | }; | ||
| 114 | |||
| 115 | enum class LightingBumpMode : u32 { | ||
| 116 | None = 0, | ||
| 117 | NormalMap = 1, | ||
| 118 | TangentMap = 2, | ||
| 119 | }; | ||
| 120 | |||
| 121 | union LightColor { | ||
| 122 | BitField<0, 10, u32> b; | ||
| 123 | BitField<10, 10, u32> g; | ||
| 124 | BitField<20, 10, u32> r; | ||
| 125 | |||
| 126 | Math::Vec3f ToVec3f() const { | ||
| 127 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color | ||
| 128 | // component | ||
| 129 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | ||
| 130 | } | ||
| 131 | }; | ||
| 132 | |||
| 133 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting | ||
| 134 | /// configuration | ||
| 135 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { | ||
| 136 | switch (sampler) { | ||
| 137 | case LightingSampler::Distribution0: | ||
| 138 | return (config != LightingConfig::Config1); | ||
| 139 | |||
| 140 | case LightingSampler::Distribution1: | ||
| 141 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && | ||
| 142 | (config != LightingConfig::Config5); | ||
| 143 | |||
| 144 | case LightingSampler::Fresnel: | ||
| 145 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && | ||
| 146 | (config != LightingConfig::Config4); | ||
| 147 | |||
| 148 | case LightingSampler::ReflectRed: | ||
| 149 | return (config != LightingConfig::Config3); | ||
| 150 | |||
| 151 | case LightingSampler::ReflectGreen: | ||
| 152 | case LightingSampler::ReflectBlue: | ||
| 153 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || | ||
| 154 | (config == LightingConfig::Config7); | ||
| 155 | default: | ||
| 156 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " | ||
| 157 | "unreachable section, sampler should be one " | ||
| 158 | "of Distribution0, Distribution1, Fresnel, " | ||
| 159 | "ReflectRed, ReflectGreen or ReflectBlue, instead " | ||
| 160 | "got %i", | ||
| 161 | static_cast<int>(config)); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | struct { | ||
| 166 | struct LightSrc { | ||
| 167 | LightColor specular_0; // material.specular_0 * light.specular_0 | ||
| 168 | LightColor specular_1; // material.specular_1 * light.specular_1 | ||
| 169 | LightColor diffuse; // material.diffuse * light.diffuse | ||
| 170 | LightColor ambient; // material.ambient * light.ambient | ||
| 171 | |||
| 172 | // Encoded as 16-bit floating point | ||
| 173 | union { | ||
| 174 | BitField<0, 16, u32> x; | ||
| 175 | BitField<16, 16, u32> y; | ||
| 176 | }; | ||
| 177 | union { | ||
| 178 | BitField<0, 16, u32> z; | ||
| 179 | }; | ||
| 180 | |||
| 181 | INSERT_PADDING_WORDS(0x3); | ||
| 182 | |||
| 183 | union { | ||
| 184 | BitField<0, 1, u32> directional; | ||
| 185 | BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 | ||
| 186 | } config; | ||
| 187 | |||
| 188 | BitField<0, 20, u32> dist_atten_bias; | ||
| 189 | BitField<0, 20, u32> dist_atten_scale; | ||
| 190 | |||
| 191 | INSERT_PADDING_WORDS(0x4); | ||
| 192 | }; | ||
| 193 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), | ||
| 194 | "LightSrc structure must be 0x10 words"); | ||
| 195 | |||
| 196 | LightSrc light[8]; | ||
| 197 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) | ||
| 198 | INSERT_PADDING_WORDS(0x1); | ||
| 199 | BitField<0, 3, u32> max_light_index; // Number of enabled lights - 1 | ||
| 200 | |||
| 201 | union { | ||
| 202 | BitField<2, 2, LightingFresnelSelector> fresnel_selector; | ||
| 203 | BitField<4, 4, LightingConfig> config; | ||
| 204 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | ||
| 205 | BitField<27, 1, u32> clamp_highlights; | ||
| 206 | BitField<28, 2, LightingBumpMode> bump_mode; | ||
| 207 | BitField<30, 1, u32> disable_bump_renorm; | ||
| 208 | } config0; | ||
| 209 | |||
| 210 | union { | ||
| 211 | BitField<16, 1, u32> disable_lut_d0; | ||
| 212 | BitField<17, 1, u32> disable_lut_d1; | ||
| 213 | BitField<19, 1, u32> disable_lut_fr; | ||
| 214 | BitField<20, 1, u32> disable_lut_rr; | ||
| 215 | BitField<21, 1, u32> disable_lut_rg; | ||
| 216 | BitField<22, 1, u32> disable_lut_rb; | ||
| 217 | |||
| 218 | // Each bit specifies whether distance attenuation should be applied for the | ||
| 219 | // corresponding light | ||
| 220 | |||
| 221 | BitField<24, 1, u32> disable_dist_atten_light_0; | ||
| 222 | BitField<25, 1, u32> disable_dist_atten_light_1; | ||
| 223 | BitField<26, 1, u32> disable_dist_atten_light_2; | ||
| 224 | BitField<27, 1, u32> disable_dist_atten_light_3; | ||
| 225 | BitField<28, 1, u32> disable_dist_atten_light_4; | ||
| 226 | BitField<29, 1, u32> disable_dist_atten_light_5; | ||
| 227 | BitField<30, 1, u32> disable_dist_atten_light_6; | ||
| 228 | BitField<31, 1, u32> disable_dist_atten_light_7; | ||
| 229 | } config1; | ||
| 230 | |||
| 231 | bool IsDistAttenDisabled(unsigned index) const { | ||
| 232 | const unsigned disable[] = { | ||
| 233 | config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, | ||
| 234 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, | ||
| 235 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, | ||
| 236 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7}; | ||
| 237 | return disable[index] != 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | union { | ||
| 241 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT | ||
| 242 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data | ||
| 243 | } lut_config; | ||
| 244 | |||
| 245 | BitField<0, 1, u32> disable; | ||
| 246 | INSERT_PADDING_WORDS(0x1); | ||
| 247 | |||
| 248 | // When data is written to any of these registers, it gets written to the lookup table of | ||
| 249 | // the selected type at the selected index, specified above in the `lut_config` register. | ||
| 250 | // With each write, `lut_config.index` is incremented. It does not matter which of these | ||
| 251 | // registers is written to, the behavior will be the same. | ||
| 252 | u32 lut_data[8]; | ||
| 253 | |||
| 254 | // These are used to specify if absolute (abs) value should be used for each LUT index. When | ||
| 255 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in | ||
| 256 | // the range of (0.0, 1.0). | ||
| 257 | union { | ||
| 258 | BitField<1, 1, u32> disable_d0; | ||
| 259 | BitField<5, 1, u32> disable_d1; | ||
| 260 | BitField<9, 1, u32> disable_sp; | ||
| 261 | BitField<13, 1, u32> disable_fr; | ||
| 262 | BitField<17, 1, u32> disable_rb; | ||
| 263 | BitField<21, 1, u32> disable_rg; | ||
| 264 | BitField<25, 1, u32> disable_rr; | ||
| 265 | } abs_lut_input; | ||
| 266 | |||
| 267 | union { | ||
| 268 | BitField<0, 3, LightingLutInput> d0; | ||
| 269 | BitField<4, 3, LightingLutInput> d1; | ||
| 270 | BitField<8, 3, LightingLutInput> sp; | ||
| 271 | BitField<12, 3, LightingLutInput> fr; | ||
| 272 | BitField<16, 3, LightingLutInput> rb; | ||
| 273 | BitField<20, 3, LightingLutInput> rg; | ||
| 274 | BitField<24, 3, LightingLutInput> rr; | ||
| 275 | } lut_input; | ||
| 276 | |||
| 277 | union { | ||
| 278 | BitField<0, 3, LightingScale> d0; | ||
| 279 | BitField<4, 3, LightingScale> d1; | ||
| 280 | BitField<8, 3, LightingScale> sp; | ||
| 281 | BitField<12, 3, LightingScale> fr; | ||
| 282 | BitField<16, 3, LightingScale> rb; | ||
| 283 | BitField<20, 3, LightingScale> rg; | ||
| 284 | BitField<24, 3, LightingScale> rr; | ||
| 285 | |||
| 286 | static float GetScale(LightingScale scale) { | ||
| 287 | switch (scale) { | ||
| 288 | case LightingScale::Scale1: | ||
| 289 | return 1.0f; | ||
| 290 | case LightingScale::Scale2: | ||
| 291 | return 2.0f; | ||
| 292 | case LightingScale::Scale4: | ||
| 293 | return 4.0f; | ||
| 294 | case LightingScale::Scale8: | ||
| 295 | return 8.0f; | ||
| 296 | case LightingScale::Scale1_4: | ||
| 297 | return 0.25f; | ||
| 298 | case LightingScale::Scale1_2: | ||
| 299 | return 0.5f; | ||
| 300 | } | ||
| 301 | return 0.0f; | ||
| 302 | } | ||
| 303 | } lut_scale; | ||
| 304 | |||
| 305 | INSERT_PADDING_WORDS(0x6); | ||
| 306 | |||
| 307 | union { | ||
| 308 | // There are 8 light enable "slots", corresponding to the total number of lights | ||
| 309 | // supported by Pica. For N enabled lights (specified by register 0x1c2, or 'src_num' | ||
| 310 | // above), the first N slots below will be set to integers within the range of 0-7, | ||
| 311 | // corresponding to the actual light that is enabled for each slot. | ||
| 312 | |||
| 313 | BitField<0, 3, u32> slot_0; | ||
| 314 | BitField<4, 3, u32> slot_1; | ||
| 315 | BitField<8, 3, u32> slot_2; | ||
| 316 | BitField<12, 3, u32> slot_3; | ||
| 317 | BitField<16, 3, u32> slot_4; | ||
| 318 | BitField<20, 3, u32> slot_5; | ||
| 319 | BitField<24, 3, u32> slot_6; | ||
| 320 | BitField<28, 3, u32> slot_7; | ||
| 321 | |||
| 322 | unsigned GetNum(unsigned index) const { | ||
| 323 | const unsigned enable_slots[] = {slot_0, slot_1, slot_2, slot_3, | ||
| 324 | slot_4, slot_5, slot_6, slot_7}; | ||
| 325 | return enable_slots[index]; | ||
| 326 | } | ||
| 327 | } light_enable; | ||
| 328 | } lighting; | ||
| 329 | |||
| 330 | INSERT_PADDING_WORDS(0x26); | ||
| 331 | 58 | ||
| 332 | enum class VertexAttributeFormat : u64 { | 59 | enum class VertexAttributeFormat : u64 { |
| 333 | BYTE = 0, | 60 | BYTE = 0, |
| @@ -702,6 +429,7 @@ ASSERT_REG_POSITION(framebuffer.output_merger, 0x100); | |||
| 702 | ASSERT_REG_POSITION(framebuffer.framebuffer, 0x110); | 429 | ASSERT_REG_POSITION(framebuffer.framebuffer, 0x110); |
| 703 | 430 | ||
| 704 | ASSERT_REG_POSITION(lighting, 0x140); | 431 | ASSERT_REG_POSITION(lighting, 0x140); |
| 432 | |||
| 705 | ASSERT_REG_POSITION(vertex_attributes, 0x200); | 433 | ASSERT_REG_POSITION(vertex_attributes, 0x200); |
| 706 | ASSERT_REG_POSITION(index_array, 0x227); | 434 | ASSERT_REG_POSITION(index_array, 0x227); |
| 707 | ASSERT_REG_POSITION(num_vertices, 0x228); | 435 | ASSERT_REG_POSITION(num_vertices, 0x228); |
diff --git a/src/video_core/regs_lighting.h b/src/video_core/regs_lighting.h new file mode 100644 index 000000000..b14500ff7 --- /dev/null +++ b/src/video_core/regs_lighting.h | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace Pica { | ||
| 14 | |||
| 15 | struct LightingRegs { | ||
| 16 | enum class LightingSampler { | ||
| 17 | Distribution0 = 0, | ||
| 18 | Distribution1 = 1, | ||
| 19 | Fresnel = 3, | ||
| 20 | ReflectBlue = 4, | ||
| 21 | ReflectGreen = 5, | ||
| 22 | ReflectRed = 6, | ||
| 23 | SpotlightAttenuation = 8, | ||
| 24 | DistanceAttenuation = 16, | ||
| 25 | }; | ||
| 26 | |||
| 27 | /** | ||
| 28 | * Pica fragment lighting supports using different LUTs for each lighting component: Reflectance | ||
| 29 | * R, G, and B channels, distribution function for specular components 0 and 1, fresnel factor, | ||
| 30 | * and spotlight attenuation. Furthermore, which LUTs are used for each channel (or whether a | ||
| 31 | * channel is enabled at all) is specified by various pre-defined lighting configurations. With | ||
| 32 | * configurations that require more LUTs, more cycles are required on HW to perform lighting | ||
| 33 | * computations. | ||
| 34 | */ | ||
| 35 | enum class LightingConfig { | ||
| 36 | Config0 = 0, ///< Reflect Red, Distribution 0, Spotlight | ||
| 37 | Config1 = 1, ///< Reflect Red, Fresnel, Spotlight | ||
| 38 | Config2 = 2, ///< Reflect Red, Distribution 0/1 | ||
| 39 | Config3 = 3, ///< Distribution 0/1, Fresnel | ||
| 40 | Config4 = 4, ///< Reflect Red/Green/Blue, Distribution 0/1, Spotlight | ||
| 41 | Config5 = 5, ///< Reflect Red/Green/Blue, Distribution 0, Fresnel, Spotlight | ||
| 42 | Config6 = 6, ///< Reflect Red, Distribution 0/1, Fresnel, Spotlight | ||
| 43 | |||
| 44 | Config7 = 8, ///< Reflect Red/Green/Blue, Distribution 0/1, Fresnel, Spotlight | ||
| 45 | ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration | ||
| 46 | }; | ||
| 47 | |||
| 48 | /// Selects which lighting components are affected by fresnel | ||
| 49 | enum class LightingFresnelSelector { | ||
| 50 | None = 0, ///< Fresnel is disabled | ||
| 51 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel | ||
| 52 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel | ||
| 53 | Both = | ||
| 54 | PrimaryAlpha | | ||
| 55 | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | ||
| 56 | }; | ||
| 57 | |||
| 58 | /// Factor used to scale the output of a lighting LUT | ||
| 59 | enum class LightingScale { | ||
| 60 | Scale1 = 0, ///< Scale is 1x | ||
| 61 | Scale2 = 1, ///< Scale is 2x | ||
| 62 | Scale4 = 2, ///< Scale is 4x | ||
| 63 | Scale8 = 3, ///< Scale is 8x | ||
| 64 | |||
| 65 | Scale1_4 = 6, ///< Scale is 0.25x | ||
| 66 | Scale1_2 = 7, ///< Scale is 0.5x | ||
| 67 | }; | ||
| 68 | |||
| 69 | enum class LightingLutInput { | ||
| 70 | NH = 0, // Cosine of the angle between the normal and half-angle vectors | ||
| 71 | VH = 1, // Cosine of the angle between the view and half-angle vectors | ||
| 72 | NV = 2, // Cosine of the angle between the normal and the view vector | ||
| 73 | LN = 3, // Cosine of the angle between the light and the normal vectors | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum class LightingBumpMode : u32 { | ||
| 77 | None = 0, | ||
| 78 | NormalMap = 1, | ||
| 79 | TangentMap = 2, | ||
| 80 | }; | ||
| 81 | |||
| 82 | union LightColor { | ||
| 83 | BitField<0, 10, u32> b; | ||
| 84 | BitField<10, 10, u32> g; | ||
| 85 | BitField<20, 10, u32> r; | ||
| 86 | |||
| 87 | Math::Vec3f ToVec3f() const { | ||
| 88 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color | ||
| 89 | // component | ||
| 90 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | |||
| 94 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting | ||
| 95 | /// configuration | ||
| 96 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { | ||
| 97 | switch (sampler) { | ||
| 98 | case LightingSampler::Distribution0: | ||
| 99 | return (config != LightingConfig::Config1); | ||
| 100 | |||
| 101 | case LightingSampler::Distribution1: | ||
| 102 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && | ||
| 103 | (config != LightingConfig::Config5); | ||
| 104 | |||
| 105 | case LightingSampler::Fresnel: | ||
| 106 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && | ||
| 107 | (config != LightingConfig::Config4); | ||
| 108 | |||
| 109 | case LightingSampler::ReflectRed: | ||
| 110 | return (config != LightingConfig::Config3); | ||
| 111 | |||
| 112 | case LightingSampler::ReflectGreen: | ||
| 113 | case LightingSampler::ReflectBlue: | ||
| 114 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || | ||
| 115 | (config == LightingConfig::Config7); | ||
| 116 | default: | ||
| 117 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " | ||
| 118 | "unreachable section, sampler should be one " | ||
| 119 | "of Distribution0, Distribution1, Fresnel, " | ||
| 120 | "ReflectRed, ReflectGreen or ReflectBlue, instead " | ||
| 121 | "got %i", | ||
| 122 | static_cast<int>(config)); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | struct LightSrc { | ||
| 127 | LightColor specular_0; // material.specular_0 * light.specular_0 | ||
| 128 | LightColor specular_1; // material.specular_1 * light.specular_1 | ||
| 129 | LightColor diffuse; // material.diffuse * light.diffuse | ||
| 130 | LightColor ambient; // material.ambient * light.ambient | ||
| 131 | |||
| 132 | // Encoded as 16-bit floating point | ||
| 133 | union { | ||
| 134 | BitField<0, 16, u32> x; | ||
| 135 | BitField<16, 16, u32> y; | ||
| 136 | }; | ||
| 137 | union { | ||
| 138 | BitField<0, 16, u32> z; | ||
| 139 | }; | ||
| 140 | |||
| 141 | INSERT_PADDING_WORDS(0x3); | ||
| 142 | |||
| 143 | union { | ||
| 144 | BitField<0, 1, u32> directional; | ||
| 145 | BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 | ||
| 146 | } config; | ||
| 147 | |||
| 148 | BitField<0, 20, u32> dist_atten_bias; | ||
| 149 | BitField<0, 20, u32> dist_atten_scale; | ||
| 150 | |||
| 151 | INSERT_PADDING_WORDS(0x4); | ||
| 152 | }; | ||
| 153 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), "LightSrc structure must be 0x10 words"); | ||
| 154 | |||
| 155 | LightSrc light[8]; | ||
| 156 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) | ||
| 157 | INSERT_PADDING_WORDS(0x1); | ||
| 158 | BitField<0, 3, u32> max_light_index; // Number of enabled lights - 1 | ||
| 159 | |||
| 160 | union { | ||
| 161 | BitField<2, 2, LightingFresnelSelector> fresnel_selector; | ||
| 162 | BitField<4, 4, LightingConfig> config; | ||
| 163 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | ||
| 164 | BitField<27, 1, u32> clamp_highlights; | ||
| 165 | BitField<28, 2, LightingBumpMode> bump_mode; | ||
| 166 | BitField<30, 1, u32> disable_bump_renorm; | ||
| 167 | } config0; | ||
| 168 | |||
| 169 | union { | ||
| 170 | BitField<16, 1, u32> disable_lut_d0; | ||
| 171 | BitField<17, 1, u32> disable_lut_d1; | ||
| 172 | BitField<19, 1, u32> disable_lut_fr; | ||
| 173 | BitField<20, 1, u32> disable_lut_rr; | ||
| 174 | BitField<21, 1, u32> disable_lut_rg; | ||
| 175 | BitField<22, 1, u32> disable_lut_rb; | ||
| 176 | |||
| 177 | // Each bit specifies whether distance attenuation should be applied for the corresponding | ||
| 178 | // light. | ||
| 179 | BitField<24, 1, u32> disable_dist_atten_light_0; | ||
| 180 | BitField<25, 1, u32> disable_dist_atten_light_1; | ||
| 181 | BitField<26, 1, u32> disable_dist_atten_light_2; | ||
| 182 | BitField<27, 1, u32> disable_dist_atten_light_3; | ||
| 183 | BitField<28, 1, u32> disable_dist_atten_light_4; | ||
| 184 | BitField<29, 1, u32> disable_dist_atten_light_5; | ||
| 185 | BitField<30, 1, u32> disable_dist_atten_light_6; | ||
| 186 | BitField<31, 1, u32> disable_dist_atten_light_7; | ||
| 187 | } config1; | ||
| 188 | |||
| 189 | bool IsDistAttenDisabled(unsigned index) const { | ||
| 190 | const unsigned disable[] = { | ||
| 191 | config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, | ||
| 192 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, | ||
| 193 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, | ||
| 194 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7}; | ||
| 195 | return disable[index] != 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | union { | ||
| 199 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT | ||
| 200 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data | ||
| 201 | } lut_config; | ||
| 202 | |||
| 203 | BitField<0, 1, u32> disable; | ||
| 204 | INSERT_PADDING_WORDS(0x1); | ||
| 205 | |||
| 206 | // When data is written to any of these registers, it gets written to the lookup table of the | ||
| 207 | // selected type at the selected index, specified above in the `lut_config` register. With each | ||
| 208 | // write, `lut_config.index` is incremented. It does not matter which of these registers is | ||
| 209 | // written to, the behavior will be the same. | ||
| 210 | u32 lut_data[8]; | ||
| 211 | |||
| 212 | // These are used to specify if absolute (abs) value should be used for each LUT index. When | ||
| 213 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in | ||
| 214 | // the range of (0.0, 1.0). | ||
| 215 | union { | ||
| 216 | BitField<1, 1, u32> disable_d0; | ||
| 217 | BitField<5, 1, u32> disable_d1; | ||
| 218 | BitField<9, 1, u32> disable_sp; | ||
| 219 | BitField<13, 1, u32> disable_fr; | ||
| 220 | BitField<17, 1, u32> disable_rb; | ||
| 221 | BitField<21, 1, u32> disable_rg; | ||
| 222 | BitField<25, 1, u32> disable_rr; | ||
| 223 | } abs_lut_input; | ||
| 224 | |||
| 225 | union { | ||
| 226 | BitField<0, 3, LightingLutInput> d0; | ||
| 227 | BitField<4, 3, LightingLutInput> d1; | ||
| 228 | BitField<8, 3, LightingLutInput> sp; | ||
| 229 | BitField<12, 3, LightingLutInput> fr; | ||
| 230 | BitField<16, 3, LightingLutInput> rb; | ||
| 231 | BitField<20, 3, LightingLutInput> rg; | ||
| 232 | BitField<24, 3, LightingLutInput> rr; | ||
| 233 | } lut_input; | ||
| 234 | |||
| 235 | union { | ||
| 236 | BitField<0, 3, LightingScale> d0; | ||
| 237 | BitField<4, 3, LightingScale> d1; | ||
| 238 | BitField<8, 3, LightingScale> sp; | ||
| 239 | BitField<12, 3, LightingScale> fr; | ||
| 240 | BitField<16, 3, LightingScale> rb; | ||
| 241 | BitField<20, 3, LightingScale> rg; | ||
| 242 | BitField<24, 3, LightingScale> rr; | ||
| 243 | |||
| 244 | static float GetScale(LightingScale scale) { | ||
| 245 | switch (scale) { | ||
| 246 | case LightingScale::Scale1: | ||
| 247 | return 1.0f; | ||
| 248 | case LightingScale::Scale2: | ||
| 249 | return 2.0f; | ||
| 250 | case LightingScale::Scale4: | ||
| 251 | return 4.0f; | ||
| 252 | case LightingScale::Scale8: | ||
| 253 | return 8.0f; | ||
| 254 | case LightingScale::Scale1_4: | ||
| 255 | return 0.25f; | ||
| 256 | case LightingScale::Scale1_2: | ||
| 257 | return 0.5f; | ||
| 258 | } | ||
| 259 | return 0.0f; | ||
| 260 | } | ||
| 261 | } lut_scale; | ||
| 262 | |||
| 263 | INSERT_PADDING_WORDS(0x6); | ||
| 264 | |||
| 265 | union { | ||
| 266 | // There are 8 light enable "slots", corresponding to the total number of lights supported | ||
| 267 | // by Pica. For N enabled lights (specified by register 0x1c2, or 'src_num' above), the | ||
| 268 | // first N slots below will be set to integers within the range of 0-7, corresponding to the | ||
| 269 | // actual light that is enabled for each slot. | ||
| 270 | |||
| 271 | BitField<0, 3, u32> slot_0; | ||
| 272 | BitField<4, 3, u32> slot_1; | ||
| 273 | BitField<8, 3, u32> slot_2; | ||
| 274 | BitField<12, 3, u32> slot_3; | ||
| 275 | BitField<16, 3, u32> slot_4; | ||
| 276 | BitField<20, 3, u32> slot_5; | ||
| 277 | BitField<24, 3, u32> slot_6; | ||
| 278 | BitField<28, 3, u32> slot_7; | ||
| 279 | |||
| 280 | unsigned GetNum(unsigned index) const { | ||
| 281 | const unsigned enable_slots[] = {slot_0, slot_1, slot_2, slot_3, | ||
| 282 | slot_4, slot_5, slot_6, slot_7}; | ||
| 283 | return enable_slots[index]; | ||
| 284 | } | ||
| 285 | } light_enable; | ||
| 286 | |||
| 287 | INSERT_PADDING_WORDS(0x26); | ||
| 288 | }; | ||
| 289 | |||
| 290 | static_assert(sizeof(LightingRegs) == 0xC0 * sizeof(u32), "LightingRegs struct has incorrect size"); | ||
| 291 | |||
| 292 | } // namespace Pica | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index bfdc0c8a4..3e6850302 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -192,18 +192,18 @@ union PicaShaderConfig { | |||
| 192 | 192 | ||
| 193 | bool enable; | 193 | bool enable; |
| 194 | unsigned src_num; | 194 | unsigned src_num; |
| 195 | Pica::Regs::LightingBumpMode bump_mode; | 195 | Pica::LightingRegs::LightingBumpMode bump_mode; |
| 196 | unsigned bump_selector; | 196 | unsigned bump_selector; |
| 197 | bool bump_renorm; | 197 | bool bump_renorm; |
| 198 | bool clamp_highlights; | 198 | bool clamp_highlights; |
| 199 | 199 | ||
| 200 | Pica::Regs::LightingConfig config; | 200 | Pica::LightingRegs::LightingConfig config; |
| 201 | Pica::Regs::LightingFresnelSelector fresnel_selector; | 201 | Pica::LightingRegs::LightingFresnelSelector fresnel_selector; |
| 202 | 202 | ||
| 203 | struct { | 203 | struct { |
| 204 | bool enable; | 204 | bool enable; |
| 205 | bool abs_input; | 205 | bool abs_input; |
| 206 | Pica::Regs::LightingLutInput type; | 206 | Pica::LightingRegs::LightingLutInput type; |
| 207 | float scale; | 207 | float scale; |
| 208 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; | 208 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; |
| 209 | } lighting; | 209 | } lighting; |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 9c7687f62..0467cccfd 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | using Pica::Regs; | 15 | using Pica::Regs; |
| 16 | using Pica::RasterizerRegs; | 16 | using Pica::RasterizerRegs; |
| 17 | using Pica::LightingRegs; | ||
| 17 | using TevStageConfig = Pica::TexturingRegs::TevStageConfig; | 18 | using TevStageConfig = Pica::TexturingRegs::TevStageConfig; |
| 18 | 19 | ||
| 19 | namespace GLShader { | 20 | namespace GLShader { |
| @@ -365,7 +366,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 365 | "vec3 refl_value = vec3(0.0);\n"; | 366 | "vec3 refl_value = vec3(0.0);\n"; |
| 366 | 367 | ||
| 367 | // Compute fragment normals | 368 | // Compute fragment normals |
| 368 | if (lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) { | 369 | if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { |
| 369 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected | 370 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected |
| 370 | // texture | 371 | // texture |
| 371 | std::string bump_selector = std::to_string(lighting.bump_selector); | 372 | std::string bump_selector = std::to_string(lighting.bump_selector); |
| @@ -379,7 +380,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 379 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; | 380 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; |
| 380 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; | 381 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; |
| 381 | } | 382 | } |
| 382 | } else if (lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) { | 383 | } else if (lighting.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { |
| 383 | // Bump mapping is enabled using a tangent map | 384 | // Bump mapping is enabled using a tangent map |
| 384 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); | 385 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); |
| 385 | UNIMPLEMENTED(); | 386 | UNIMPLEMENTED(); |
| @@ -393,23 +394,24 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 393 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; | 394 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; |
| 394 | 395 | ||
| 395 | // Gets the index into the specified lookup table for specular lighting | 396 | // Gets the index into the specified lookup table for specular lighting |
| 396 | auto GetLutIndex = [&lighting](unsigned light_num, Regs::LightingLutInput input, bool abs) { | 397 | auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input, |
| 398 | bool abs) { | ||
| 397 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; | 399 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; |
| 398 | std::string index; | 400 | std::string index; |
| 399 | switch (input) { | 401 | switch (input) { |
| 400 | case Regs::LightingLutInput::NH: | 402 | case LightingRegs::LightingLutInput::NH: |
| 401 | index = "dot(normal, " + half_angle + ")"; | 403 | index = "dot(normal, " + half_angle + ")"; |
| 402 | break; | 404 | break; |
| 403 | 405 | ||
| 404 | case Regs::LightingLutInput::VH: | 406 | case LightingRegs::LightingLutInput::VH: |
| 405 | index = std::string("dot(normalize(view), " + half_angle + ")"); | 407 | index = std::string("dot(normalize(view), " + half_angle + ")"); |
| 406 | break; | 408 | break; |
| 407 | 409 | ||
| 408 | case Regs::LightingLutInput::NV: | 410 | case LightingRegs::LightingLutInput::NV: |
| 409 | index = std::string("dot(normal, normalize(view))"); | 411 | index = std::string("dot(normal, normalize(view))"); |
| 410 | break; | 412 | break; |
| 411 | 413 | ||
| 412 | case Regs::LightingLutInput::LN: | 414 | case LightingRegs::LightingLutInput::LN: |
| 413 | index = std::string("dot(light_vector, normal)"); | 415 | index = std::string("dot(light_vector, normal)"); |
| 414 | break; | 416 | break; |
| 415 | 417 | ||
| @@ -433,7 +435,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 433 | }; | 435 | }; |
| 434 | 436 | ||
| 435 | // Gets the lighting lookup table value given the specified sampler and index | 437 | // Gets the lighting lookup table value given the specified sampler and index |
| 436 | auto GetLutValue = [](Regs::LightingSampler sampler, std::string lut_index) { | 438 | auto GetLutValue = [](LightingRegs::LightingSampler sampler, std::string lut_index) { |
| 437 | return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " + | 439 | return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " + |
| 438 | lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]"); | 440 | lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]"); |
| 439 | }; | 441 | }; |
| @@ -462,8 +464,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 462 | light_src + ".position) + " + light_src + ".dist_atten_bias)"; | 464 | light_src + ".position) + " + light_src + ".dist_atten_bias)"; |
| 463 | index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; | 465 | index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; |
| 464 | const unsigned lut_num = | 466 | const unsigned lut_num = |
| 465 | ((unsigned)Regs::LightingSampler::DistanceAttenuation + light_config.num); | 467 | ((unsigned)LightingRegs::LightingSampler::DistanceAttenuation + light_config.num); |
| 466 | dist_atten = GetLutValue((Regs::LightingSampler)lut_num, index); | 468 | dist_atten = GetLutValue((LightingRegs::LightingSampler)lut_num, index); |
| 467 | } | 469 | } |
| 468 | 470 | ||
| 469 | // If enabled, clamp specular component if lighting result is negative | 471 | // If enabled, clamp specular component if lighting result is negative |
| @@ -473,24 +475,24 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 473 | // Specular 0 component | 475 | // Specular 0 component |
| 474 | std::string d0_lut_value = "1.0"; | 476 | std::string d0_lut_value = "1.0"; |
| 475 | if (lighting.lut_d0.enable && | 477 | if (lighting.lut_d0.enable && |
| 476 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 478 | LightingRegs::IsLightingSamplerSupported( |
| 477 | Pica::Regs::LightingSampler::Distribution0)) { | 479 | lighting.config, LightingRegs::LightingSampler::Distribution0)) { |
| 478 | // Lookup specular "distribution 0" LUT value | 480 | // Lookup specular "distribution 0" LUT value |
| 479 | std::string index = | 481 | std::string index = |
| 480 | GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); | 482 | GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); |
| 481 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + | 483 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + |
| 482 | GetLutValue(Regs::LightingSampler::Distribution0, index) + ")"; | 484 | GetLutValue(LightingRegs::LightingSampler::Distribution0, index) + ")"; |
| 483 | } | 485 | } |
| 484 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; | 486 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; |
| 485 | 487 | ||
| 486 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used | 488 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used |
| 487 | if (lighting.lut_rr.enable && | 489 | if (lighting.lut_rr.enable && |
| 488 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 490 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 489 | Pica::Regs::LightingSampler::ReflectRed)) { | 491 | LightingRegs::LightingSampler::ReflectRed)) { |
| 490 | std::string index = | 492 | std::string index = |
| 491 | GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); | 493 | GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); |
| 492 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + | 494 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + |
| 493 | GetLutValue(Regs::LightingSampler::ReflectRed, index) + ")"; | 495 | GetLutValue(LightingRegs::LightingSampler::ReflectRed, index) + ")"; |
| 494 | out += "refl_value.r = " + value + ";\n"; | 496 | out += "refl_value.r = " + value + ";\n"; |
| 495 | } else { | 497 | } else { |
| 496 | out += "refl_value.r = 1.0;\n"; | 498 | out += "refl_value.r = 1.0;\n"; |
| @@ -498,12 +500,13 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 498 | 500 | ||
| 499 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used | 501 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used |
| 500 | if (lighting.lut_rg.enable && | 502 | if (lighting.lut_rg.enable && |
| 501 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 503 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 502 | Pica::Regs::LightingSampler::ReflectGreen)) { | 504 | LightingRegs::LightingSampler::ReflectGreen)) { |
| 503 | std::string index = | 505 | std::string index = |
| 504 | GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); | 506 | GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); |
| 505 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + | 507 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + |
| 506 | GetLutValue(Regs::LightingSampler::ReflectGreen, index) + ")"; | 508 | GetLutValue(LightingRegs::LightingSampler::ReflectGreen, index) + |
| 509 | ")"; | ||
| 507 | out += "refl_value.g = " + value + ";\n"; | 510 | out += "refl_value.g = " + value + ";\n"; |
| 508 | } else { | 511 | } else { |
| 509 | out += "refl_value.g = refl_value.r;\n"; | 512 | out += "refl_value.g = refl_value.r;\n"; |
| @@ -511,12 +514,13 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 511 | 514 | ||
| 512 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used | 515 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used |
| 513 | if (lighting.lut_rb.enable && | 516 | if (lighting.lut_rb.enable && |
| 514 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 517 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 515 | Pica::Regs::LightingSampler::ReflectBlue)) { | 518 | LightingRegs::LightingSampler::ReflectBlue)) { |
| 516 | std::string index = | 519 | std::string index = |
| 517 | GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); | 520 | GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); |
| 518 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + | 521 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + |
| 519 | GetLutValue(Regs::LightingSampler::ReflectBlue, index) + ")"; | 522 | GetLutValue(LightingRegs::LightingSampler::ReflectBlue, index) + |
| 523 | ")"; | ||
| 520 | out += "refl_value.b = " + value + ";\n"; | 524 | out += "refl_value.b = " + value + ";\n"; |
| 521 | } else { | 525 | } else { |
| 522 | out += "refl_value.b = refl_value.r;\n"; | 526 | out += "refl_value.b = refl_value.r;\n"; |
| @@ -525,35 +529,39 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 525 | // Specular 1 component | 529 | // Specular 1 component |
| 526 | std::string d1_lut_value = "1.0"; | 530 | std::string d1_lut_value = "1.0"; |
| 527 | if (lighting.lut_d1.enable && | 531 | if (lighting.lut_d1.enable && |
| 528 | Pica::Regs::IsLightingSamplerSupported(lighting.config, | 532 | LightingRegs::IsLightingSamplerSupported( |
| 529 | Pica::Regs::LightingSampler::Distribution1)) { | 533 | lighting.config, LightingRegs::LightingSampler::Distribution1)) { |
| 530 | // Lookup specular "distribution 1" LUT value | 534 | // Lookup specular "distribution 1" LUT value |
| 531 | std::string index = | 535 | std::string index = |
| 532 | GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); | 536 | GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); |
| 533 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + | 537 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + |
| 534 | GetLutValue(Regs::LightingSampler::Distribution1, index) + ")"; | 538 | GetLutValue(LightingRegs::LightingSampler::Distribution1, index) + ")"; |
| 535 | } | 539 | } |
| 536 | std::string specular_1 = | 540 | std::string specular_1 = |
| 537 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; | 541 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; |
| 538 | 542 | ||
| 539 | // Fresnel | 543 | // Fresnel |
| 540 | if (lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported( | 544 | if (lighting.lut_fr.enable && |
| 541 | lighting.config, Pica::Regs::LightingSampler::Fresnel)) { | 545 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 546 | LightingRegs::LightingSampler::Fresnel)) { | ||
| 542 | // Lookup fresnel LUT value | 547 | // Lookup fresnel LUT value |
| 543 | std::string index = | 548 | std::string index = |
| 544 | GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); | 549 | GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); |
| 545 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + | 550 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + |
| 546 | GetLutValue(Regs::LightingSampler::Fresnel, index) + ")"; | 551 | GetLutValue(LightingRegs::LightingSampler::Fresnel, index) + ")"; |
| 547 | 552 | ||
| 548 | // Enabled for difffuse lighting alpha component | 553 | // Enabled for difffuse lighting alpha component |
| 549 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha || | 554 | if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || |
| 550 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 555 | lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { |
| 551 | out += "diffuse_sum.a *= " + value + ";\n"; | 556 | out += "diffuse_sum.a *= " + value + ";\n"; |
| 557 | } | ||
| 552 | 558 | ||
| 553 | // Enabled for the specular lighting alpha component | 559 | // Enabled for the specular lighting alpha component |
| 554 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha || | 560 | if (lighting.fresnel_selector == |
| 555 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 561 | LightingRegs::LightingFresnelSelector::SecondaryAlpha || |
| 562 | lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::Both) { | ||
| 556 | out += "specular_sum.a *= " + value + ";\n"; | 563 | out += "specular_sum.a *= " + value + ";\n"; |
| 564 | } | ||
| 557 | } | 565 | } |
| 558 | 566 | ||
| 559 | // Compute primary fragment color (diffuse lighting) function | 567 | // Compute primary fragment color (diffuse lighting) function |
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h index c1bf3dc24..97c044918 100644 --- a/src/video_core/renderer_opengl/pica_to_gl.h +++ b/src/video_core/renderer_opengl/pica_to_gl.h | |||
| @@ -210,7 +210,7 @@ inline GLvec4 ColorRGBA8(const u32 color) { | |||
| 210 | }}; | 210 | }}; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | inline std::array<GLfloat, 3> LightColor(const Pica::Regs::LightColor& color) { | 213 | inline std::array<GLfloat, 3> LightColor(const Pica::LightingRegs::LightColor& color) { |
| 214 | return {{ | 214 | return {{ |
| 215 | color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, | 215 | color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, |
| 216 | }}; | 216 | }}; |