forked from suyu/suyu
renderer_opengl: Implement HW fragment lighting LUTs within our default UBO.
This commit is contained in:
parent
afbef52516
commit
e9af70eaf3
4 changed files with 66 additions and 15 deletions
|
@ -1216,7 +1216,7 @@ struct State {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<LutEntry, 256> luts[24];
|
std::array<std::array<LutEntry, 256>, 24> luts;
|
||||||
} lighting;
|
} lighting;
|
||||||
|
|
||||||
/// Current Pica command list
|
/// Current Pica command list
|
||||||
|
|
|
@ -162,6 +162,13 @@ void RasterizerOpenGL::DrawTriangles() {
|
||||||
state.draw.shader_dirty = false;
|
state.draw.shader_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned index = 0; index < Pica::g_state.lighting.luts.size(); index++) {
|
||||||
|
if (uniform_block_data.lut_dirty[index]) {
|
||||||
|
SyncLightingLUT(index);
|
||||||
|
uniform_block_data.lut_dirty[index] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (uniform_block_data.dirty) {
|
if (uniform_block_data.dirty) {
|
||||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
|
glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
|
||||||
uniform_block_data.dirty = false;
|
uniform_block_data.dirty = false;
|
||||||
|
@ -381,6 +388,21 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
|
||||||
SyncGlobalAmbient();
|
SyncGlobalAmbient();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Fragment lighting lookup tables
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[0], 0x1c8):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[1], 0x1c9):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[2], 0x1ca):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[3], 0x1cb):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[4], 0x1cc):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[5], 0x1cd):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce):
|
||||||
|
case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf):
|
||||||
|
{
|
||||||
|
auto& lut_config = regs.lighting.lut_config;
|
||||||
|
uniform_block_data.lut_dirty[lut_config.type] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,20 +615,23 @@ void RasterizerOpenGL::SetShader() {
|
||||||
|
|
||||||
unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");
|
unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");
|
||||||
glUniformBlockBinding(current_shader->shader.handle, block_index, 0);
|
glUniformBlockBinding(current_shader->shader.handle, block_index, 0);
|
||||||
}
|
|
||||||
|
|
||||||
// Update uniforms
|
// Update uniforms
|
||||||
SyncAlphaTest();
|
SyncAlphaTest();
|
||||||
SyncCombinerColor();
|
SyncCombinerColor();
|
||||||
auto& tev_stages = Pica::g_state.regs.GetTevStages();
|
auto& tev_stages = Pica::g_state.regs.GetTevStages();
|
||||||
for (int index = 0; index < tev_stages.size(); ++index)
|
for (int index = 0; index < tev_stages.size(); ++index)
|
||||||
SyncTevConstColor(index, tev_stages[index]);
|
SyncTevConstColor(index, tev_stages[index]);
|
||||||
|
|
||||||
SyncGlobalAmbient();
|
for (unsigned index = 0; index < Pica::g_state.lighting.luts.size(); ++index)
|
||||||
for (int light_index = 0; light_index < 8; light_index++) {
|
SyncLightingLUT(index);
|
||||||
SyncLightDiffuse(light_index);
|
|
||||||
SyncLightAmbient(light_index);
|
SyncGlobalAmbient();
|
||||||
SyncLightPosition(light_index);
|
for (int light_index = 0; light_index < 8; light_index++) {
|
||||||
|
SyncLightDiffuse(light_index);
|
||||||
|
SyncLightAmbient(light_index);
|
||||||
|
SyncLightPosition(light_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,6 +821,20 @@ void RasterizerOpenGL::SyncGlobalAmbient() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::SyncLightingLUT(unsigned lut_index) {
|
||||||
|
auto& lut = uniform_block_data.data.lighting_lut[lut_index / 4];
|
||||||
|
std::array<std::array<GLfloat, 4>, 256> new_lut;
|
||||||
|
|
||||||
|
for (int offset = 0; offset < new_lut.size(); ++offset) {
|
||||||
|
new_lut[offset][lut_index & 3] = Pica::g_state.lighting.luts[lut_index][offset].ToFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_lut != lut) {
|
||||||
|
lut = new_lut;
|
||||||
|
uniform_block_data.dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncLightDiffuse(int light_index) {
|
void RasterizerOpenGL::SyncLightDiffuse(int light_index) {
|
||||||
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
|
auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
|
||||||
if (color != uniform_block_data.data.light_src[light_index].diffuse) {
|
if (color != uniform_block_data.data.light_src[light_index].diffuse) {
|
||||||
|
|
|
@ -242,10 +242,11 @@ private:
|
||||||
std::array<GLfloat, 3> lighting_global_ambient;
|
std::array<GLfloat, 3> lighting_global_ambient;
|
||||||
INSERT_PADDING_WORDS(1);
|
INSERT_PADDING_WORDS(1);
|
||||||
LightSrc light_src[8];
|
LightSrc light_src[8];
|
||||||
|
std::array<std::array<std::array<GLfloat, 4>, 256>, 6> lighting_lut;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(UniformData) == 0x210, "The size of the UniformData structure has changed, update the structure in the shader");
|
static_assert(sizeof(UniformData) == 0x6210, "The size of the UniformData structure has changed, update the structure in the shader");
|
||||||
static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec");
|
static_assert(sizeof(UniformData) < 32768, "UniformData structure must be less than 32kb");
|
||||||
|
|
||||||
/// Reconfigure the OpenGL color texture to use the given format and dimensions
|
/// Reconfigure the OpenGL color texture to use the given format and dimensions
|
||||||
void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height);
|
void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height);
|
||||||
|
@ -295,6 +296,9 @@ private:
|
||||||
/// Syncs the lighting global ambient color to match the PICA register
|
/// Syncs the lighting global ambient color to match the PICA register
|
||||||
void SyncGlobalAmbient();
|
void SyncGlobalAmbient();
|
||||||
|
|
||||||
|
/// Syncs the lighting lookup tables
|
||||||
|
void SyncLightingLUT(unsigned index);
|
||||||
|
|
||||||
/// Syncs the specified light's diffuse color to match the PICA register
|
/// Syncs the specified light's diffuse color to match the PICA register
|
||||||
void SyncLightDiffuse(int light_index);
|
void SyncLightDiffuse(int light_index);
|
||||||
|
|
||||||
|
@ -346,6 +350,7 @@ private:
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
UniformData data;
|
UniformData data;
|
||||||
|
bool lut_dirty[24];
|
||||||
bool dirty;
|
bool dirty;
|
||||||
} uniform_block_data;
|
} uniform_block_data;
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,7 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) {
|
||||||
#version 330 core
|
#version 330 core
|
||||||
#define NUM_TEV_STAGES 6
|
#define NUM_TEV_STAGES 6
|
||||||
#define NUM_LIGHTS 8
|
#define NUM_LIGHTS 8
|
||||||
|
#define LIGHTING_LUT_SIZE 256
|
||||||
|
|
||||||
in vec4 primary_color;
|
in vec4 primary_color;
|
||||||
in vec2 texcoord[3];
|
in vec2 texcoord[3];
|
||||||
|
@ -345,6 +346,12 @@ layout (std140) uniform shader_data {
|
||||||
float depth_offset;
|
float depth_offset;
|
||||||
vec3 lighting_global_ambient;
|
vec3 lighting_global_ambient;
|
||||||
LightSrc light_src[NUM_LIGHTS];
|
LightSrc light_src[NUM_LIGHTS];
|
||||||
|
vec4 lighting_lut_0[LIGHTING_LUT_SIZE];
|
||||||
|
vec4 lighting_lut_1[LIGHTING_LUT_SIZE];
|
||||||
|
vec4 lighting_lut_2[LIGHTING_LUT_SIZE];
|
||||||
|
vec4 lighting_lut_3[LIGHTING_LUT_SIZE];
|
||||||
|
vec4 lighting_lut_4[LIGHTING_LUT_SIZE];
|
||||||
|
vec4 lighting_lut_5[LIGHTING_LUT_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform sampler2D tex[3];
|
uniform sampler2D tex[3];
|
||||||
|
|
Loading…
Reference in a new issue