mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-19 16:41:05 +00:00
Merge pull request #2800 from wwylele/fog-lutlutlut
gl_rasterizer: use texture buffer for fog LUT
This commit is contained in:
commit
a613d45de9
@ -111,6 +111,14 @@ struct State {
|
|||||||
|
|
||||||
BitField<0, 13, s32> difference; // 1.1.11 fixed point
|
BitField<0, 13, s32> difference; // 1.1.11 fixed point
|
||||||
BitField<13, 11, u32> value; // 0.0.11 fixed point
|
BitField<13, 11, u32> value; // 0.0.11 fixed point
|
||||||
|
|
||||||
|
float ToFloat() const {
|
||||||
|
return static_cast<float>(value) / 2047.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DiffToFloat() const {
|
||||||
|
return static_cast<float>(difference) / 2047.0f;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<LutEntry, 128> lut;
|
std::array<LutEntry, 128> lut;
|
||||||
|
@ -94,10 +94,10 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
|
|||||||
framebuffer.Create();
|
framebuffer.Create();
|
||||||
|
|
||||||
// Allocate and bind lighting lut textures
|
// Allocate and bind lighting lut textures
|
||||||
lighting_lut_buffer.Create();
|
lighting_lut.Create();
|
||||||
state.lighting_lut.texture_buffer = lighting_lut.handle;
|
state.lighting_lut.texture_buffer = lighting_lut.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
lighting_lut.Create();
|
lighting_lut_buffer.Create();
|
||||||
glBindBuffer(GL_TEXTURE_BUFFER, lighting_lut_buffer.handle);
|
glBindBuffer(GL_TEXTURE_BUFFER, lighting_lut_buffer.handle);
|
||||||
glBufferData(GL_TEXTURE_BUFFER,
|
glBufferData(GL_TEXTURE_BUFFER,
|
||||||
sizeof(GLfloat) * 2 * 256 * Pica::LightingRegs::NumLightingSampler, nullptr,
|
sizeof(GLfloat) * 2 * 256 * Pica::LightingRegs::NumLightingSampler, nullptr,
|
||||||
@ -106,16 +106,14 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
|
|||||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, lighting_lut_buffer.handle);
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, lighting_lut_buffer.handle);
|
||||||
|
|
||||||
// Setup the LUT for the fog
|
// Setup the LUT for the fog
|
||||||
{
|
fog_lut.Create();
|
||||||
fog_lut.Create();
|
state.fog_lut.texture_buffer = fog_lut.handle;
|
||||||
state.fog_lut.texture_1d = fog_lut.handle;
|
|
||||||
}
|
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
fog_lut_buffer.Create();
|
||||||
|
glBindBuffer(GL_TEXTURE_BUFFER, fog_lut_buffer.handle);
|
||||||
|
glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW);
|
||||||
glActiveTexture(TextureUnits::FogLUT.Enum());
|
glActiveTexture(TextureUnits::FogLUT.Enum());
|
||||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr);
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, fog_lut_buffer.handle);
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
// Setup the noise LUT for proctex
|
// Setup the noise LUT for proctex
|
||||||
proctex_noise_lut.Create();
|
proctex_noise_lut.Create();
|
||||||
@ -1356,16 +1354,17 @@ void RasterizerOpenGL::SyncFogColor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncFogLUT() {
|
void RasterizerOpenGL::SyncFogLUT() {
|
||||||
std::array<GLuint, 128> new_data;
|
std::array<GLvec2, 128> new_data;
|
||||||
|
|
||||||
std::transform(Pica::g_state.fog.lut.begin(), Pica::g_state.fog.lut.end(), new_data.begin(),
|
std::transform(Pica::g_state.fog.lut.begin(), Pica::g_state.fog.lut.end(), new_data.begin(),
|
||||||
[](const auto& entry) { return entry.raw; });
|
[](const auto& entry) {
|
||||||
|
return GLvec2{entry.ToFloat(), entry.DiffToFloat()};
|
||||||
|
});
|
||||||
|
|
||||||
if (new_data != fog_lut_data) {
|
if (new_data != fog_lut_data) {
|
||||||
fog_lut_data = new_data;
|
fog_lut_data = new_data;
|
||||||
glActiveTexture(TextureUnits::FogLUT.Enum());
|
glBindBuffer(GL_TEXTURE_BUFFER, fog_lut_buffer.handle);
|
||||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RED_INTEGER, GL_UNSIGNED_INT,
|
glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec2), new_data.data());
|
||||||
fog_lut_data.data());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,8 +283,9 @@ private:
|
|||||||
OGLTexture lighting_lut;
|
OGLTexture lighting_lut;
|
||||||
std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{};
|
std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{};
|
||||||
|
|
||||||
|
OGLBuffer fog_lut_buffer;
|
||||||
OGLTexture fog_lut;
|
OGLTexture fog_lut;
|
||||||
std::array<GLuint, 128> fog_lut_data{};
|
std::array<GLvec2, 128> fog_lut_data{};
|
||||||
|
|
||||||
OGLTexture proctex_noise_lut;
|
OGLTexture proctex_noise_lut;
|
||||||
std::array<GLvec2, 128> proctex_noise_lut_data{};
|
std::array<GLvec2, 128> proctex_noise_lut_data{};
|
||||||
|
@ -1052,7 +1052,7 @@ layout (std140) uniform shader_data {
|
|||||||
|
|
||||||
uniform sampler2D tex[3];
|
uniform sampler2D tex[3];
|
||||||
uniform samplerBuffer lighting_lut;
|
uniform samplerBuffer lighting_lut;
|
||||||
uniform usampler1D fog_lut;
|
uniform samplerBuffer fog_lut;
|
||||||
uniform sampler1D proctex_noise_lut;
|
uniform sampler1D proctex_noise_lut;
|
||||||
uniform sampler1D proctex_color_map;
|
uniform sampler1D proctex_color_map;
|
||||||
uniform sampler1D proctex_alpha_map;
|
uniform sampler1D proctex_alpha_map;
|
||||||
@ -1145,12 +1145,8 @@ vec4 secondary_fragment_color = vec4(0.0);
|
|||||||
// Generate clamped fog factor from LUT for given fog index
|
// Generate clamped fog factor from LUT for given fog index
|
||||||
out += "float fog_i = clamp(floor(fog_index), 0.0, 127.0);\n";
|
out += "float fog_i = clamp(floor(fog_index), 0.0, 127.0);\n";
|
||||||
out += "float fog_f = fog_index - fog_i;\n";
|
out += "float fog_f = fog_index - fog_i;\n";
|
||||||
out += "uint fog_lut_entry = texelFetch(fog_lut, int(fog_i), 0).r;\n";
|
out += "vec2 fog_lut_entry = texelFetch(fog_lut, int(fog_i)).rg;\n";
|
||||||
out += "float fog_lut_entry_difference = float(int((fog_lut_entry & 0x1FFFU) << 19U) >> "
|
out += "float fog_factor = fog_lut_entry.r + fog_lut_entry.g * fog_f;\n";
|
||||||
"19);\n"; // Extract signed difference
|
|
||||||
out += "float fog_lut_entry_value = float((fog_lut_entry >> 13U) & 0x7FFU);\n";
|
|
||||||
out += "float fog_factor = (fog_lut_entry_value + fog_lut_entry_difference * fog_f) / "
|
|
||||||
"2047.0;\n";
|
|
||||||
out += "fog_factor = clamp(fog_factor, 0.0, 1.0);\n";
|
out += "fog_factor = clamp(fog_factor, 0.0, 1.0);\n";
|
||||||
|
|
||||||
// Blend the fog
|
// Blend the fog
|
||||||
|
@ -54,7 +54,7 @@ OpenGLState::OpenGLState() {
|
|||||||
|
|
||||||
lighting_lut.texture_buffer = 0;
|
lighting_lut.texture_buffer = 0;
|
||||||
|
|
||||||
fog_lut.texture_1d = 0;
|
fog_lut.texture_buffer = 0;
|
||||||
|
|
||||||
proctex_lut.texture_1d = 0;
|
proctex_lut.texture_1d = 0;
|
||||||
proctex_diff_lut.texture_1d = 0;
|
proctex_diff_lut.texture_1d = 0;
|
||||||
@ -198,9 +198,9 @@ void OpenGLState::Apply() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fog LUT
|
// Fog LUT
|
||||||
if (fog_lut.texture_1d != cur_state.fog_lut.texture_1d) {
|
if (fog_lut.texture_buffer != cur_state.fog_lut.texture_buffer) {
|
||||||
glActiveTexture(TextureUnits::FogLUT.Enum());
|
glActiveTexture(TextureUnits::FogLUT.Enum());
|
||||||
glBindTexture(GL_TEXTURE_1D, fog_lut.texture_1d);
|
glBindTexture(GL_TEXTURE_BUFFER, fog_lut.texture_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcTex Noise LUT
|
// ProcTex Noise LUT
|
||||||
@ -272,8 +272,8 @@ void OpenGLState::ResetTexture(GLuint handle) {
|
|||||||
}
|
}
|
||||||
if (cur_state.lighting_lut.texture_buffer == handle)
|
if (cur_state.lighting_lut.texture_buffer == handle)
|
||||||
cur_state.lighting_lut.texture_buffer = 0;
|
cur_state.lighting_lut.texture_buffer = 0;
|
||||||
if (cur_state.fog_lut.texture_1d == handle)
|
if (cur_state.fog_lut.texture_buffer == handle)
|
||||||
cur_state.fog_lut.texture_1d = 0;
|
cur_state.fog_lut.texture_buffer = 0;
|
||||||
if (cur_state.proctex_noise_lut.texture_1d == handle)
|
if (cur_state.proctex_noise_lut.texture_1d == handle)
|
||||||
cur_state.proctex_noise_lut.texture_1d = 0;
|
cur_state.proctex_noise_lut.texture_1d = 0;
|
||||||
if (cur_state.proctex_color_map.texture_1d == handle)
|
if (cur_state.proctex_color_map.texture_1d == handle)
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
} lighting_lut;
|
} lighting_lut;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLuint texture_1d; // GL_TEXTURE_BINDING_1D
|
GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
|
||||||
} fog_lut;
|
} fog_lut;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -584,8 +584,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
|
|||||||
float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
|
float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
|
||||||
float fog_f = fog_index - fog_i;
|
float fog_f = fog_index - fog_i;
|
||||||
const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
|
const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
|
||||||
float fog_factor = (fog_lut_entry.value + fog_lut_entry.difference * fog_f) /
|
float fog_factor = fog_lut_entry.ToFloat() + fog_lut_entry.DiffToFloat() * fog_f;
|
||||||
2047.0f; // This is signed fixed point 1.11
|
|
||||||
fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
|
fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
|
||||||
|
|
||||||
// Blend the fog
|
// Blend the fog
|
||||||
|
Loading…
Reference in New Issue
Block a user