diff options
| -rw-r--r-- | src/video_core/pica.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 32 |
3 files changed, 42 insertions, 5 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 267070e45..809b16d2b 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -702,6 +702,12 @@ struct Regs { | |||
| 702 | LN = 3, // Cosine of the angle between the light and the normal vectors | 702 | LN = 3, // Cosine of the angle between the light and the normal vectors |
| 703 | }; | 703 | }; |
| 704 | 704 | ||
| 705 | enum class LightingBumpMode : u32 { | ||
| 706 | None = 0, | ||
| 707 | NormalMap = 1, | ||
| 708 | TangentMap = 2, | ||
| 709 | }; | ||
| 710 | |||
| 705 | union LightColor { | 711 | union LightColor { |
| 706 | BitField< 0, 10, u32> b; | 712 | BitField< 0, 10, u32> b; |
| 707 | BitField<10, 10, u32> g; | 713 | BitField<10, 10, u32> g; |
| @@ -775,7 +781,10 @@ struct Regs { | |||
| 775 | union { | 781 | union { |
| 776 | BitField< 2, 2, LightingFresnelSelector> fresnel_selector; | 782 | BitField< 2, 2, LightingFresnelSelector> fresnel_selector; |
| 777 | BitField< 4, 4, LightingConfig> config; | 783 | BitField< 4, 4, LightingConfig> config; |
| 784 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | ||
| 778 | BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE | 785 | BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE |
| 786 | BitField<28, 2, LightingBumpMode> bump_mode; // 1: GL_TRUE, 0: GL_FALSE | ||
| 787 | BitField<30, 1, u32> bump_renorm; // 0: GL_TRUE, 1: GL_FALSE | ||
| 779 | }; | 788 | }; |
| 780 | 789 | ||
| 781 | union { | 790 | union { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 62a4d8953..d7eac5213 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -119,6 +119,9 @@ struct PicaShaderConfig { | |||
| 119 | 119 | ||
| 120 | res.lighting.config = regs.lighting.config; | 120 | res.lighting.config = regs.lighting.config; |
| 121 | res.lighting.fresnel_selector = regs.lighting.fresnel_selector; | 121 | res.lighting.fresnel_selector = regs.lighting.fresnel_selector; |
| 122 | res.lighting.bump_mode = regs.lighting.bump_mode; | ||
| 123 | res.lighting.bump_selector = regs.lighting.bump_selector; | ||
| 124 | res.lighting.bump_renorm = regs.lighting.bump_renorm == 0; | ||
| 122 | res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0; | 125 | res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0; |
| 123 | 126 | ||
| 124 | return res; | 127 | return res; |
| @@ -153,6 +156,9 @@ struct PicaShaderConfig { | |||
| 153 | 156 | ||
| 154 | bool enable = false; | 157 | bool enable = false; |
| 155 | unsigned src_num = 0; | 158 | unsigned src_num = 0; |
| 159 | Pica::Regs::LightingBumpMode bump_mode = Pica::Regs::LightingBumpMode::None; | ||
| 160 | unsigned bump_selector = 0; | ||
| 161 | bool bump_renorm = false; | ||
| 156 | bool clamp_highlights = false; | 162 | bool clamp_highlights = false; |
| 157 | 163 | ||
| 158 | Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0; | 164 | Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0; |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index d59f2054b..ee4b54ab9 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -326,11 +326,28 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 326 | "vec3 light_vector = vec3(0.0);\n" | 326 | "vec3 light_vector = vec3(0.0);\n" |
| 327 | "vec3 refl_value = vec3(0.0);\n"; | 327 | "vec3 refl_value = vec3(0.0);\n"; |
| 328 | 328 | ||
| 329 | // Convert interpolated quaternion to a GL fragment normal | 329 | // Compute fragment normals |
| 330 | out += "vec3 normal = normalize(vec3(\n"; | 330 | if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) { |
| 331 | out += " 2.f*(normquat.x*normquat.z + normquat.y*normquat.w),\n"; | 331 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected texture |
| 332 | out += " 2.f*(normquat.y*normquat.z + normquat.x*normquat.w),\n"; | 332 | std::string bump_selector = std::to_string(config.lighting.bump_selector); |
| 333 | out += " 1.f - 2.f*(normquat.x*normquat.x + normquat.y*normquat.y)));\n"; | 333 | out += "vec3 surface_normal = 2.0 * texture(tex[" + bump_selector + "], texcoord[" + bump_selector + "]).rgb - 1.0;\n"; |
| 334 | |||
| 335 | // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher precision result | ||
| 336 | if (config.lighting.bump_renorm) { | ||
| 337 | std::string val = "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; | ||
| 338 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; | ||
| 339 | } | ||
| 340 | } else if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) { | ||
| 341 | // Bump mapping is enabled using a tangent map | ||
| 342 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); | ||
| 343 | UNIMPLEMENTED(); | ||
| 344 | } else { | ||
| 345 | // No bump mapping - surface local normal is just a unit normal | ||
| 346 | out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n"; | ||
| 347 | } | ||
| 348 | |||
| 349 | // Rotate the surface-local normal by the interpolated normal quaternion to convert it to eyespace | ||
| 350 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; | ||
| 334 | 351 | ||
| 335 | // Gets the index into the specified lookup table for specular lighting | 352 | // Gets the index into the specified lookup table for specular lighting |
| 336 | auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) { | 353 | auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) { |
| @@ -516,6 +533,11 @@ layout (std140) uniform shader_data { | |||
| 516 | uniform sampler2D tex[3]; | 533 | uniform sampler2D tex[3]; |
| 517 | uniform sampler1D lut[6]; | 534 | uniform sampler1D lut[6]; |
| 518 | 535 | ||
| 536 | // Rotate the vector v by the quaternion q | ||
| 537 | vec3 quaternion_rotate(vec4 q, vec3 v) { | ||
| 538 | return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); | ||
| 539 | } | ||
| 540 | |||
| 519 | void main() { | 541 | void main() { |
| 520 | vec4 primary_fragment_color = vec4(0.0); | 542 | vec4 primary_fragment_color = vec4(0.0); |
| 521 | vec4 secondary_fragment_color = vec4(0.0); | 543 | vec4 secondary_fragment_color = vec4(0.0); |