summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2015-11-25 20:49:48 -0500
committerGravatar bunnei2016-02-05 17:20:19 -0500
commit9dfb223d26a7d700e38a4c0eec9d32d78c42f91d (patch)
treedcd826661707d299319483a261df469469e375ac
parentgl_shader_gen: Fix bug in LUT range (should within range [0, 255] not [0, 256]). (diff)
downloadyuzu-9dfb223d26a7d700e38a4c0eec9d32d78c42f91d.tar.gz
yuzu-9dfb223d26a7d700e38a4c0eec9d32d78c42f91d.tar.xz
yuzu-9dfb223d26a7d700e38a4c0eec9d32d78c42f91d.zip
gl_rasterizer: Initial implementation of bump mapping.
-rw-r--r--src/video_core/pica.h9
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp32
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 {
516uniform sampler2D tex[3]; 533uniform sampler2D tex[3];
517uniform sampler1D lut[6]; 534uniform sampler1D lut[6];
518 535
536// Rotate the vector v by the quaternion q
537vec3 quaternion_rotate(vec4 q, vec3 v) {
538 return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
539}
540
519void main() { 541void main() {
520vec4 primary_fragment_color = vec4(0.0); 542vec4 primary_fragment_color = vec4(0.0);
521vec4 secondary_fragment_color = vec4(0.0); 543vec4 secondary_fragment_color = vec4(0.0);