mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
gl_rasterizer: Initial implementation of bump mapping.
This commit is contained in:
parent
449902b558
commit
9dfb223d26
3 changed files with 42 additions and 5 deletions
|
@ -702,6 +702,12 @@ struct Regs {
|
||||||
LN = 3, // Cosine of the angle between the light and the normal vectors
|
LN = 3, // Cosine of the angle between the light and the normal vectors
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LightingBumpMode : u32 {
|
||||||
|
None = 0,
|
||||||
|
NormalMap = 1,
|
||||||
|
TangentMap = 2,
|
||||||
|
};
|
||||||
|
|
||||||
union LightColor {
|
union LightColor {
|
||||||
BitField< 0, 10, u32> b;
|
BitField< 0, 10, u32> b;
|
||||||
BitField<10, 10, u32> g;
|
BitField<10, 10, u32> g;
|
||||||
|
@ -775,7 +781,10 @@ struct Regs {
|
||||||
union {
|
union {
|
||||||
BitField< 2, 2, LightingFresnelSelector> fresnel_selector;
|
BitField< 2, 2, LightingFresnelSelector> fresnel_selector;
|
||||||
BitField< 4, 4, LightingConfig> config;
|
BitField< 4, 4, LightingConfig> config;
|
||||||
|
BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2
|
||||||
BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE
|
BitField<27, 1, u32> clamp_highlights; // 1: GL_TRUE, 0: GL_FALSE
|
||||||
|
BitField<28, 2, LightingBumpMode> bump_mode; // 1: GL_TRUE, 0: GL_FALSE
|
||||||
|
BitField<30, 1, u32> bump_renorm; // 0: GL_TRUE, 1: GL_FALSE
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -119,6 +119,9 @@ struct PicaShaderConfig {
|
||||||
|
|
||||||
res.lighting.config = regs.lighting.config;
|
res.lighting.config = regs.lighting.config;
|
||||||
res.lighting.fresnel_selector = regs.lighting.fresnel_selector;
|
res.lighting.fresnel_selector = regs.lighting.fresnel_selector;
|
||||||
|
res.lighting.bump_mode = regs.lighting.bump_mode;
|
||||||
|
res.lighting.bump_selector = regs.lighting.bump_selector;
|
||||||
|
res.lighting.bump_renorm = regs.lighting.bump_renorm == 0;
|
||||||
res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
|
res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -153,6 +156,9 @@ struct PicaShaderConfig {
|
||||||
|
|
||||||
bool enable = false;
|
bool enable = false;
|
||||||
unsigned src_num = 0;
|
unsigned src_num = 0;
|
||||||
|
Pica::Regs::LightingBumpMode bump_mode = Pica::Regs::LightingBumpMode::None;
|
||||||
|
unsigned bump_selector = 0;
|
||||||
|
bool bump_renorm = false;
|
||||||
bool clamp_highlights = false;
|
bool clamp_highlights = false;
|
||||||
|
|
||||||
Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0;
|
Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0;
|
||||||
|
|
|
@ -326,11 +326,28 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
|
||||||
"vec3 light_vector = vec3(0.0);\n"
|
"vec3 light_vector = vec3(0.0);\n"
|
||||||
"vec3 refl_value = vec3(0.0);\n";
|
"vec3 refl_value = vec3(0.0);\n";
|
||||||
|
|
||||||
// Convert interpolated quaternion to a GL fragment normal
|
// Compute fragment normals
|
||||||
out += "vec3 normal = normalize(vec3(\n";
|
if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) {
|
||||||
out += " 2.f*(normquat.x*normquat.z + normquat.y*normquat.w),\n";
|
// Bump mapping is enabled using a normal map, read perturbation vector from the selected texture
|
||||||
out += " 2.f*(normquat.y*normquat.z + normquat.x*normquat.w),\n";
|
std::string bump_selector = std::to_string(config.lighting.bump_selector);
|
||||||
out += " 1.f - 2.f*(normquat.x*normquat.x + normquat.y*normquat.y)));\n";
|
out += "vec3 surface_normal = 2.0 * texture(tex[" + bump_selector + "], texcoord[" + bump_selector + "]).rgb - 1.0;\n";
|
||||||
|
|
||||||
|
// Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher precision result
|
||||||
|
if (config.lighting.bump_renorm) {
|
||||||
|
std::string val = "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))";
|
||||||
|
out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n";
|
||||||
|
}
|
||||||
|
} else if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) {
|
||||||
|
// Bump mapping is enabled using a tangent map
|
||||||
|
LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)");
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
} else {
|
||||||
|
// No bump mapping - surface local normal is just a unit normal
|
||||||
|
out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate the surface-local normal by the interpolated normal quaternion to convert it to eyespace
|
||||||
|
out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n";
|
||||||
|
|
||||||
// Gets the index into the specified lookup table for specular lighting
|
// Gets the index into the specified lookup table for specular lighting
|
||||||
auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) {
|
auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) {
|
||||||
|
@ -516,6 +533,11 @@ layout (std140) uniform shader_data {
|
||||||
uniform sampler2D tex[3];
|
uniform sampler2D tex[3];
|
||||||
uniform sampler1D lut[6];
|
uniform sampler1D lut[6];
|
||||||
|
|
||||||
|
// Rotate the vector v by the quaternion q
|
||||||
|
vec3 quaternion_rotate(vec4 q, vec3 v) {
|
||||||
|
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 primary_fragment_color = vec4(0.0);
|
vec4 primary_fragment_color = vec4(0.0);
|
||||||
vec4 secondary_fragment_color = vec4(0.0);
|
vec4 secondary_fragment_color = vec4(0.0);
|
||||||
|
|
Loading…
Reference in a new issue