ShaderGenerator: pack eye-space normal to save one varying

Only when normal mapping is enabled.
This commit is contained in:
rdb 2019-01-30 23:51:50 +01:00
parent 376cef51c4
commit dc8f01df8a

View File

@ -749,6 +749,11 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
bool need_world_normal = false;
bool need_eye_position = key._lighting;
bool need_eye_normal = !key._lights.empty() || ((key._outputs & AuxBitplaneAttrib::ABO_aux_normal) != 0);
bool need_tangents = ((key._texture_flags & ShaderKey::TF_map_normal) != 0);
// If we have binormal/tangent and eye position, we can pack eye normal in
// the w channels of the others.
bool pack_eye_normal = need_eye_normal && need_tangents && need_eye_position;
bool have_specular = false;
if (key._lighting) {
@ -829,7 +834,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
map_index_gloss = i;
}
}
if (key._texture_flags & ShaderKey::TF_map_normal) {
if (need_tangents) {
tangent_freg = alloc_freg();
binormal_freg = alloc_freg();
text << "\t out float4 l_tangent : " << tangent_freg << ",\n";
@ -854,14 +859,16 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t uniform float4x4 trans_model_to_view,\n";
eye_position_freg = alloc_freg();
text << "\t out float4 l_eye_position : " << eye_position_freg << ",\n";
} else if (key._texture_flags & ShaderKey::TF_map_normal) {
} else if (need_tangents) {
text << "\t uniform float4x4 trans_model_to_view,\n";
}
if (need_eye_normal) {
eye_normal_freg = alloc_freg();
text << "\t uniform float4x4 tpose_view_to_model,\n";
if (!pack_eye_normal) {
eye_normal_freg = alloc_freg();
text << "\t out float3 l_eye_normal : " << eye_normal_freg << ",\n";
}
}
if ((key._texture_flags & ShaderKey::TF_map_height) != 0 || need_world_normal || need_eye_normal) {
text << "\t in float3 vtx_normal : " << normal_vreg << ",\n";
}
@ -946,9 +953,6 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
if (need_eye_position) {
text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n";
}
if (need_eye_normal) {
text << "\t l_eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
}
pmap<const InternalName *, const char *>::const_iterator it;
for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
// Pass through all texcoord inputs as-is.
@ -958,7 +962,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
if (need_color && key._color_type == ColorAttrib::T_vertex) {
text << "\t l_color = vtx_color;\n";
}
if (key._texture_flags & ShaderKey::TF_map_normal) {
if (need_tangents) {
text << "\t l_tangent.xyz = normalize(mul((float3x3)trans_model_to_view, vtx_" << tangent_input << ".xyz));\n";
text << "\t l_tangent.w = 0;\n";
text << "\t l_binormal.xyz = normalize(mul((float3x3)trans_model_to_view, -vtx_" << binormal_input << ".xyz));\n";
@ -976,6 +980,17 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t l_eyevec.z = dot(vtx_normal, eyedir);\n";
text << "\t l_eyevec = normalize(l_eyevec);\n";
}
if (need_eye_normal) {
if (pack_eye_normal) {
// We can pack the normal into the w channels of these unused varyings.
text << "\t float3 eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
text << "\t l_tangent.w = eye_normal.x;\n";
text << "\t l_binormal.w = eye_normal.y;\n";
text << "\t l_eye_position.w = eye_normal.z;\n";
} else {
text << "\t l_eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
}
}
text << "}\n\n";
// Fragment shader
@ -995,7 +1010,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
if (need_eye_position) {
text << "\t in float4 l_eye_position : " << eye_position_freg << ",\n";
}
if (need_eye_normal) {
if (need_eye_normal && !pack_eye_normal) {
text << "\t in float3 l_eye_normal : " << eye_normal_freg << ",\n";
}
for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
@ -1020,9 +1035,9 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t uniform float4 texcolor_" << i << ",\n";
}
}
if (key._texture_flags & ShaderKey::TF_map_normal) {
text << "\t in float3 l_tangent : " << tangent_freg << ",\n";
text << "\t in float3 l_binormal : " << binormal_freg << ",\n";
if (need_tangents) {
text << "\t in float4 l_tangent : " << tangent_freg << ",\n";
text << "\t in float4 l_binormal : " << binormal_freg << ",\n";
}
for (size_t i = 0; i < key._lights.size(); ++i) {
text << "\t uniform float4x4 attr_light" << i << ",\n";
@ -1078,6 +1093,12 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t discard;\n";
text << "\t }\n";
}
// Reconstruct a packed normal vector.
if (need_eye_normal && pack_eye_normal) {
text << "\t float3 l_eye_normal = float3(l_tangent.w, l_binormal.w, l_eye_position.w);\n";
}
text << "\t float4 result;\n";
if (key._outputs & (AuxBitplaneAttrib::ABO_aux_normal | AuxBitplaneAttrib::ABO_aux_glow)) {
text << "\t o_aux = float4(0, 0, 0, 0);\n";
@ -1102,7 +1123,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t float4 texcoord" << i << " = l_world_normal;\n";
break;
case TexGenAttrib::M_eye_position:
text << "\t float4 texcoord" << i << " = l_eye_position;\n";
text << "\t float4 texcoord" << i << " = float4(l_eye_position.xyz, 1.0f);\n";
break;
case TexGenAttrib::M_eye_normal:
text << "\t float4 texcoord" << i << " = float4(l_eye_normal, 1.0f);\n";
@ -1199,7 +1220,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t // Correct the surface normal for interpolation effects\n";
text << "\t l_eye_normal = normalize(l_eye_normal);\n";
}
if (key._texture_flags & ShaderKey::TF_map_normal) {
if (need_tangents) {
text << "\t // Translate tangent-space normal in map to view-space.\n";
// Use Reoriented Normal Mapping to blend additional normal maps.
@ -1218,8 +1239,8 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
}
text << "\t l_eye_normal *= tsnormal.z;\n";
text << "\t l_eye_normal += normalize(l_tangent) * tsnormal.x;\n";
text << "\t l_eye_normal += normalize(l_binormal) * tsnormal.y;\n";
text << "\t l_eye_normal += normalize(l_tangent.xyz) * tsnormal.x;\n";
text << "\t l_eye_normal += normalize(l_binormal.xyz) * tsnormal.y;\n";
text << "\t l_eye_normal = normalize(l_eye_normal);\n";
}
if (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) {