rsx: Implement interpolation using barycentrics

This commit is contained in:
kd-11 2022-12-05 22:28:43 +03:00 committed by kd-11
parent 1fd265d316
commit a0ef1a672c
13 changed files with 199 additions and 90 deletions

View file

@ -1,7 +1,9 @@
#include "stdafx.h"
#include "Utilities/StrFmt.h"
#include "../Common/simple_array.hpp"
#include "GLSLCommon.h"
#include "RSXFragmentProgram.h"
namespace program_common
{
@ -1140,4 +1142,103 @@ namespace glsl
" uint flags;\n"
"};\n\n";
}
void insert_fragment_shader_inputs_block(
std::stringstream& OS,
const RSXFragmentProgram& prog,
const std::vector<ParamType>& params,
const two_sided_lighting_config& _2sided_lighting,
std::function<int(std::string_view)> varying_location)
{
struct _varying_register_config
{
int location;
std::string name;
std::string type;
};
rsx::simple_array<_varying_register_config> varying_list;
for (const ParamType& PT : params)
{
for (const ParamItem& PI : PT.items)
{
// ssa is defined in the program body and is not a varying type
if (PI.name == "ssa") continue;
const auto reg_location = varying_location(PI.name);
std::string var_name = PI.name;
if (var_name == "fogc")
{
var_name = "fog_c";
}
else if (prog.two_sided_lighting)
{
if (var_name == "diff_color")
{
var_name = "diff_color0";
}
else if (var_name == "spec_color")
{
var_name = "spec_color0";
}
}
varying_list.push_back({ reg_location, var_name, PT.type });
}
}
if (prog.two_sided_lighting)
{
if (_2sided_lighting.two_sided_color)
{
varying_list.push_back({ varying_location("diff_color1"), "diff_color1", "vec4" });
}
if (_2sided_lighting.two_sided_specular)
{
varying_list.push_back({ varying_location("spec_color1"), "spec_color1", "vec4" });
}
}
if (varying_list.empty())
{
return;
}
// Make the output a little nicer
varying_list.sort(FN(x.location < y.location));
if (!(prog.ctrl & RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION))
{
for (const auto& reg : varying_list)
{
OS << "layout(location=" << reg.location << ") in " << reg.type << " " << reg.name << ";\n";
}
return;
}
for (const auto& reg : varying_list)
{
OS << "layout(location=" << reg.location << ") pervertexNV in " << reg.type << " " << reg.name << "_raw[3];\n";
}
// Interpolate the input attributes manually.
// Matches AMD behavior where gl_BaryCoordSmoothAMD only provides x and y with z being autogenerated.
OS <<
"vec4 _interpolate_varying3(const in vec4[3] v)\n"
"{\n"
" const BaryCoord_z = 1.0 - (gl_BaryCoordNV.x + gl_BaryCoordNV.y);\n"
" return gl_BaryCoordNV.x * v[0] + gl_BaryCoordNV.y * v[1] + BaryCoord_z * v[2];\n"
"}\n\n";
for (const auto& reg : varying_list)
{
OS << "vec4 " << reg.name << " = _interpolate_varying3(" << reg.name << "_raw);\n";
}
OS << "\n";
}
}