Smoothly transition from orthographic projection to perspective projection?











up vote
6
down vote

favorite
2












I'm developing a game that consists of 2 stages, one of these has an orthographic projection, and the other stage has a perspective projection.



Currently when we go between modes we fade to black, and then come back in the new camera mode.



How would I go about smoothly transitioning between the two?










share|improve this question


















  • 1




    I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
    – user463035818
    Feb 8 '17 at 19:12












  • This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
    – Jared Updike
    Feb 22 '17 at 18:02















up vote
6
down vote

favorite
2












I'm developing a game that consists of 2 stages, one of these has an orthographic projection, and the other stage has a perspective projection.



Currently when we go between modes we fade to black, and then come back in the new camera mode.



How would I go about smoothly transitioning between the two?










share|improve this question


















  • 1




    I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
    – user463035818
    Feb 8 '17 at 19:12












  • This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
    – Jared Updike
    Feb 22 '17 at 18:02













up vote
6
down vote

favorite
2









up vote
6
down vote

favorite
2






2





I'm developing a game that consists of 2 stages, one of these has an orthographic projection, and the other stage has a perspective projection.



Currently when we go between modes we fade to black, and then come back in the new camera mode.



How would I go about smoothly transitioning between the two?










share|improve this question













I'm developing a game that consists of 2 stages, one of these has an orthographic projection, and the other stage has a perspective projection.



Currently when we go between modes we fade to black, and then come back in the new camera mode.



How would I go about smoothly transitioning between the two?







c++ opengl graphics






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Feb 8 '17 at 19:01









Jackson Rushing

426




426








  • 1




    I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
    – user463035818
    Feb 8 '17 at 19:12












  • This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
    – Jared Updike
    Feb 22 '17 at 18:02














  • 1




    I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
    – user463035818
    Feb 8 '17 at 19:12












  • This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
    – Jared Updike
    Feb 22 '17 at 18:02








1




1




I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
– user463035818
Feb 8 '17 at 19:12






I am just guessing, but if P1(x) is the coordinates in one projection and P2(x) in the other, then you could get a smooth transition f P1(x) + (1-f) P2(x) by smoothly changing f from 0 to 1
– user463035818
Feb 8 '17 at 19:12














This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
– Jared Updike
Feb 22 '17 at 18:02




This question is interesting and clear, but as written it makes it sound like you are asking for someone to do the work for you. You should add more details, like the matrix for the ortho and the matrix for the perspective transformation, etc. As the other comment mentions, if your ortho projection is a 4x4 matrix and the perspective matrix is too, you could try a linear combination of the two.
– Jared Updike
Feb 22 '17 at 18:02












3 Answers
3






active

oldest

votes

















up vote
5
down vote



accepted










There are probably a handful of ways of accomplishing this, the two I found that seemed like they would work the best were:




  1. Lerping all the matrix elements from one matrix to the other. Apparently this works pretty well all things considered. I don't believe this transition will appear linear, though. You could try to give it an easing function instead of doing the interpolation linearly


  2. A dolly zoom on the perspective matrix going to/from a near 0 field of view. You would pop from the orthographic matrix to the near 0 perspective matrix and lerp the fov out to your target, and probably be heavily tweaking the near/far planes as you go. In reverse you would lerp to 0 and then pop to the orthographic matrix. The idea behind this being that things appear flatter with a lower fov and that a fov of 0 is essentially an orthographic projection. This is more complex but can also be tweaked a whole lot more.







share|improve this answer























  • Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
    – Jackson Rushing
    Feb 8 '17 at 19:32












  • Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
    – Robert Rouhani
    Feb 8 '17 at 19:36


















up vote
1
down vote













If you have access to a programmable pipeline (a.k.a. shaders), you can do the transition in the vertex shader. I have found that this works very well and does not introduce artifacts. Here's a GLSL code snippet:



#version 150

uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;

uniform float uNearClipPlane = 1.0;
uniform vec2 uPerspToOrtho = vec2( 0.0 );

in vec4 inPosition;

void main( void )
{
// Calculate view space position.
vec4 view = uViewMatrix * uModelMatrix * inPosition;

// Scale x&y to 'undo' perspective projection.
view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );

// Output clip space coordinate.
gl_Position = uProjectionMatrix * view;
}


In the code, uPerspToOrtho is a vec2 (e.g. a float2) that contains a value in the range [0..1]. When set to 0, your coordinates will use perspective projection (assuming your projection matrix is a perspective one). When set to 1, your coordinates will behave as if projected by an orthographic projection matrix. You can do this separately for the X- and Y-axes.



'uNearClipPlane' is the near plane distance, which is the value you used to create the perspective projection matrix.



When converting this to HLSL, you may need to use view.z instead of -view.z, but I could be wrong.



I hope you find this useful.



Edit: instead of passing in the near clip plane distance, you can also extract it from the projection matrix. For OpenGL, this is how:



float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );


Edit 2: you can optimize the code by doing the scaling on x and y at the same time:



view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );


To get rid of the division, you could multiply by the inverse near plane distance:



uniform float uInvNearClipPlane; // = 1.0 / zNear





share|improve this answer






























    up vote
    1
    down vote













    I managed to do this without the explicit use of matrices. I used Java so the syntax is different but comparable. One of the things I used was this mix() function. It returns value1 when factor is 1 and value2 when factor is 0, and has a linear transition for every value in between.



    private double mix(double value1, double value2, double factor)
    {
    return (value1 * factor) + (value2 * (1 - factor));
    }


    When I call this function, I use value1 for perspective and value2 for orthographic, like so:mix(focalLength/voxel.z, orthoZoom, factor)



    When determining your focal length and orthographic zoom factor, it is helpful to know that anything at distance focalLength/orthoZoom away from the camera will project to the same point throughout the transition.



    Hope this helps. You can download my program to see how it looks at https://github.com/npetrangelo/3rd-Dimension/releases.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42121494%2fsmoothly-transition-from-orthographic-projection-to-perspective-projection%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      5
      down vote



      accepted










      There are probably a handful of ways of accomplishing this, the two I found that seemed like they would work the best were:




      1. Lerping all the matrix elements from one matrix to the other. Apparently this works pretty well all things considered. I don't believe this transition will appear linear, though. You could try to give it an easing function instead of doing the interpolation linearly


      2. A dolly zoom on the perspective matrix going to/from a near 0 field of view. You would pop from the orthographic matrix to the near 0 perspective matrix and lerp the fov out to your target, and probably be heavily tweaking the near/far planes as you go. In reverse you would lerp to 0 and then pop to the orthographic matrix. The idea behind this being that things appear flatter with a lower fov and that a fov of 0 is essentially an orthographic projection. This is more complex but can also be tweaked a whole lot more.







      share|improve this answer























      • Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
        – Jackson Rushing
        Feb 8 '17 at 19:32












      • Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
        – Robert Rouhani
        Feb 8 '17 at 19:36















      up vote
      5
      down vote



      accepted










      There are probably a handful of ways of accomplishing this, the two I found that seemed like they would work the best were:




      1. Lerping all the matrix elements from one matrix to the other. Apparently this works pretty well all things considered. I don't believe this transition will appear linear, though. You could try to give it an easing function instead of doing the interpolation linearly


      2. A dolly zoom on the perspective matrix going to/from a near 0 field of view. You would pop from the orthographic matrix to the near 0 perspective matrix and lerp the fov out to your target, and probably be heavily tweaking the near/far planes as you go. In reverse you would lerp to 0 and then pop to the orthographic matrix. The idea behind this being that things appear flatter with a lower fov and that a fov of 0 is essentially an orthographic projection. This is more complex but can also be tweaked a whole lot more.







      share|improve this answer























      • Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
        – Jackson Rushing
        Feb 8 '17 at 19:32












      • Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
        – Robert Rouhani
        Feb 8 '17 at 19:36













      up vote
      5
      down vote



      accepted







      up vote
      5
      down vote



      accepted






      There are probably a handful of ways of accomplishing this, the two I found that seemed like they would work the best were:




      1. Lerping all the matrix elements from one matrix to the other. Apparently this works pretty well all things considered. I don't believe this transition will appear linear, though. You could try to give it an easing function instead of doing the interpolation linearly


      2. A dolly zoom on the perspective matrix going to/from a near 0 field of view. You would pop from the orthographic matrix to the near 0 perspective matrix and lerp the fov out to your target, and probably be heavily tweaking the near/far planes as you go. In reverse you would lerp to 0 and then pop to the orthographic matrix. The idea behind this being that things appear flatter with a lower fov and that a fov of 0 is essentially an orthographic projection. This is more complex but can also be tweaked a whole lot more.







      share|improve this answer














      There are probably a handful of ways of accomplishing this, the two I found that seemed like they would work the best were:




      1. Lerping all the matrix elements from one matrix to the other. Apparently this works pretty well all things considered. I don't believe this transition will appear linear, though. You could try to give it an easing function instead of doing the interpolation linearly


      2. A dolly zoom on the perspective matrix going to/from a near 0 field of view. You would pop from the orthographic matrix to the near 0 perspective matrix and lerp the fov out to your target, and probably be heavily tweaking the near/far planes as you go. In reverse you would lerp to 0 and then pop to the orthographic matrix. The idea behind this being that things appear flatter with a lower fov and that a fov of 0 is essentially an orthographic projection. This is more complex but can also be tweaked a whole lot more.








      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Feb 8 '17 at 19:33









      Varaquilex

      2,53953054




      2,53953054










      answered Feb 8 '17 at 19:29









      Robert Rouhani

      12.7k53753




      12.7k53753












      • Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
        – Jackson Rushing
        Feb 8 '17 at 19:32












      • Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
        – Robert Rouhani
        Feb 8 '17 at 19:36


















      • Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
        – Jackson Rushing
        Feb 8 '17 at 19:32












      • Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
        – Robert Rouhani
        Feb 8 '17 at 19:36
















      Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
      – Jackson Rushing
      Feb 8 '17 at 19:32






      Great, thanks! I'd thought about dolly zooms, but I hadn't thought of "replicating" the orthographic view in a perspective view with 0 field of view. So theoretically, all I'd have to do is tweak the camera position with a 0 field of view to recreate the orthographic scene, and then interpolate the field of view and camera position?
      – Jackson Rushing
      Feb 8 '17 at 19:32














      Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
      – Robert Rouhani
      Feb 8 '17 at 19:36




      Theoretically, yeah. A lot of results came up for Unity specific stuff, but the theory/math are the same - answers.unity3d.com/questions/58306/…
      – Robert Rouhani
      Feb 8 '17 at 19:36












      up vote
      1
      down vote













      If you have access to a programmable pipeline (a.k.a. shaders), you can do the transition in the vertex shader. I have found that this works very well and does not introduce artifacts. Here's a GLSL code snippet:



      #version 150

      uniform mat4 uModelMatrix;
      uniform mat4 uViewMatrix;
      uniform mat4 uProjectionMatrix;

      uniform float uNearClipPlane = 1.0;
      uniform vec2 uPerspToOrtho = vec2( 0.0 );

      in vec4 inPosition;

      void main( void )
      {
      // Calculate view space position.
      vec4 view = uViewMatrix * uModelMatrix * inPosition;

      // Scale x&y to 'undo' perspective projection.
      view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
      view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );

      // Output clip space coordinate.
      gl_Position = uProjectionMatrix * view;
      }


      In the code, uPerspToOrtho is a vec2 (e.g. a float2) that contains a value in the range [0..1]. When set to 0, your coordinates will use perspective projection (assuming your projection matrix is a perspective one). When set to 1, your coordinates will behave as if projected by an orthographic projection matrix. You can do this separately for the X- and Y-axes.



      'uNearClipPlane' is the near plane distance, which is the value you used to create the perspective projection matrix.



      When converting this to HLSL, you may need to use view.z instead of -view.z, but I could be wrong.



      I hope you find this useful.



      Edit: instead of passing in the near clip plane distance, you can also extract it from the projection matrix. For OpenGL, this is how:



      float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );


      Edit 2: you can optimize the code by doing the scaling on x and y at the same time:



      view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );


      To get rid of the division, you could multiply by the inverse near plane distance:



      uniform float uInvNearClipPlane; // = 1.0 / zNear





      share|improve this answer



























        up vote
        1
        down vote













        If you have access to a programmable pipeline (a.k.a. shaders), you can do the transition in the vertex shader. I have found that this works very well and does not introduce artifacts. Here's a GLSL code snippet:



        #version 150

        uniform mat4 uModelMatrix;
        uniform mat4 uViewMatrix;
        uniform mat4 uProjectionMatrix;

        uniform float uNearClipPlane = 1.0;
        uniform vec2 uPerspToOrtho = vec2( 0.0 );

        in vec4 inPosition;

        void main( void )
        {
        // Calculate view space position.
        vec4 view = uViewMatrix * uModelMatrix * inPosition;

        // Scale x&y to 'undo' perspective projection.
        view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
        view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );

        // Output clip space coordinate.
        gl_Position = uProjectionMatrix * view;
        }


        In the code, uPerspToOrtho is a vec2 (e.g. a float2) that contains a value in the range [0..1]. When set to 0, your coordinates will use perspective projection (assuming your projection matrix is a perspective one). When set to 1, your coordinates will behave as if projected by an orthographic projection matrix. You can do this separately for the X- and Y-axes.



        'uNearClipPlane' is the near plane distance, which is the value you used to create the perspective projection matrix.



        When converting this to HLSL, you may need to use view.z instead of -view.z, but I could be wrong.



        I hope you find this useful.



        Edit: instead of passing in the near clip plane distance, you can also extract it from the projection matrix. For OpenGL, this is how:



        float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );


        Edit 2: you can optimize the code by doing the scaling on x and y at the same time:



        view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );


        To get rid of the division, you could multiply by the inverse near plane distance:



        uniform float uInvNearClipPlane; // = 1.0 / zNear





        share|improve this answer

























          up vote
          1
          down vote










          up vote
          1
          down vote









          If you have access to a programmable pipeline (a.k.a. shaders), you can do the transition in the vertex shader. I have found that this works very well and does not introduce artifacts. Here's a GLSL code snippet:



          #version 150

          uniform mat4 uModelMatrix;
          uniform mat4 uViewMatrix;
          uniform mat4 uProjectionMatrix;

          uniform float uNearClipPlane = 1.0;
          uniform vec2 uPerspToOrtho = vec2( 0.0 );

          in vec4 inPosition;

          void main( void )
          {
          // Calculate view space position.
          vec4 view = uViewMatrix * uModelMatrix * inPosition;

          // Scale x&y to 'undo' perspective projection.
          view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
          view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );

          // Output clip space coordinate.
          gl_Position = uProjectionMatrix * view;
          }


          In the code, uPerspToOrtho is a vec2 (e.g. a float2) that contains a value in the range [0..1]. When set to 0, your coordinates will use perspective projection (assuming your projection matrix is a perspective one). When set to 1, your coordinates will behave as if projected by an orthographic projection matrix. You can do this separately for the X- and Y-axes.



          'uNearClipPlane' is the near plane distance, which is the value you used to create the perspective projection matrix.



          When converting this to HLSL, you may need to use view.z instead of -view.z, but I could be wrong.



          I hope you find this useful.



          Edit: instead of passing in the near clip plane distance, you can also extract it from the projection matrix. For OpenGL, this is how:



          float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );


          Edit 2: you can optimize the code by doing the scaling on x and y at the same time:



          view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );


          To get rid of the division, you could multiply by the inverse near plane distance:



          uniform float uInvNearClipPlane; // = 1.0 / zNear





          share|improve this answer














          If you have access to a programmable pipeline (a.k.a. shaders), you can do the transition in the vertex shader. I have found that this works very well and does not introduce artifacts. Here's a GLSL code snippet:



          #version 150

          uniform mat4 uModelMatrix;
          uniform mat4 uViewMatrix;
          uniform mat4 uProjectionMatrix;

          uniform float uNearClipPlane = 1.0;
          uniform vec2 uPerspToOrtho = vec2( 0.0 );

          in vec4 inPosition;

          void main( void )
          {
          // Calculate view space position.
          vec4 view = uViewMatrix * uModelMatrix * inPosition;

          // Scale x&y to 'undo' perspective projection.
          view.x = mix( view.x, view.x * ( -view.z / uNearClipPlane ), uPerspToOrtho.x );
          view.y = mix( view.y, view.y * ( -view.z / uNearClipPlane ), uPerspToOrtho.y );

          // Output clip space coordinate.
          gl_Position = uProjectionMatrix * view;
          }


          In the code, uPerspToOrtho is a vec2 (e.g. a float2) that contains a value in the range [0..1]. When set to 0, your coordinates will use perspective projection (assuming your projection matrix is a perspective one). When set to 1, your coordinates will behave as if projected by an orthographic projection matrix. You can do this separately for the X- and Y-axes.



          'uNearClipPlane' is the near plane distance, which is the value you used to create the perspective projection matrix.



          When converting this to HLSL, you may need to use view.z instead of -view.z, but I could be wrong.



          I hope you find this useful.



          Edit: instead of passing in the near clip plane distance, you can also extract it from the projection matrix. For OpenGL, this is how:



          float zNear = 2.0 * uProjectionMatrix[3][2] / ( 2.0 * uProjectionMatrix[2][2] - 2.0 );


          Edit 2: you can optimize the code by doing the scaling on x and y at the same time:



          view.xy = mix( view.xy, view.xy * ( -view.z / uNearClipPlane ), uPerspToOrtho.xy );


          To get rid of the division, you could multiply by the inverse near plane distance:



          uniform float uInvNearClipPlane; // = 1.0 / zNear






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 11 at 7:39

























          answered Jul 5 at 17:26









          Paul Houx

          1,2591012




          1,2591012






















              up vote
              1
              down vote













              I managed to do this without the explicit use of matrices. I used Java so the syntax is different but comparable. One of the things I used was this mix() function. It returns value1 when factor is 1 and value2 when factor is 0, and has a linear transition for every value in between.



              private double mix(double value1, double value2, double factor)
              {
              return (value1 * factor) + (value2 * (1 - factor));
              }


              When I call this function, I use value1 for perspective and value2 for orthographic, like so:mix(focalLength/voxel.z, orthoZoom, factor)



              When determining your focal length and orthographic zoom factor, it is helpful to know that anything at distance focalLength/orthoZoom away from the camera will project to the same point throughout the transition.



              Hope this helps. You can download my program to see how it looks at https://github.com/npetrangelo/3rd-Dimension/releases.






              share|improve this answer



























                up vote
                1
                down vote













                I managed to do this without the explicit use of matrices. I used Java so the syntax is different but comparable. One of the things I used was this mix() function. It returns value1 when factor is 1 and value2 when factor is 0, and has a linear transition for every value in between.



                private double mix(double value1, double value2, double factor)
                {
                return (value1 * factor) + (value2 * (1 - factor));
                }


                When I call this function, I use value1 for perspective and value2 for orthographic, like so:mix(focalLength/voxel.z, orthoZoom, factor)



                When determining your focal length and orthographic zoom factor, it is helpful to know that anything at distance focalLength/orthoZoom away from the camera will project to the same point throughout the transition.



                Hope this helps. You can download my program to see how it looks at https://github.com/npetrangelo/3rd-Dimension/releases.






                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  I managed to do this without the explicit use of matrices. I used Java so the syntax is different but comparable. One of the things I used was this mix() function. It returns value1 when factor is 1 and value2 when factor is 0, and has a linear transition for every value in between.



                  private double mix(double value1, double value2, double factor)
                  {
                  return (value1 * factor) + (value2 * (1 - factor));
                  }


                  When I call this function, I use value1 for perspective and value2 for orthographic, like so:mix(focalLength/voxel.z, orthoZoom, factor)



                  When determining your focal length and orthographic zoom factor, it is helpful to know that anything at distance focalLength/orthoZoom away from the camera will project to the same point throughout the transition.



                  Hope this helps. You can download my program to see how it looks at https://github.com/npetrangelo/3rd-Dimension/releases.






                  share|improve this answer














                  I managed to do this without the explicit use of matrices. I used Java so the syntax is different but comparable. One of the things I used was this mix() function. It returns value1 when factor is 1 and value2 when factor is 0, and has a linear transition for every value in between.



                  private double mix(double value1, double value2, double factor)
                  {
                  return (value1 * factor) + (value2 * (1 - factor));
                  }


                  When I call this function, I use value1 for perspective and value2 for orthographic, like so:mix(focalLength/voxel.z, orthoZoom, factor)



                  When determining your focal length and orthographic zoom factor, it is helpful to know that anything at distance focalLength/orthoZoom away from the camera will project to the same point throughout the transition.



                  Hope this helps. You can download my program to see how it looks at https://github.com/npetrangelo/3rd-Dimension/releases.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 12 at 15:30









                  genpfault

                  41.3k95097




                  41.3k95097










                  answered Apr 20 '17 at 1:52









                  Nathan Petrangelo

                  112




                  112






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42121494%2fsmoothly-transition-from-orthographic-projection-to-perspective-projection%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Florida Star v. B. J. F.

                      Error while running script in elastic search , gateway timeout

                      Adding quotations to stringified JSON object values