diff options
| author | 2017-06-14 20:08:26 -0700 | |
|---|---|---|
| committer | 2017-06-14 20:08:26 -0700 | |
| commit | da1bec121a252aa0fe17dbc80bfad2d0423e342c (patch) | |
| tree | 4e2bfbc17000c9cda10804f26b2bcbe34dd410da /src | |
| parent | Merge pull request #2743 from wwylele/wrap-fix (diff) | |
| parent | gl_rasterizer/lighting: Implement tangent mapping (diff) | |
| download | yuzu-da1bec121a252aa0fe17dbc80bfad2d0423e342c.tar.gz yuzu-da1bec121a252aa0fe17dbc80bfad2d0423e342c.tar.xz yuzu-da1bec121a252aa0fe17dbc80bfad2d0423e342c.zip | |
Merge pull request #2762 from wwylele/light-cp-tangent
Fragment lighting: implement lut input 5 (CP) and tangent mapping
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/regs_lighting.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 46 |
2 files changed, 38 insertions, 10 deletions
diff --git a/src/video_core/regs_lighting.h b/src/video_core/regs_lighting.h index fbfebc0a7..f383b8b4f 100644 --- a/src/video_core/regs_lighting.h +++ b/src/video_core/regs_lighting.h | |||
| @@ -84,7 +84,7 @@ struct LightingRegs { | |||
| 84 | NV = 2, // Cosine of the angle between the normal and the view vector | 84 | NV = 2, // Cosine of the angle between the normal and the view vector |
| 85 | LN = 3, // Cosine of the angle between the light and the normal vectors | 85 | LN = 3, // Cosine of the angle between the light and the normal vectors |
| 86 | SP = 4, // Cosine of the angle between the light and the inverse spotlight vectors | 86 | SP = 4, // Cosine of the angle between the light and the inverse spotlight vectors |
| 87 | CP = 5, // TODO: document and implement | 87 | CP = 5, // Cosine of the angle between the tangent and projection of half-angle vectors |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | enum class LightingBumpMode : u32 { | 90 | enum class LightingBumpMode : u32 { |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index db53710aa..14be1201f 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -520,12 +520,12 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 520 | "vec3 refl_value = vec3(0.0);\n" | 520 | "vec3 refl_value = vec3(0.0);\n" |
| 521 | "vec3 spot_dir = vec3(0.0);\n;"; | 521 | "vec3 spot_dir = vec3(0.0);\n;"; |
| 522 | 522 | ||
| 523 | // Compute fragment normals | 523 | // Compute fragment normals and tangents |
| 524 | const std::string pertubation = | ||
| 525 | "2.0 * (" + SampleTexture(config, lighting.bump_selector) + ").rgb - 1.0"; | ||
| 524 | if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { | 526 | if (lighting.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { |
| 525 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected | 527 | // Bump mapping is enabled using a normal map |
| 526 | // texture | 528 | out += "vec3 surface_normal = " + pertubation + ";\n"; |
| 527 | out += "vec3 surface_normal = 2.0 * (" + SampleTexture(config, lighting.bump_selector) + | ||
| 528 | ").rgb - 1.0;\n"; | ||
| 529 | 529 | ||
| 530 | // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher | 530 | // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher |
| 531 | // precision result | 531 | // precision result |
| @@ -534,18 +534,29 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 534 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; | 534 | "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; |
| 535 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; | 535 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; |
| 536 | } | 536 | } |
| 537 | |||
| 538 | // The tangent vector is not perturbed by the normal map and is just a unit vector. | ||
| 539 | out += "vec3 surface_tangent = vec3(1.0, 0.0, 0.0);\n"; | ||
| 537 | } else if (lighting.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { | 540 | } else if (lighting.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { |
| 538 | // Bump mapping is enabled using a tangent map | 541 | // Bump mapping is enabled using a tangent map |
| 539 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); | 542 | out += "vec3 surface_tangent = " + pertubation + ";\n"; |
| 540 | UNIMPLEMENTED(); | 543 | // Mathematically, recomputing Z-component of the tangent vector won't affect the relevant |
| 544 | // computation below, which is also confirmed on 3DS. So we don't bother recomputing here | ||
| 545 | // even if 'renorm' is enabled. | ||
| 546 | |||
| 547 | // The normal vector is not perturbed by the tangent map and is just a unit vector. | ||
| 548 | out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n"; | ||
| 541 | } else { | 549 | } else { |
| 542 | // No bump mapping - surface local normal is just a unit normal | 550 | // No bump mapping - surface local normal and tangent are just unit vectors |
| 543 | out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n"; | 551 | out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n"; |
| 552 | out += "vec3 surface_tangent = vec3(1.0, 0.0, 0.0);\n"; | ||
| 544 | } | 553 | } |
| 545 | 554 | ||
| 546 | // Rotate the surface-local normal by the interpolated normal quaternion to convert it to | 555 | // Rotate the surface-local normal by the interpolated normal quaternion to convert it to |
| 547 | // eyespace. | 556 | // eyespace. |
| 548 | out += "vec3 normal = quaternion_rotate(normalize(normquat), surface_normal);\n"; | 557 | out += "vec4 normalized_normquat = normalize(normquat);\n"; |
| 558 | out += "vec3 normal = quaternion_rotate(normalized_normquat, surface_normal);\n"; | ||
| 559 | out += "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\n"; | ||
| 549 | 560 | ||
| 550 | // Gets the index into the specified lookup table for specular lighting | 561 | // Gets the index into the specified lookup table for specular lighting |
| 551 | auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input, | 562 | auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input, |
| @@ -573,6 +584,23 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 573 | index = std::string("dot(light_vector, spot_dir)"); | 584 | index = std::string("dot(light_vector, spot_dir)"); |
| 574 | break; | 585 | break; |
| 575 | 586 | ||
| 587 | case LightingRegs::LightingLutInput::CP: | ||
| 588 | // CP input is only available with configuration 7 | ||
| 589 | if (lighting.config == LightingRegs::LightingConfig::Config7) { | ||
| 590 | // Note: even if the normal vector is modified by normal map, which is not the | ||
| 591 | // normal of the tangent plane anymore, the half angle vector is still projected | ||
| 592 | // using the modified normal vector. | ||
| 593 | std::string half_angle_proj = half_angle + | ||
| 594 | " - normal / dot(normal, normal) * dot(normal, " + | ||
| 595 | half_angle + ")"; | ||
| 596 | // Note: the half angle vector projection is confirmed not normalized before the dot | ||
| 597 | // product. The result is in fact not cos(phi) as the name suggested. | ||
| 598 | index = "dot(" + half_angle_proj + ", tangent)"; | ||
| 599 | } else { | ||
| 600 | index = "0.0"; | ||
| 601 | } | ||
| 602 | break; | ||
| 603 | |||
| 576 | default: | 604 | default: |
| 577 | LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input); | 605 | LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input); |
| 578 | UNIMPLEMENTED(); | 606 | UNIMPLEMENTED(); |