mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue