diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 3 | ||||
| -rw-r--r-- | src/video_core/swrasterizer/clipper.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/swrasterizer/rasterizer.h | 6 | 
6 files changed, 28 insertions, 10 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 1c6c15a58..aa95ef21d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -28,6 +28,9 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));  MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));  RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { +    // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 +    state.clip_distance[0] = true; +      // Create sampler objects      for (size_t i = 0; i < texture_samplers.size(); ++i) {          texture_samplers[i].Create(); diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index ae67aab05..015e69da9 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -1112,7 +1112,10 @@ vec4 secondary_fragment_color = vec4(0.0);                 "gl_FragCoord.y < scissor_y2)) discard;\n";      } -    out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; +    // After perspective divide, OpenGL transform z_over_w from [-1, 1] to [near, far]. Here we use +    // default near = 0 and far = 1, and undo the transformation to get the original z_over_w, then +    // do our own transformation according to PICA specification. +    out += "float z_over_w = 2.0 * gl_FragCoord.z - 1.0;\n";      out += "float depth = z_over_w * depth_scale + depth_offset;\n";      if (state.depthmap_enable == RasterizerRegs::DepthBuffering::WBuffering) {          out += "depth /= gl_FragCoord.w;\n"; @@ -1195,7 +1198,9 @@ void main() {      texcoord0_w = vert_texcoord0_w;      normquat = vert_normquat;      view = vert_view; -    gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w); +    gl_Position = vert_position; +    gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0 +    // TODO (wwylele): calculate gl_ClipDistance[1] from user-defined clipping plane  }  )"; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index bc9d34b84..06a905766 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -68,6 +68,8 @@ OpenGLState::OpenGLState() {      draw.vertex_buffer = 0;      draw.uniform_buffer = 0;      draw.shader_program = 0; + +    clip_distance = {};  }  void OpenGLState::Apply() const { @@ -261,6 +263,17 @@ void OpenGLState::Apply() const {          glUseProgram(draw.shader_program);      } +    // Clip distance +    for (size_t i = 0; i < clip_distance.size(); ++i) { +        if (clip_distance[i] != cur_state.clip_distance[i]) { +            if (clip_distance[i]) { +                glEnable(GL_CLIP_DISTANCE0 + i); +            } else { +                glDisable(GL_CLIP_DISTANCE0 + i); +            } +        } +    } +      cur_state = *this;  } diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 745a74479..437fe34c4 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -4,6 +4,7 @@  #pragma once +#include <array>  #include <glad/glad.h>  namespace TextureUnits { @@ -123,6 +124,8 @@ public:          GLuint shader_program;   // GL_CURRENT_PROGRAM      } draw; +    std::array<bool, 2> clip_distance; // GL_CLIP_DISTANCE +      OpenGLState();      /// Get the currently active OpenGL state diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp index 7537689b7..cdbc71502 100644 --- a/src/video_core/swrasterizer/clipper.cpp +++ b/src/video_core/swrasterizer/clipper.cpp @@ -125,10 +125,6 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu          {Math::MakeVec(f0, f0, f0, -f1), Math::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON      }}; -    // TODO: If one vertex lies outside one of the depth clipping planes, some platforms (e.g. Wii) -    //       drop the whole primitive instead of clipping the primitive properly. We should test if -    //       this happens on the 3DS, too. -      // Simple implementation of the Sutherland-Hodgman clipping algorithm.      // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)      for (auto edge : clipping_edges) { diff --git a/src/video_core/swrasterizer/rasterizer.h b/src/video_core/swrasterizer/rasterizer.h index 2f0877581..66cd6cfd4 100644 --- a/src/video_core/swrasterizer/rasterizer.h +++ b/src/video_core/swrasterizer/rasterizer.h @@ -19,10 +19,9 @@ struct Vertex : Shader::OutputVertex {      // Linear interpolation      // factor: 0=this, 1=vtx +    // Note: This function cannot be called after perspective divide      void Lerp(float24 factor, const Vertex& vtx) {          pos = pos * factor + vtx.pos * (float24::FromFloat32(1) - factor); - -        // TODO: Should perform perspective correct interpolation here...          quat = quat * factor + vtx.quat * (float24::FromFloat32(1) - factor);          color = color * factor + vtx.color * (float24::FromFloat32(1) - factor);          tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor); @@ -30,12 +29,11 @@ struct Vertex : Shader::OutputVertex {          tc0_w = tc0_w * factor + vtx.tc0_w * (float24::FromFloat32(1) - factor);          view = view * factor + vtx.view * (float24::FromFloat32(1) - factor);          tc2 = tc2 * factor + vtx.tc2 * (float24::FromFloat32(1) - factor); - -        screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor);      }      // Linear interpolation      // factor: 0=v0, 1=v1 +    // Note: This function cannot be called after perspective divide      static Vertex Lerp(float24 factor, const Vertex& v0, const Vertex& v1) {          Vertex ret = v0;          ret.Lerp(factor, v1);  | 
