mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	renderer_opengl: Implement diffuse component of HW fragment lighting.
This commit is contained in:
		
							parent
							
								
									b003075570
								
							
						
					
					
						commit
						afbef52516
					
				
					 6 changed files with 270 additions and 15 deletions
				
			
		|  | @ -662,17 +662,18 @@ struct Regs { | ||||||
|         LN = 3, // Cosine of the angle between the light and the normal vectors
 |         LN = 3, // Cosine of the angle between the light and the normal vectors
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     union LightColor { | ||||||
|  |         BitField< 0, 10, u32> b; | ||||||
|  |         BitField<10, 10, u32> g; | ||||||
|  |         BitField<20, 10, u32> r; | ||||||
|  | 
 | ||||||
|  |         Math::Vec3f ToVec3f() const { | ||||||
|  |             // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color component
 | ||||||
|  |             return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     struct { |     struct { | ||||||
|         union LightColor { |  | ||||||
|             BitField< 0, 10, u32> b; |  | ||||||
|             BitField<10, 10, u32> g; |  | ||||||
|             BitField<20, 10, u32> r; |  | ||||||
| 
 |  | ||||||
|             Math::Vec3f ToVec3f() const { |  | ||||||
|                 return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         struct LightSrc { |         struct LightSrc { | ||||||
|             LightColor specular_0;  // material.specular_0 * light.specular_0
 |             LightColor specular_0;  // material.specular_0 * light.specular_0
 | ||||||
|             LightColor specular_1;  // material.specular_1 * light.specular_1
 |             LightColor specular_1;  // material.specular_1 * light.specular_1
 | ||||||
|  |  | ||||||
|  | @ -75,6 +75,12 @@ void RasterizerOpenGL::InitObjects() { | ||||||
|     glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD1); |     glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD1); | ||||||
|     glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD2); |     glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD2); | ||||||
| 
 | 
 | ||||||
|  |     glVertexAttribPointer(GLShader::ATTRIBUTE_NORMQUAT, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, normquat)); | ||||||
|  |     glEnableVertexAttribArray(GLShader::ATTRIBUTE_NORMQUAT); | ||||||
|  | 
 | ||||||
|  |     glVertexAttribPointer(GLShader::ATTRIBUTE_VIEW, 3, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, view)); | ||||||
|  |     glEnableVertexAttribArray(GLShader::ATTRIBUTE_VIEW); | ||||||
|  | 
 | ||||||
|     SetShader(); |     SetShader(); | ||||||
| 
 | 
 | ||||||
|     // Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
 |     // Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
 | ||||||
|  | @ -283,6 +289,98 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | ||||||
|     case PICA_REG_INDEX(tev_combiner_buffer_color): |     case PICA_REG_INDEX(tev_combiner_buffer_color): | ||||||
|         SyncCombinerColor(); |         SyncCombinerColor(); | ||||||
|         break; |         break; | ||||||
|  | 
 | ||||||
|  |     // Fragment lighting diffuse color
 | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[0].diffuse, 0x142 + 0 * 0x10): | ||||||
|  |         SyncLightDiffuse(0); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[1].diffuse, 0x142 + 1 * 0x10): | ||||||
|  |         SyncLightDiffuse(1); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[2].diffuse, 0x142 + 2 * 0x10): | ||||||
|  |         SyncLightDiffuse(2); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[3].diffuse, 0x142 + 3 * 0x10): | ||||||
|  |         SyncLightDiffuse(3); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[4].diffuse, 0x142 + 4 * 0x10): | ||||||
|  |         SyncLightDiffuse(4); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[5].diffuse, 0x142 + 5 * 0x10): | ||||||
|  |         SyncLightDiffuse(5); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[6].diffuse, 0x142 + 6 * 0x10): | ||||||
|  |         SyncLightDiffuse(6); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[7].diffuse, 0x142 + 7 * 0x10): | ||||||
|  |         SyncLightDiffuse(7); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     // Fragment lighting ambient color
 | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[0].ambient, 0x143 + 0 * 0x10): | ||||||
|  |         SyncLightAmbient(0); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[1].ambient, 0x143 + 1 * 0x10): | ||||||
|  |         SyncLightAmbient(1); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[2].ambient, 0x143 + 2 * 0x10): | ||||||
|  |         SyncLightAmbient(2); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[3].ambient, 0x143 + 3 * 0x10): | ||||||
|  |         SyncLightAmbient(3); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[4].ambient, 0x143 + 4 * 0x10): | ||||||
|  |         SyncLightAmbient(4); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[5].ambient, 0x143 + 5 * 0x10): | ||||||
|  |         SyncLightAmbient(5); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[6].ambient, 0x143 + 6 * 0x10): | ||||||
|  |         SyncLightAmbient(6); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[7].ambient, 0x143 + 7 * 0x10): | ||||||
|  |         SyncLightAmbient(7); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |      // Fragment lighting position
 | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[0].x, 0x144 + 0 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[0].z, 0x145 + 0 * 0x10): | ||||||
|  |         SyncLightPosition(0); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[1].x, 0x144 + 1 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[1].z, 0x145 + 1 * 0x10): | ||||||
|  |         SyncLightPosition(1); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[2].x, 0x144 + 2 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[2].z, 0x145 + 2 * 0x10): | ||||||
|  |         SyncLightPosition(2); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[3].x, 0x144 + 3 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[3].z, 0x145 + 3 * 0x10): | ||||||
|  |         SyncLightPosition(3); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[4].x, 0x144 + 4 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[4].z, 0x145 + 4 * 0x10): | ||||||
|  |         SyncLightPosition(4); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[5].x, 0x144 + 5 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[5].z, 0x145 + 5 * 0x10): | ||||||
|  |         SyncLightPosition(5); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[6].x, 0x144 + 6 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[6].z, 0x145 + 6 * 0x10): | ||||||
|  |         SyncLightPosition(6); | ||||||
|  |         break; | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[7].x, 0x144 + 7 * 0x10): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.light[7].z, 0x145 + 7 * 0x10): | ||||||
|  |         SyncLightPosition(7); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     // Fragment lighting global ambient color (emission + ambient * ambient)
 | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(lighting.global_ambient, 0x1c0): | ||||||
|  |         SyncGlobalAmbient(); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -503,6 +601,13 @@ void RasterizerOpenGL::SetShader() { | ||||||
|     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 (int light_index = 0; light_index < 8; light_index++) { | ||||||
|  |         SyncLightDiffuse(light_index); | ||||||
|  |         SyncLightAmbient(light_index); | ||||||
|  |         SyncLightPosition(light_index); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerOpenGL::SyncFramebuffer() { | void RasterizerOpenGL::SyncFramebuffer() { | ||||||
|  | @ -683,6 +788,42 @@ void RasterizerOpenGL::SyncTevConstColor(int stage_index, const Pica::Regs::TevS | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RasterizerOpenGL::SyncGlobalAmbient() { | ||||||
|  |     auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.global_ambient); | ||||||
|  |     if (color != uniform_block_data.data.lighting_global_ambient) { | ||||||
|  |         uniform_block_data.data.lighting_global_ambient = color; | ||||||
|  |         uniform_block_data.dirty = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RasterizerOpenGL::SyncLightDiffuse(int light_index) { | ||||||
|  |     auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse); | ||||||
|  |     if (color != uniform_block_data.data.light_src[light_index].diffuse) { | ||||||
|  |         uniform_block_data.data.light_src[light_index].diffuse = color; | ||||||
|  |         uniform_block_data.dirty = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RasterizerOpenGL::SyncLightAmbient(int light_index) { | ||||||
|  |     auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].ambient); | ||||||
|  |     if (color != uniform_block_data.data.light_src[light_index].ambient) { | ||||||
|  |         uniform_block_data.data.light_src[light_index].ambient = color; | ||||||
|  |         uniform_block_data.dirty = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RasterizerOpenGL::SyncLightPosition(int light_index) { | ||||||
|  |     std::array<GLfloat, 3> position = { | ||||||
|  |         Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(), | ||||||
|  |         Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(), | ||||||
|  |         Pica::float16::FromRawFloat16(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32() }; | ||||||
|  | 
 | ||||||
|  |     if (position != uniform_block_data.data.light_src[light_index].position) { | ||||||
|  |         uniform_block_data.data.light_src[light_index].position = position; | ||||||
|  |         uniform_block_data.dirty = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void RasterizerOpenGL::SyncDrawState() { | void RasterizerOpenGL::SyncDrawState() { | ||||||
|     const auto& regs = Pica::g_state.regs; |     const auto& regs = Pica::g_state.regs; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,6 +71,18 @@ struct PicaShaderConfig { | ||||||
|             regs.tev_combiner_buffer_input.update_mask_rgb.Value() | |             regs.tev_combiner_buffer_input.update_mask_rgb.Value() | | ||||||
|             regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; |             regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; | ||||||
| 
 | 
 | ||||||
|  |         // Fragment lighting
 | ||||||
|  | 
 | ||||||
|  |         res.lighting_enabled = !regs.lighting.disable; | ||||||
|  |         res.num_lights = regs.lighting.src_num + 1; | ||||||
|  | 
 | ||||||
|  |         for (unsigned light_index = 0; light_index < res.num_lights; ++light_index) { | ||||||
|  |             unsigned num = regs.lighting.light_enable.GetNum(light_index); | ||||||
|  |             res.light_src[light_index].num = num; | ||||||
|  |             res.light_src[light_index].directional = regs.lighting.light[num].w; | ||||||
|  |             res.light_src[light_index].two_sided_diffuse = regs.lighting.light[num].two_sided_diffuse; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         return res; |         return res; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -89,6 +101,16 @@ struct PicaShaderConfig { | ||||||
|     Pica::Regs::CompareFunc alpha_test_func; |     Pica::Regs::CompareFunc alpha_test_func; | ||||||
|     std::array<Pica::Regs::TevStageConfig, 6> tev_stages = {}; |     std::array<Pica::Regs::TevStageConfig, 6> tev_stages = {}; | ||||||
|     u8 combiner_buffer_input; |     u8 combiner_buffer_input; | ||||||
|  | 
 | ||||||
|  |     struct { | ||||||
|  |         unsigned num; | ||||||
|  |         bool directional; | ||||||
|  |         bool two_sided_diffuse; | ||||||
|  |         bool dist_atten_enabled; | ||||||
|  |     } light_src[8]; | ||||||
|  | 
 | ||||||
|  |     bool lighting_enabled; | ||||||
|  |     unsigned num_lights; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| namespace std { | namespace std { | ||||||
|  | @ -182,6 +204,13 @@ private: | ||||||
|             tex_coord1[1] = v.tc1.y.ToFloat32(); |             tex_coord1[1] = v.tc1.y.ToFloat32(); | ||||||
|             tex_coord2[0] = v.tc2.x.ToFloat32(); |             tex_coord2[0] = v.tc2.x.ToFloat32(); | ||||||
|             tex_coord2[1] = v.tc2.y.ToFloat32(); |             tex_coord2[1] = v.tc2.y.ToFloat32(); | ||||||
|  |             normquat[0] = v.quat.x.ToFloat32(); | ||||||
|  |             normquat[1] = v.quat.y.ToFloat32(); | ||||||
|  |             normquat[2] = v.quat.z.ToFloat32(); | ||||||
|  |             normquat[3] = v.quat.w.ToFloat32(); | ||||||
|  |             view[0] = v.view.x.ToFloat32(); | ||||||
|  |             view[1] = v.view.y.ToFloat32(); | ||||||
|  |             view[2] = v.view.z.ToFloat32(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         GLfloat position[4]; |         GLfloat position[4]; | ||||||
|  | @ -189,6 +218,17 @@ private: | ||||||
|         GLfloat tex_coord0[2]; |         GLfloat tex_coord0[2]; | ||||||
|         GLfloat tex_coord1[2]; |         GLfloat tex_coord1[2]; | ||||||
|         GLfloat tex_coord2[2]; |         GLfloat tex_coord2[2]; | ||||||
|  |         GLfloat normquat[4]; | ||||||
|  |         GLfloat view[3]; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct LightSrc { | ||||||
|  |         std::array<GLfloat, 3> diffuse; | ||||||
|  |         INSERT_PADDING_WORDS(1); | ||||||
|  |         std::array<GLfloat, 3> ambient; | ||||||
|  |         INSERT_PADDING_WORDS(1); | ||||||
|  |         std::array<GLfloat, 3> position; | ||||||
|  |         INSERT_PADDING_WORDS(1); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned
 |     /// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned
 | ||||||
|  | @ -198,11 +238,14 @@ private: | ||||||
|         std::array<GLfloat, 4> tev_combiner_buffer_color; |         std::array<GLfloat, 4> tev_combiner_buffer_color; | ||||||
|         GLint alphatest_ref; |         GLint alphatest_ref; | ||||||
|         GLfloat depth_offset; |         GLfloat depth_offset; | ||||||
|         INSERT_PADDING_BYTES(8); |         INSERT_PADDING_WORDS(2); | ||||||
|  |         std::array<GLfloat, 3> lighting_global_ambient; | ||||||
|  |         INSERT_PADDING_WORDS(1); | ||||||
|  |         LightSrc light_src[8]; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     static_assert(sizeof(UniformData) == 0x80, "The size of the UniformData structure has changed, update the structure in the shader"); |     static_assert(sizeof(UniformData) == 0x210, "The size of the UniformData structure has changed, update the structure in the shader"); | ||||||
|     static_assert(sizeof(UniformData) < 16000, "UniformData structure must be less than 16kb as per the OpenGL spec"); |     static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec"); | ||||||
| 
 | 
 | ||||||
|     /// 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); | ||||||
|  | @ -249,6 +292,18 @@ private: | ||||||
|     /// Syncs the TEV combiner color buffer to match the PICA register
 |     /// Syncs the TEV combiner color buffer to match the PICA register
 | ||||||
|     void SyncCombinerColor(); |     void SyncCombinerColor(); | ||||||
| 
 | 
 | ||||||
|  |     /// Syncs the lighting global ambient color to match the PICA register
 | ||||||
|  |     void SyncGlobalAmbient(); | ||||||
|  | 
 | ||||||
|  |     /// Syncs the specified light's diffuse color to match the PICA register
 | ||||||
|  |     void SyncLightDiffuse(int light_index); | ||||||
|  | 
 | ||||||
|  |     /// Syncs the specified light's ambient color to match the PICA register
 | ||||||
|  |     void SyncLightAmbient(int light_index); | ||||||
|  | 
 | ||||||
|  |     /// Syncs the specified light's position to match the PICA register
 | ||||||
|  |     void SyncLightPosition(int light_index); | ||||||
|  | 
 | ||||||
|     /// Syncs the remaining OpenGL drawing state to match the current PICA state
 |     /// Syncs the remaining OpenGL drawing state to match the current PICA state
 | ||||||
|     void SyncDrawState(); |     void SyncDrawState(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -32,8 +32,7 @@ static void AppendSource(std::string& out, TevStageConfig::Source source, | ||||||
|         out += "primary_color"; |         out += "primary_color"; | ||||||
|         break; |         break; | ||||||
|     case Source::PrimaryFragmentColor: |     case Source::PrimaryFragmentColor: | ||||||
|         // HACK: Until we implement fragment lighting, use primary_color
 |         out += "primary_fragment_color"; | ||||||
|         out += "primary_color"; |  | ||||||
|         break; |         break; | ||||||
|     case Source::SecondaryFragmentColor: |     case Source::SecondaryFragmentColor: | ||||||
|         // HACK: Until we implement fragment lighting, use zero
 |         // HACK: Until we implement fragment lighting, use zero
 | ||||||
|  | @ -324,24 +323,67 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) { | ||||||
|     std::string out = R"( |     std::string out = R"( | ||||||
| #version 330 core | #version 330 core | ||||||
| #define NUM_TEV_STAGES 6 | #define NUM_TEV_STAGES 6 | ||||||
|  | #define NUM_LIGHTS 8 | ||||||
| 
 | 
 | ||||||
| in vec4 primary_color; | in vec4 primary_color; | ||||||
| in vec2 texcoord[3]; | in vec2 texcoord[3]; | ||||||
|  | in vec4 normquat; | ||||||
|  | in vec3 view; | ||||||
| 
 | 
 | ||||||
| out vec4 color; | out vec4 color; | ||||||
| 
 | 
 | ||||||
|  | struct LightSrc { | ||||||
|  |     vec3 diffuse; | ||||||
|  |     vec3 ambient; | ||||||
|  |     vec3 position; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| layout (std140) uniform shader_data { | layout (std140) uniform shader_data { | ||||||
|     vec4 const_color[NUM_TEV_STAGES]; |     vec4 const_color[NUM_TEV_STAGES]; | ||||||
|     vec4 tev_combiner_buffer_color; |     vec4 tev_combiner_buffer_color; | ||||||
|     int alphatest_ref; |     int alphatest_ref; | ||||||
|     float depth_offset; |     float depth_offset; | ||||||
|  |     vec3 lighting_global_ambient; | ||||||
|  |     LightSrc light_src[NUM_LIGHTS]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| uniform sampler2D tex[3]; | uniform sampler2D tex[3]; | ||||||
| 
 | 
 | ||||||
| void main() { | void main() { | ||||||
|  | vec4 primary_fragment_color = vec4(0.0); | ||||||
| )"; | )"; | ||||||
| 
 | 
 | ||||||
|  |     if (config.lighting_enabled) { | ||||||
|  |         out += "vec3 normal = normalize(vec3(\n"; | ||||||
|  |         out += "          2.f*(normquat.x*normquat.z + normquat.y*normquat.w),\n"; | ||||||
|  |         out += "          2.f*(normquat.y*normquat.z + normquat.x*normquat.w),\n"; | ||||||
|  |         out += "    1.f - 2.f*(normquat.x*normquat.x + normquat.y*normquat.y)));\n"; | ||||||
|  |         out += "vec4 secondary_color = vec4(0.0);\n"; | ||||||
|  |         out += "vec3 diffuse_sum = vec3(0.0);\n"; | ||||||
|  |         out += "vec3 fragment_position = -view;\n"; | ||||||
|  | 
 | ||||||
|  |         for (unsigned light_index = 0; light_index < config.num_lights; ++light_index) { | ||||||
|  |             unsigned num = config.light_src[light_index].num; | ||||||
|  | 
 | ||||||
|  |             std::string light_vector; | ||||||
|  |             if (config.light_src[light_index].directional) | ||||||
|  |                 light_vector = "normalize(-light_src[" + std::to_string(num) + "].position)"; | ||||||
|  |             else | ||||||
|  |                 light_vector = "normalize(light_src[" + std::to_string(num) + "].position - fragment_position)"; | ||||||
|  | 
 | ||||||
|  |             std::string dot_product; | ||||||
|  |             if (config.light_src[light_index].two_sided_diffuse) | ||||||
|  |                 dot_product = "abs(dot(" + light_vector + ", normal))"; | ||||||
|  |             else | ||||||
|  |                 dot_product = "max(dot(" + light_vector + ", normal), 0.0)"; | ||||||
|  | 
 | ||||||
|  |             out += "diffuse_sum += ((light_src[" + std::to_string(num) + "].diffuse * " + dot_product + ") + light_src[" + std::to_string(num) + "].ambient) * 1.0;\n"; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         out += "diffuse_sum += lighting_global_ambient;\n"; | ||||||
|  |         out += "primary_fragment_color = vec4(clamp(diffuse_sum, vec3(0.0), vec3(1.0)), 1.0);\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Do not do any sort of processing if it's obvious we're not going to pass the alpha test
 |     // Do not do any sort of processing if it's obvious we're not going to pass the alpha test
 | ||||||
|     if (config.alpha_test_func == Regs::CompareFunc::Never) { |     if (config.alpha_test_func == Regs::CompareFunc::Never) { | ||||||
|         out += "discard; }"; |         out += "discard; }"; | ||||||
|  | @ -369,21 +411,28 @@ void main() { | ||||||
| 
 | 
 | ||||||
| std::string GenerateVertexShader() { | std::string GenerateVertexShader() { | ||||||
|     std::string out = "#version 330 core\n"; |     std::string out = "#version 330 core\n"; | ||||||
|  | 
 | ||||||
|     out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION)  + ") in vec4 vert_position;\n"; |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION)  + ") in vec4 vert_position;\n"; | ||||||
|     out += "layout(location = " + std::to_string((int)ATTRIBUTE_COLOR)     + ") in vec4 vert_color;\n"; |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_COLOR)     + ") in vec4 vert_color;\n"; | ||||||
|     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0) + ") in vec2 vert_texcoord0;\n"; |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0) + ") in vec2 vert_texcoord0;\n"; | ||||||
|     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD1) + ") in vec2 vert_texcoord1;\n"; |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD1) + ") in vec2 vert_texcoord1;\n"; | ||||||
|     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD2) + ") in vec2 vert_texcoord2;\n"; |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD2) + ") in vec2 vert_texcoord2;\n"; | ||||||
|  |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_NORMQUAT)  + ") in vec4 vert_normquat;\n"; | ||||||
|  |     out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW)      + ") in vec3 vert_view;\n"; | ||||||
| 
 | 
 | ||||||
|     out += R"( |     out += R"( | ||||||
| out vec4 primary_color; | out vec4 primary_color; | ||||||
| out vec2 texcoord[3]; | out vec2 texcoord[3]; | ||||||
|  | out vec4 normquat; | ||||||
|  | out vec3 view; | ||||||
| 
 | 
 | ||||||
| void main() { | void main() { | ||||||
|     primary_color = vert_color; |     primary_color = vert_color; | ||||||
|     texcoord[0] = vert_texcoord0; |     texcoord[0] = vert_texcoord0; | ||||||
|     texcoord[1] = vert_texcoord1; |     texcoord[1] = vert_texcoord1; | ||||||
|     texcoord[2] = vert_texcoord2; |     texcoord[2] = vert_texcoord2; | ||||||
|  |     normquat = vert_normquat; | ||||||
|  |     view = vert_view; | ||||||
|     gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w); |     gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w); | ||||||
| } | } | ||||||
| )"; | )"; | ||||||
|  |  | ||||||
|  | @ -14,6 +14,8 @@ enum Attributes { | ||||||
|     ATTRIBUTE_TEXCOORD0, |     ATTRIBUTE_TEXCOORD0, | ||||||
|     ATTRIBUTE_TEXCOORD1, |     ATTRIBUTE_TEXCOORD1, | ||||||
|     ATTRIBUTE_TEXCOORD2, |     ATTRIBUTE_TEXCOORD2, | ||||||
|  |     ATTRIBUTE_NORMQUAT, | ||||||
|  |     ATTRIBUTE_VIEW, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -183,4 +183,11 @@ inline std::array<GLfloat, 4> ColorRGBA8(const u32 color) { | ||||||
|            } }; |            } }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | inline std::array<GLfloat, 3> LightColor(const Pica::Regs::LightColor& color) { | ||||||
|  |     return { { color.r / 255.0f, | ||||||
|  |                color.g / 255.0f, | ||||||
|  |                color.b / 255.0f | ||||||
|  |            } }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue