How to build perspective projection matrix (no API)

前端 未结 2 1359
夕颜
夕颜 2020-12-24 03:43

I develop a simple 3D engine (Without any use of API), successfully transformed my scene into world and view space but have trouble projecting my scene (from view space) usi

相关标签:
2条回答
  • 2020-12-24 04:18

    Following is a typical implemenation of perspective projection matrix. And here is a good link to explain everything OpenGL Projection Matrix

    void ComputeFOVProjection( Matrix& result, float fov, float aspect, float nearDist, float farDist, bool leftHanded /* = true */ )
    {
        //
        // General form of the Projection Matrix
        //
        // uh = Cot( fov/2 ) == 1/Tan(fov/2)
        // uw / uh = 1/aspect
        // 
        //   uw         0       0       0
        //    0        uh       0       0
        //    0         0      f/(f-n)  1
        //    0         0    -fn/(f-n)  0
        //
        // Make result to be identity first
    
        // check for bad parameters to avoid divide by zero:
        // if found, assert and return an identity matrix.
        if ( fov <= 0 || aspect == 0 )
        {
            Assert( fov > 0 && aspect != 0 );
            return;
        }
    
        float frustumDepth = farDist - nearDist;
        float oneOverDepth = 1 / frustumDepth;
    
        result[1][1] = 1 / tan(0.5f * fov);
        result[0][0] = (leftHanded ? 1 : -1 ) * result[1][1] / aspect;
        result[2][2] = farDist * oneOverDepth;
        result[3][2] = (-farDist * nearDist) * oneOverDepth;
        result[2][3] = 1;
        result[3][3] = 0;
    }
    
    0 讨论(0)
  • 2020-12-24 04:25

    Another function that may be useful.

    This one is based on left/right/top/bottom/near/far parameters (used in OpenGL):

    static void test(){
        float projectionMatrix[16];
    
        // width and height of viewport to display on (screen dimensions in case of fullscreen rendering)
        float ratio = (float)width/height;
        float left = -ratio;
        float right = ratio;
        float bottom = -1.0f;
        float top = 1.0f;
        float near = -1.0f;
        float far = 100.0f;
    
        frustum(projectionMatrix, 0, left, right, bottom, top, near, far);
    
    }
    
    static void frustum(float *m, int offset,
                         float left, float right, float bottom, float top,
                         float near, float far) {
    
        float r_width  = 1.0f / (right - left);
        float r_height = 1.0f / (top - bottom);
        float r_depth  = 1.0f / (far - near);
        float x =  2.0f * (r_width);
        float y =  2.0f * (r_height);
        float z =  2.0f * (r_depth);
        float A = (right + left) * r_width;
        float B = (top + bottom) * r_height;
        float C = (far + near) * r_depth;
        m[offset + 0] = x;
        m[offset + 3] = -A;
        m[offset + 5] = y;
        m[offset + 7] = -B;
        m[offset + 10] = -z;
        m[offset + 11] = -C;
        m[offset +  1] = 0.0f;
        m[offset +  2] = 0.0f;
        m[offset +  4] = 0.0f;
        m[offset +  6] = 0.0f;
        m[offset +  8] = 0.0f;
        m[offset +  9] = 0.0f;
        m[offset + 12] = 0.0f;
        m[offset + 13] = 0.0f;
        m[offset + 14] = 0.0f;
        m[offset + 15] = 1.0f;
    
    }
    
    0 讨论(0)
提交回复
热议问题