Fixed fog and alphakill implementation in glsl (based on DH's old commits) (#2137)

* Fixed NV4097_SET_COLOR_CLEAR_VALUE

* Fixed fog and alphakill implementation in glsl (based on DH's old commits)
This commit is contained in:
Oil 2016-09-14 17:47:53 +03:00 committed by raven02
parent e73fce2d60
commit 153a2d2b40
3 changed files with 93 additions and 33 deletions

View File

@ -88,6 +88,7 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
int index = atoi(&PI.name.data()[3]); int index = atoi(&PI.name.data()[3]);
OS << "uniform " << samplerType << " " << PI.name << ";" << std::endl; OS << "uniform " << samplerType << " " << PI.name << ";" << std::endl;
OS << "uniform " << "vec4 " << "f" << PI.name << "_cm = vec4(1.0);" << std::endl;
} }
} }
@ -118,33 +119,69 @@ namespace
// But it makes more sense to compute exp of interpoled value than to interpolate exp values. // But it makes more sense to compute exp of interpoled value than to interpolate exp values.
void insert_fog_declaration(std::stringstream & OS, rsx::fog_mode mode) void insert_fog_declaration(std::stringstream & OS, rsx::fog_mode mode)
{ {
std::string fog_func = {};
switch (mode) switch (mode)
{ {
case rsx::fog_mode::linear: case rsx::fog_mode::linear:
OS << " vec4 fogc = vec4(fog_param1 * fog_c.x + (fog_param0 - 1.), fog_param1 * fog_c.x + (fog_param0 - 1.), 0., 0.);\n"; fog_func = "fog_param1 * fog_c.x + (fog_param0 - 1.), fog_param1 * fog_c.x + (fog_param0 - 1.)";
return; break;
case rsx::fog_mode::exponential: case rsx::fog_mode::exponential:
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5)), 0., 0.);\n"; fog_func = "11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5))";
return; break;
case rsx::fog_mode::exponential2: case rsx::fog_mode::exponential2:
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5)), 2.), 0., 0.);\n"; fog_func = "4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5)), 2.)";
return; break;
case rsx::fog_mode::linear_abs: case rsx::fog_mode::linear_abs:
OS << " vec4 fogc = vec4(fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), 0., 0.);\n"; fog_func = "fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), fog_param1 * abs(fog_c.x) + (fog_param0 - 1.)";
return; break;
case rsx::fog_mode::exponential_abs: case rsx::fog_mode::exponential_abs:
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5)), 0., 0.);\n"; fog_func = "11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5))";
return; break;
case rsx::fog_mode::exponential2_abs: case rsx::fog_mode::exponential2_abs:
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5)), 2.), 0., 0.);\n"; fog_func = "4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5)), 2.)";
return; break;
default: fog_func = "0.0, 0.0";
} }
OS << " vec4 fogc = clamp(vec4(" << fog_func << ", 0., 0.), 0., 1.);\n";
}
void insert_texture_fetch(std::stringstream & OS, const RSXFragmentProgram& prog, const ParamArray& param)
{
OS << "vec4 texture_fetch(int index, vec4 coord)\n{\n";
OS << " switch (index)\n\t{\n";
for (u8 id = 0; id < 16; id++)
{
if (prog.textures_alpha_kill[id])
{
OS << " case " + std::to_string(id) + ": return ";
switch (prog.get_texture_dimension(id))
{
case rsx::texture_dimension_extended::texture_dimension_1d: OS << "texture(tex" + std::to_string(id) + ", coord.x)"; break;
case rsx::texture_dimension_extended::texture_dimension_2d: OS << "texture(tex" + std::to_string(id) + ", coord.xy)"; break;
case rsx::texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_cubemap: OS << "texture(tex" + std::to_string(id) + ", coord.xyz)"; break;
default: OS << "vec4(0.0)";
}
OS << ";\n";
}
}
OS << " default: return vec4(0.0);\n";
OS << " }\n";
OS << "}\n";
} }
} }
void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS) void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{ {
insert_glsl_legacy_function(OS); insert_glsl_legacy_function(OS);
insert_texture_fetch(OS, m_prog, m_parr);
OS << "void main ()" << std::endl; OS << "void main ()" << std::endl;
OS << "{" << std::endl; OS << "{" << std::endl;
@ -231,27 +268,37 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
if (!first_output_name.empty()) if (!first_output_name.empty())
{ {
switch (m_prog.alpha_func) auto make_comparison_test = [](rsx::comparison_function compare_func, const std::string &test, const std::string &a, const std::string &b) -> std::string
{ {
case rsx::comparison_function::equal: if (compare_func == rsx::comparison_function::always) return{};
OS << " if (bool(alpha_test) && " << first_output_name << ".a != alpha_ref) discard;\n";
break; if (compare_func == rsx::comparison_function::never) return " discard;\n";
case rsx::comparison_function::not_equal:
OS << " if (bool(alpha_test) && " << first_output_name << ".a == alpha_ref) discard;\n"; std::string compare;
break; switch (compare_func)
case rsx::comparison_function::less_or_equal: {
OS << " if (bool(alpha_test) && " << first_output_name << ".a > alpha_ref) discard;\n"; case rsx::comparison_function::equal: compare = " == "; break;
break; case rsx::comparison_function::not_equal: compare = " != "; break;
case rsx::comparison_function::less: case rsx::comparison_function::less_or_equal: compare = " <= "; break;
OS << " if (bool(alpha_test) && " << first_output_name << ".a >= alpha_ref) discard;\n"; case rsx::comparison_function::less: compare = " < "; break;
break; case rsx::comparison_function::greater: compare = " > "; break;
case rsx::comparison_function::greater: case rsx::comparison_function::greater_or_equal: compare = " >= "; break;
OS << " if (bool(alpha_test) && " << first_output_name << ".a <= alpha_ref) discard;\n";
break;
case rsx::comparison_function::greater_or_equal:
OS << " if (bool(alpha_test) && " << first_output_name << ".a < alpha_ref) discard;\n";
break;
} }
return " if (" + test + "!(" + a + compare + b + ")) discard;\n";
};
for (u8 index = 0; index < 16; ++index)
{
if (m_prog.textures_alpha_kill[index])
{
std::string index_string = std::to_string(index);
std::string fetch_texture = "texture_fetch(" + index_string + ", tc" + index_string + " * ftex" + index_string + "_cm).a";
OS << make_comparison_test((rsx::comparison_function)m_prog.textures_zfunc[index], "", "0", fetch_texture);
}
}
OS << make_comparison_test(m_prog.alpha_func, "alpha_test != 0 && ", first_output_name + ".a", "alpha_ref");
} }
OS << "}" << std::endl; OS << "}" << std::endl;

View File

@ -233,6 +233,9 @@ struct RSXFragmentProgram
rsx::fog_mode fog_equation; rsx::fog_mode fog_equation;
u16 height; u16 height;
u8 textures_alpha_kill[16];
u32 textures_zfunc[16];
rsx::texture_dimension_extended get_texture_dimension(u8 id) const rsx::texture_dimension_extended get_texture_dimension(u8 id) const
{ {
return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3); return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);

View File

@ -808,9 +808,19 @@ namespace rsx
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i) for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)
{ {
if (!rsx::method_registers.fragment_textures[i].enabled()) if (!rsx::method_registers.fragment_textures[i].enabled())
{
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d; texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
result.textures_alpha_kill[i] = 0;
result.textures_zfunc[i] = 0;
}
else else
{
texture_dimensions[i] = rsx::method_registers.fragment_textures[i].get_extended_texture_dimension(); texture_dimensions[i] = rsx::method_registers.fragment_textures[i].get_extended_texture_dimension();
result.textures_alpha_kill[i] = rsx::method_registers.fragment_textures[i].alpha_kill_enabled() ? 1 : 0;
result.textures_zfunc[i] = rsx::method_registers.fragment_textures[i].zfunc();
}
if (rsx::method_registers.fragment_textures[i].enabled() && (rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN)) if (rsx::method_registers.fragment_textures[i].enabled() && (rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN))
result.unnormalized_coords |= (1 << i); result.unnormalized_coords |= (1 << i);
} }