gl_rasterizer: implement custom clip plane
This commit is contained in:
		| @@ -169,6 +169,8 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||||||
|     glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_diff_lut_buffer.handle); |     glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_diff_lut_buffer.handle); | ||||||
|  |  | ||||||
|     // Sync fixed function OpenGL state |     // Sync fixed function OpenGL state | ||||||
|  |     SyncClipEnabled(); | ||||||
|  |     SyncClipCoef(); | ||||||
|     SyncCullMode(); |     SyncCullMode(); | ||||||
|     SyncBlendEnabled(); |     SyncBlendEnabled(); | ||||||
|     SyncBlendFuncs(); |     SyncBlendFuncs(); | ||||||
| @@ -401,6 +403,18 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||||||
|         SyncCullMode(); |         SyncCullMode(); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  |     // Clipping plane | ||||||
|  |     case PICA_REG_INDEX(rasterizer.clip_enable): | ||||||
|  |         SyncClipEnabled(); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[0], 0x48): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[1], 0x49): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[2], 0x4a): | ||||||
|  |     case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[3], 0x4b): | ||||||
|  |         SyncClipCoef(); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|     // Depth modifiers |     // Depth modifiers | ||||||
|     case PICA_REG_INDEX(rasterizer.viewport_depth_range): |     case PICA_REG_INDEX(rasterizer.viewport_depth_range): | ||||||
|         SyncDepthScale(); |         SyncDepthScale(); | ||||||
| @@ -1280,6 +1294,20 @@ void RasterizerOpenGL::SetShader() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void RasterizerOpenGL::SyncClipEnabled() { | ||||||
|  |     state.clip_distance[1] = Pica::g_state.regs.rasterizer.clip_enable != 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void RasterizerOpenGL::SyncClipCoef() { | ||||||
|  |     const auto raw_clip_coef = Pica::g_state.regs.rasterizer.GetClipCoef(); | ||||||
|  |     const GLvec4 new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(), | ||||||
|  |                                   raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()}; | ||||||
|  |     if (new_clip_coef != uniform_block_data.data.clip_coef) { | ||||||
|  |         uniform_block_data.data.clip_coef = new_clip_coef; | ||||||
|  |         uniform_block_data.dirty = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| void RasterizerOpenGL::SyncCullMode() { | void RasterizerOpenGL::SyncCullMode() { | ||||||
|     const auto& regs = Pica::g_state.regs; |     const auto& regs = Pica::g_state.regs; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -151,14 +151,21 @@ private: | |||||||
|         LightSrc light_src[8]; |         LightSrc light_src[8]; | ||||||
|         alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages |         alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages | ||||||
|         alignas(16) GLvec4 tev_combiner_buffer_color; |         alignas(16) GLvec4 tev_combiner_buffer_color; | ||||||
|  |         alignas(16) GLvec4 clip_coef; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     static_assert( |     static_assert( | ||||||
|         sizeof(UniformData) == 0x460, |         sizeof(UniformData) == 0x470, | ||||||
|         "The size of the UniformData structure has changed, update the structure in the shader"); |         "The size of the UniformData structure has changed, update the structure in the shader"); | ||||||
|     static_assert(sizeof(UniformData) < 16384, |     static_assert(sizeof(UniformData) < 16384, | ||||||
|                   "UniformData structure must be less than 16kb as per the OpenGL spec"); |                   "UniformData structure must be less than 16kb as per the OpenGL spec"); | ||||||
|  |  | ||||||
|  |     /// Syncs the clip enabled status to match the PICA register | ||||||
|  |     void SyncClipEnabled(); | ||||||
|  |  | ||||||
|  |     /// Syncs the clip coefficients to match the PICA register | ||||||
|  |     void SyncClipCoef(); | ||||||
|  |  | ||||||
|     /// Sets the OpenGL shader in accordance with the current PICA register state |     /// Sets the OpenGL shader in accordance with the current PICA register state | ||||||
|     void SetShader(); |     void SetShader(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,6 +24,42 @@ using TevStageConfig = TexturingRegs::TevStageConfig; | |||||||
|  |  | ||||||
| namespace GLShader { | namespace GLShader { | ||||||
|  |  | ||||||
|  | static const std::string UniformBlockDef = R"( | ||||||
|  | #define NUM_TEV_STAGES 6 | ||||||
|  | #define NUM_LIGHTS 8 | ||||||
|  |  | ||||||
|  | struct LightSrc { | ||||||
|  |     vec3 specular_0; | ||||||
|  |     vec3 specular_1; | ||||||
|  |     vec3 diffuse; | ||||||
|  |     vec3 ambient; | ||||||
|  |     vec3 position; | ||||||
|  |     vec3 spot_direction; | ||||||
|  |     float dist_atten_bias; | ||||||
|  |     float dist_atten_scale; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | layout (std140) uniform shader_data { | ||||||
|  |     vec2 framebuffer_scale; | ||||||
|  |     int alphatest_ref; | ||||||
|  |     float depth_scale; | ||||||
|  |     float depth_offset; | ||||||
|  |     int scissor_x1; | ||||||
|  |     int scissor_y1; | ||||||
|  |     int scissor_x2; | ||||||
|  |     int scissor_y2; | ||||||
|  |     vec3 fog_color; | ||||||
|  |     vec2 proctex_noise_f; | ||||||
|  |     vec2 proctex_noise_a; | ||||||
|  |     vec2 proctex_noise_p; | ||||||
|  |     vec3 lighting_global_ambient; | ||||||
|  |     LightSrc light_src[NUM_LIGHTS]; | ||||||
|  |     vec4 const_color[NUM_TEV_STAGES]; | ||||||
|  |     vec4 tev_combiner_buffer_color; | ||||||
|  |     vec4 clip_coef; | ||||||
|  | }; | ||||||
|  | )"; | ||||||
|  |  | ||||||
| PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { | PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { | ||||||
|     PicaShaderConfig res; |     PicaShaderConfig res; | ||||||
|  |  | ||||||
| @@ -1008,8 +1044,6 @@ 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_LIGHTS 8 |  | ||||||
|  |  | ||||||
| in vec4 primary_color; | in vec4 primary_color; | ||||||
| in vec2 texcoord[3]; | in vec2 texcoord[3]; | ||||||
| @@ -1021,36 +1055,6 @@ in vec4 gl_FragCoord; | |||||||
|  |  | ||||||
| out vec4 color; | out vec4 color; | ||||||
|  |  | ||||||
| struct LightSrc { |  | ||||||
|     vec3 specular_0; |  | ||||||
|     vec3 specular_1; |  | ||||||
|     vec3 diffuse; |  | ||||||
|     vec3 ambient; |  | ||||||
|     vec3 position; |  | ||||||
|     vec3 spot_direction; |  | ||||||
|     float dist_atten_bias; |  | ||||||
|     float dist_atten_scale; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| layout (std140) uniform shader_data { |  | ||||||
|     vec2 framebuffer_scale; |  | ||||||
|     int alphatest_ref; |  | ||||||
|     float depth_scale; |  | ||||||
|     float depth_offset; |  | ||||||
|     int scissor_x1; |  | ||||||
|     int scissor_y1; |  | ||||||
|     int scissor_x2; |  | ||||||
|     int scissor_y2; |  | ||||||
|     vec3 fog_color; |  | ||||||
|     vec2 proctex_noise_f; |  | ||||||
|     vec2 proctex_noise_a; |  | ||||||
|     vec2 proctex_noise_p; |  | ||||||
|     vec3 lighting_global_ambient; |  | ||||||
|     LightSrc light_src[NUM_LIGHTS]; |  | ||||||
|     vec4 const_color[NUM_TEV_STAGES]; |  | ||||||
|     vec4 tev_combiner_buffer_color; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| uniform sampler2D tex[3]; | uniform sampler2D tex[3]; | ||||||
| uniform samplerBuffer lighting_lut; | uniform samplerBuffer lighting_lut; | ||||||
| uniform samplerBuffer fog_lut; | uniform samplerBuffer fog_lut; | ||||||
| @@ -1059,7 +1063,11 @@ uniform samplerBuffer proctex_color_map; | |||||||
| uniform samplerBuffer proctex_alpha_map; | uniform samplerBuffer proctex_alpha_map; | ||||||
| uniform samplerBuffer proctex_lut; | uniform samplerBuffer proctex_lut; | ||||||
| uniform samplerBuffer proctex_diff_lut; | uniform samplerBuffer proctex_diff_lut; | ||||||
|  | )"; | ||||||
|  |  | ||||||
|  |     out += UniformBlockDef; | ||||||
|  |  | ||||||
|  |     out += R"( | ||||||
| // Rotate the vector v by the quaternion q | // Rotate the vector v by the quaternion q | ||||||
| vec3 quaternion_rotate(vec4 q, vec3 v) { | vec3 quaternion_rotate(vec4 q, vec3 v) { | ||||||
|     return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); |     return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); | ||||||
| @@ -1190,6 +1198,12 @@ out float texcoord0_w; | |||||||
| out vec4 normquat; | out vec4 normquat; | ||||||
| out vec3 view; | out vec3 view; | ||||||
|  |  | ||||||
|  | )"; | ||||||
|  |  | ||||||
|  |     out += UniformBlockDef; | ||||||
|  |  | ||||||
|  |     out += R"( | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
|     primary_color = vert_color; |     primary_color = vert_color; | ||||||
|     texcoord[0] = vert_texcoord0; |     texcoord[0] = vert_texcoord0; | ||||||
| @@ -1200,7 +1214,7 @@ void main() { | |||||||
|     view = vert_view; |     view = vert_view; | ||||||
|     gl_Position = vert_position; |     gl_Position = vert_position; | ||||||
|     gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0 |     gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0 | ||||||
|     // TODO (wwylele): calculate gl_ClipDistance[1] from user-defined clipping plane |     gl_ClipDistance[1] = dot(clip_coef, vert_position); | ||||||
| } | } | ||||||
| )"; | )"; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user