国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣

這篇具有很好參考價值的文章主要介紹了第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣

第一章 OpenGL ES 基礎(chǔ)-屏幕、紋理、頂點坐標(biāo)
第二章 OpenGL ES 基礎(chǔ)-GLSL語法簡單總結(jié)
第三章 OpenGL ES 基礎(chǔ)-GLSL渲染紋理
第四章 OpenGL ES 基礎(chǔ)-位移、縮放、旋轉(zhuǎn)原理
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣

什么是透視投影?

模型都是3D的,但屏幕是2D的。如何將3D空間投影到2D平面,還能保持深度的視覺效果?在OpenGL中,采用透視投影矩陣作用頂點來實現(xiàn),即完成縮放、選擇、位移之后,進行透視投影的操作。

第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣

投影矩陣原理

投影矩陣用于投影變換,投影變換是三維場景中的物體正確渲染到二維屏幕的重要過程之一。在透視矩陣中,有幾個重要元素:視場角、成像設(shè)備的寬高比、場景中能看到的最近距離以及最遠(yuǎn)距離,通過這幾個參數(shù)可以定義一個視錐體對象,從而模擬人眼或者相機的在三維空間中的成像原理,通常有這個幾個值就可以構(gòu)造一個4x4的矩陣,通過OpenGL提供的接口設(shè)置即可。參數(shù)(near=n, far=f, left=l, right=r, top=t, bottom=b),對應(yīng)矩陣如下:

第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
假設(shè)下圖是Z方向投影到屏幕的立體圖如下 ,根據(jù)上面矩陣參數(shù)可以推到為圖的對應(yīng)參數(shù)
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
側(cè)視圖看
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣

根據(jù)上圖推出對應(yīng)參數(shù)技術(shù)

  • 1.aspect:屏幕寬高比m_screenWidth / m_screenHeight
  • 2.n:近截面z軸坐標(biāo)
  • 3.f :遠(yuǎn)截面z軸坐標(biāo)
  • 4.fov角度
  • 5.我們可以求出t的長度t=n*tan(fov/2)
  • 6.t = n * Math.tan(fov / 2);// n*tan(fov / 2)=T(勾股定理,計算直角邊)
  • 7.b = -t;
  • 8.r = aspect * t;
  • 9.l= -r;

上面推到的對應(yīng)矩陣參數(shù),為什么要做這樣矩陣,視錐體視圖進一步的介紹,更加深刻認(rèn)識和理解還是圖解,下面透視投影進行點位和對應(yīng)參數(shù),如下:
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣

對稱攝像機在相機空間中 YZ 平面上的視錐體視圖。請注意,頂部(t)、底部(b)和近裁剪面距離(n)都決定了垂直視野角(θ)。遠(yuǎn)處平面上的 Y 范圍是通過比率 f/n 計算的,因為對于原點/近處三角形和原點/遠(yuǎn)處三角形來說,這些角度都是相同的。由下圖可以計算相關(guān)點位
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
對稱攝像機在相機空間中 XZ 平面上的視錐體視圖。與圖1幾乎相同,只是使用左側(cè)(l)和右側(cè)(r)的視錐體范圍。

  t = n * Math.tan(fov / 2);
  b = -t;
  r = aspect * t;
  l= -r;

通過上面知識和原理,就可以實現(xiàn)對應(yīng)代碼生成4x4的矩陣

  • const double DEG2RAD = 3.14159265 / 180;:該行定義了一個常量 DEG2RAD,用于將角度轉(zhuǎn)換為弧度
  • float tangent = tanf(fFov / 2.f * DEG2RAD);:在這行中,fFov 表示視場角(Field of View),它通常以角度表示。首先,將 fFov 視場角轉(zhuǎn)換為弧度,并取其一半。
    m3dLoadIdentity44對應(yīng)的初始化可以查看這篇-OpenGL 位移、縮放、旋轉(zhuǎn)原理
void m3dMakePerspectiveMatrix(M3DMatrix44f mProjection, float fFov, float fAspect, float zMin, float zMax)
{
	m3dLoadIdentity44(mProjection); // Fastest way to get most valid values already in place
	const double DEG2RAD = 3.14159265 / 180;
	float tangent = tanf(fFov / 2.f * DEG2RAD);   // tangent of half fovY
	float height = zMin * tangent;           // half height of near plane
	float width = height * fAspect;       // half width of near plane

	float l = -width, r = width, b = -height, t = height, n = zMin, f = zMax;
	// params: left, right, bottom, top, near, far
    mProjection[0]  =  2 * n / (r - l);
    mProjection[5]  =  2 * n / (t - b);
    mProjection[8]  =  (r + l) / (r - l);
    mProjection[9]  =  (t + b) / (t - b);
    mProjection[10] = -(f + n) / (f - n);
    mProjection[11] = -1;
    mProjection[14] = -(2 * f * n) / (f - n);
    mProjection[15] =  0;
}

正交投影矩陣原理

正交投影矩陣中 x 軸方向的縮放值
正交投影矩陣(Orthographic Projection Matrix)相較于透視投影矩陣具有以下特點:

  1. 等比例縮放:正交投影矩陣將物體等比例地投影到屏幕上,不會因為距離遠(yuǎn)近而導(dǎo)致物體大小的變化,保持了物體在觀察者視野中的大小一致性。

  2. 平行投影:所有的光線都是平行的,與觀察者的位置無關(guān)。這意味著從不同位置看到的物體大小和形狀保持不變。

  3. 沒有透視效果:正交投影不會出現(xiàn)透視效果,即物體遠(yuǎn)近大小差異不會隨著距離改變而產(chǎn)生。

  4. 簡單計算:相對于透視投影,正交投影的計算比較簡單,只需要定義視圖空間的邊界值即可,不涉及復(fù)雜的透視變換公式。

第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
結(jié)合圖,我們知道,正交投影其實就是將目標(biāo)視域體[L,B,N]至[R,T,F]的區(qū)域
度量到規(guī)則視域體[-1,-1,0]至[1,1,1]的區(qū)域中,請仔細(xì)理解這句話,這意味著,我可以將很大的一個區(qū)域映射到的規(guī)則視域體cvv中,也可以將很小的區(qū)域映射到使視域體中,而這個區(qū)域的具體的大小是由L,B,N 至R,T,F的區(qū)域大小決定的。
在正交投影矩陣中,通常不需要考慮將 x 軸方向的縮放值乘以 near 或者 far 的情況。在一個簡單的正交投影矩陣中,x、y、z 三個軸的縮放比例是相同的,因此只需根據(jù)視圖空間的邊界值計算出寬度和高度的倒數(shù)(r_width 和 r_height),然后分別乘以一個恰當(dāng)?shù)南禂?shù)即可。

由于正交投影矩陣的特性是保持物體在觀察者視野中等比例地縮放,并且是平行投影,因此在計算 x、y、z 軸的縮放值時,并不需要考慮 near 或 far 參數(shù)對縮放的影響,這兩個參數(shù)主要用于定義裁剪空間的深度范圍,而非影響各個軸的縮放比例。

因此,在正交投影矩陣中,一般會根據(jù)邊界值計算出寬度和高度的倒數(shù),然后根據(jù)需要乘以適當(dāng)?shù)南禂?shù)來確定每個軸的縮放比例,而不涉及 near 或 far 對縮放值的影響。
第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣,OpenGL,矩陣,OpenGL,投影矩陣
由上圖推出對應(yīng)代碼生成4x4的矩陣

void EffectMatrix4::orthoM(float m[16], int mOffset,
                          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 tx = -(right + left) * r_width;
    float ty = -(top + bottom) * r_height;
    float tz = -(far + near) * r_depth;
    m[mOffset + 0] = x;
    m[mOffset + 5] = y;
    m[mOffset +10] = z;
    m[mOffset +12] = tx;
    m[mOffset +13] = ty;
    m[mOffset +14] = tz;
    m[mOffset +15] = 1.0f;
    m[mOffset + 1] = 0.0f;
    m[mOffset + 2] = 0.0f;
    m[mOffset + 3] = 0.0f;
    m[mOffset + 4] = 0.0f;
    m[mOffset + 6] = 0.0f;
    m[mOffset + 7] = 0.0f;
    m[mOffset + 8] = 0.0f;
    m[mOffset + 9] = 0.0f;
    m[mOffset + 11] = 0.0f;
}

正交投影矩陣用法

正交投影矩陣作用,為了適配2D畫面到渲染屏幕上等比縮放不變形

案例1:

播放視頻,畫面寬高,是如何視頻寬高匹配屏幕寬高?
分析:頂點坐標(biāo)四個點分別在[-1,1]之間,視頻播放正常要左右占滿,要么上下占滿,那個有一遍頂點要進行寬高比

用法 : vertexData頂點坐標(biāo), vertexSource頂點著色器, u_Matrix*av_Position,對頂點進行矩陣操作使用正交投影

  1. screenRatio = (float) screenWidth / screenHeight;:表示屏幕縱橫比(寬高比)的值。

  2. videoRatio = (float) videoWidth / videoHeight;: 表示視頻縱橫比(寬高比)的值。

  3. videoRatio > screenRatio: 這個條件的滿足意味著視頻的橫向跨度相對于其縱向跨度更大,或者說視頻是橫向拉伸的。橫向占滿屏幕也是就(left,right)為(-1f, 1f),反之一樣道理上下占滿。
    橫向占滿采用: Matrix.orthoM(matrix, 0, -1f, 1f, -videoRatio / screenRatio, videoRatio / screenRatio, -1f, 1f); 這行代碼是設(shè)置居于頂點坐標(biāo)[-1,1]之間一個正交投影矩陣,-1f, 1f, -videoRatio / screenRatio, videoRatio / screenRatio分別為 float left, float right, float bottom, float top左右為滿left=-1,right=1,上下縮放top=videoRatio / screenRatio,bottom= -videoRatio / screenRatio,重點理解 :居于頂點坐標(biāo)[-1,1]之間一個正交投影矩陣

    //頂點坐標(biāo)(原點為顯示區(qū)域中心店)
    private final float[] vertexData  = {
                -1.0f, -1.0f,  //左下角
                1.0f, -1.0f,   //右下角
                -1.0f,  1.0f,  //左上角
                1.0f,  1.0f,   //右上角
    };

    String vertexSource ="attribute vec4 av_Position;\n" +
            "attribute vec4 af_Position;//S T 紋理坐標(biāo)\n" +
            "varying vec2 v_texPosition;\n" +
            "uniform mat4 u_Matrix;\n" +
            "void main() {\n" +
            "    v_texPosition= af_Position.xy;\n" +
            "    gl_Position = u_Matrix*av_Position ;\n" +
            "}\n";


    public void updateProjection(int videoWidth, int videoHeight) {
        float screenRatio = (float) screenWidth / screenHeight;

        this.videoWidth = videoWidth;
        this.videoHeight = videoHeight;

        float videoRatio = (float) videoWidth / videoHeight;
        if (videoRatio > screenRatio) {
            Matrix.orthoM(matrix, 0, -1f, 1f, -videoRatio / screenRatio, videoRatio / screenRatio, -1f, 1f);
        } else {
            Matrix.orthoM(matrix, 0, -screenRatio / videoRatio, screenRatio / videoRatio, -1f, 1f, -1f, 1f);
        }

    }

案例2:

坐標(biāo)原點對應(yīng)屏幕左上角的貼紙怎么實現(xiàn)貼在屏幕上

頂點著色器

uniform mat4 uMVPMatrix;        // 變換矩陣
attribute vec4 aPosition;       // 圖像頂點坐標(biāo)
attribute vec2 aTextureCoord;   // 圖像紋理坐標(biāo)

varying vec2 textureCoordinate; // 圖像紋理坐標(biāo)

void main() {
    gl_Position = uMVPMatrix * aPosition;
    textureCoordinate = aTextureCoord.xy;
}

vertexData是按貼紙的實際像素 float[] value={0f,0f,500,500};//x,y,w,h為準(zhǔn), Matrix.orthoM(matrix, 0, 0, mFrameWidth, mFrameHeight,0 , -1, 1);和案例1原理一樣,按寬高mFrameWidth,mFrameHeight的模版,0, mFrameWidth, mFrameHeight,0分別為 float left, float right, float bottom, float top,left=0,right=mFrameWidth,bottom=mFrameHeight,top=0,對應(yīng)vertexData 的點位和正交投影矩陣相乘實現(xiàn),歸一化標(biāo)準(zhǔn)的OpenGL的[-1,1]的標(biāo)準(zhǔn)點位文章來源地址http://www.zghlxwxcb.cn/news/detail-837433.html

    //坐標(biāo)原點對應(yīng)屏幕左上角
    private final float[] vertexData = {
            0f, 0f,//左上角坐標(biāo)
            500f, 0f,//右上角坐標(biāo)
            0f, 500f, //左下角坐標(biāo)
            500f, 500f,//右下角坐標(biāo)
    };
        Matrix.orthoM(matrix, 0, 0, mFrameWidth, mFrameHeight,0 , -1, 1);

        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix,0);

        //傳遞頂點坐標(biāo)到shader
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false,
                8, vertexBuffer);

到了這里,關(guān)于第五章 OpenGL ES 基礎(chǔ)-透視投影矩陣與正交投影矩陣的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包