1. 程式人生 > >GLSL矩陣變換詳解(三、view matrix和projection matrix)

GLSL矩陣變換詳解(三、view matrix和projection matrix)

我們在前一篇部落格

GLSL矩陣變換詳解(二、旋轉變換、平移變換以及QMatrix4x4)

的基礎上再增加對攝像機位置、姿態的設定功能,以及成像區域的定義功能。

QMatrix4x4::lookAt(camera, center, upDirection)定義了攝像機的位置與姿態,屬於view matrix操作的範疇。三個輸入變數都是QVector3D型別。camera是攝像機在世界座標系的座標。center是攝像機的光軸上的任一點,也是世界座標系座標,它與camera連線決定了光軸的方向。這樣獲取影像後,還需要確定照片正上方的指向。upDirection決定了這一方向。這一方向同樣在世界座標系中表述。顯然,這一方向不能與攝像機光軸平行。


QMatrix4x4::ortho(left, right, bottom, top, near, far)定義了一塊長方體(視景體),屬於projection 操作的範疇。長方體的正面與camera的光軸垂直。near表示長方體正面與camera的距離,far表示長方體背面與camera的距離。其他量的意義見下圖。

其中l表示left,r表示right,t表示top,b表示bottom


根據https://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations,view matrix操作在model matrix之後,而projection放在view之後。因此,在下面的例項中,我把ortho放在最前面,其次是lookAt,最後才是translate和rotate

h檔案:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>

class MainWindow : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    GLuint                          m_uiVertLoc;
    GLuint                          m_uiTexNum;
    QOpenGLTexture          *       m_pTextures;
    QOpenGLShaderProgram    *       m_pProgram;
    GLfloat                 *       m_pVertices;

protected:
    void        initializeGL();
    void        paintGL();
    void        resizeGL(int w, int h);
};

#endif // MAINWINDOW_H

cpp檔案:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QOpenGLWidget(parent)
{
}

MainWindow::~MainWindow()
{
    m_pTextures->release();
    delete m_pTextures;
    delete m_pProgram;
    delete [] m_pVertices;

}

void MainWindow::initializeGL()
{
    initializeOpenGLFunctions();

    m_uiTexNum = 0;
    m_pVertices = new GLfloat[18];
    //給頂點賦值
    GLfloat arrVertices[18] = {0.0, 1.0, 0.0,
                               0.0, 0.0, 0.0,
                               1.0, 0.0, 0.0,
                               1.0, 0.0, 0.0,
                               1.0, 1.0, 0.0,
                               0.0, 1.0, 0.0};
    m_pVertices = new GLfloat[18];
    memcpy(m_pVertices, arrVertices, 18 * sizeof(GLfloat));

    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    const char *vsrc =
                        "#version 330\n"
                        "in vec3 pos;\n"
                        "out vec2 texCoord;\n"
                        "uniform mat4 mat4MVP;\n"
                        "void main()\n"
                        "{\n"
                        "    gl_Position = mat4MVP * vec4(pos, 1.0);\n"
                        "    texCoord = pos.xy;\n"
                        "}\n";
    vshader->compileSourceCode(vsrc);

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    const char *fsrc =
                        "#version 330\n"
                        "out vec4 color;\n"
                        "in vec2 texCoord;\n"
                        "uniform sampler2D Tex\n;"
                        "void main()\n"
                        "{\n"
                        "    color = texture(Tex, texCoord);\n"
                        //"      color = vec4(1.0, 0.0, 0.0, 0.0);\n"
                        "}\n";
    fshader->compileSourceCode(fsrc);

    m_pProgram = new QOpenGLShaderProgram;
    m_pProgram->addShader(vshader);
    m_pProgram->addShader(fshader);
    m_pProgram->link();
    m_pProgram->bind();

    m_uiVertLoc = m_pProgram->attributeLocation("pos");
    m_pProgram->enableAttributeArray(m_uiVertLoc);
    m_pProgram->setAttributeArray(m_uiVertLoc, m_pVertices, 3, 0);


    m_pTextures = new QOpenGLTexture(QImage(QString("earth.bmp")).mirrored());
    m_pTextures->setMinificationFilter(QOpenGLTexture::Nearest);
    m_pTextures->setMagnificationFilter(QOpenGLTexture::Linear);
    m_pTextures->setWrapMode(QOpenGLTexture::Repeat);
    m_pProgram->setUniformValue("Tex", m_uiTexNum);


    glEnable(GL_DEPTH_TEST);
    glClearColor(0,0,0,1);
}

void MainWindow::paintGL()
{
    //QMatrix4x4在宣告時被預設為單位矩陣
    QMatrix4x4 m1, m2, m3, m;

    //m1.viewport(0,0,m_iWidth, m_iHeight,-15,15);//useless
    m1.ortho(-1.0f, +1.0f, -1.0f, 1.0f, 0.0f, 15.0f);//right//generate projection matrix
    m2.lookAt(QVector3D(10,0,10), QVector3D(0,0,0), QVector3D(0,1,0));//generate view matrix, right
    qDebug()<<m2;
    m3.translate(0,-0.707,0.0);//right, generate model matrices
    m3.rotate(45, 0.0f, 0.0f, 1.0f);//right, generate model matrices

    m = m1 * m2 * m3;

    m_pProgram->setUniformValue("mat4MVP", m);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    m_pTextures->bind(m_uiTexNum);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    m_pTextures->release();
}

void MainWindow::resizeGL(int w, int h)
{
    glViewport(0,0,w,h);
}

效果:


分析:


上圖展現的是攝像機和紋理圖在世界座標系的位置。從攝像機到紋理中心的距離為14.14。而ortho(-1,1,-1,1,0,15)函式決定了從攝像機沿光軸方向走出15個單位內的物體都被成像,所以紋理可以看到。

再將攝像機移動到更遠的位置(20,0,10),此時由於攝像機視角明顯傾斜,影象在X方向與Y方向比例差距就明顯了。


現在取一個極限值:22.36 = sqrt(20 * 20 + 10 * 10),這是攝像機到紋理中心的距離。將這個值作為視景體背面到攝像機的距離,則紋理有一半顯示不出來了--突出視景體的那一半。


相關推薦

GLSL矩陣變換view matrixprojection matrix

我們在前一篇部落格GLSL矩陣變換詳解(二、旋轉變換、平移變換以及QMatrix4x4)的基礎上再增加對攝像機位置、姿態的設定功能,以及成像區域的定義功能。QMatrix4x4::lookAt(camera, center, upDirection)定義了攝像機的位置與姿態,

JavaScript的事件DOM模型事件流模型以及內置對象

dde function n) 事件冒泡 字符 nds rep == 防止 JS中的事件 JS中的事件分類   1.鼠標事件:     click/dbclick/mouseover/mouseout   2.HTML事件:     onload/onunload

史上最全python面試題附帶詳細答案關注持續更新

38、面向物件深度優先和廣度優先是什麼?     39、面向物件中super的作用? 40、是否使用過functools中的函式?其作用是什麼? 1 Python自帶的 functools 模組提供了一些常用的高階函式,也就是用於處理其它函式的特殊函式。

Android6.0 MountServicevold vold SD卡otg

既上面兩篇部落格,繼續分析vold、對外接SD卡和OTG的分析: 一、process_config函式 上一篇我們再main函式中分析了VolumeManager的start函式,這次我們接下來分析process_config函式 static int process_c

Java 多線程------線程的同步

alt 來看 監聽 介紹 創建進程 java 多線程 system ima 關鍵字 Java 多線程詳解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多線程詳解(二)------如何創建進

elastic-job:Job的手動觸發功能

方法 idt image blog per tle cnblogs ack display elastic-job的任務都是使用quartz來觸發的,quartz表達式一般都是定期執行。但有時候一些周期較長的任務,比如一天一次,幾小時一次的任務,我們需要等待很久才能觸發一次

10.5-全棧Java筆記:常見流

java上節我們講到「Java中常用流:緩沖流」,本節我們學習數據流和對象流~ 數據流數據流將“基本數據類型變量”作為數據源,從而允許程序以與機器無關方式從底層輸入輸出流中操作java基本數據類型。 DataInputStream和DataOutputStream提供了可以存取與機器無關的所有Java基礎類

SpringMVC------基於註解的入門實例

frame hello text 1.0 har ret doc 4.0 進行   前兩篇博客我們講解了基於XML 的入門實例,以及SpringMVC運行的詳細流程。但是我們發現基於 XML 的配置還是比較麻煩的,而且,每個 Handler 類只能有一個方法,在實際開發中肯

Maven------ Maven工程目錄介紹

詳細講解 com tid pom.xml imp 工程目錄 在哪裏 根據 cat   上一章我們配置並安裝好了 Maven,那麽這一章我們介紹如何用eclipse創建一個 Maven 工程,然後介紹 Maven 工程的目錄結構。 1、eclipse 創建 Maven 工程

轉-Linux啟動過程inittabrc.sysinitrcX.drc.local

dha mage 模塊 都是 交換 如何配置 mas 完全 打開 http://blog.chinaunix.net/space.php?uid=10167808&do=blog&id=26042 1)BIOS自檢2)啟動Grub/Lilo3)加載內

C++: I/O流——串流

name namespace 轉換 pac end 成員 col logs nbsp 一、串流 串流類是 ios 中的派生類 C++的串流對象可以連接string對象或字符串 串流提取數據時對字符串按變量類型解釋;插入數據時把類型 數據轉換成字符串 串流I/O具有格式化功能

Zookeeper:Zookeeper中的Znode特性

zookeeper數據模型 znode 節點數據 數據模型ZK擁有一個命名空間就像一個精簡的文件系統,不同的是它的命名空間中的每個節點擁有它自己或者它下面子節點相關聯的數據。ZK中必須使用絕對路徑也就是使用“/”開頭。Znode:ZK目錄樹中每個節點對應一個Znode。每個Znode維護這一個屬性

Splay

.html rotate cqoi2014 org tps 線段樹 .cn html highlight 前言 上一節我們學習了splay所能解決的基本問題,這節我來講一下splay怎麽搞區間問題 實現 splay搞區間問題非常簡單,比如我們要在區間$l,r$上搞事情

編碼原理---量化

進一步 mark 新的 dct 說明 一點 註意 cto water 本節開始介紹編碼過程中的量化環節。還記得上一篇的變換嗎?變換之後得到了一個新的矩陣,一個經過從空域變換到頻域的一個矩陣。那麽,量化呢,就是基於變換後得到的矩陣,再做進一步的處理,本質也就是進一步的壓縮。

大數據入門第八天——MapReduce

大數 blog eve 分享圖片 shuf open src hid span 1/mr的combiner 2/mr的排序 3/mr的shuffle 4/mr與yarn 5/mr運行模式 6/mr實現join 7/mr全局圖

常見圖片格式---JPEG

JPEG 圖片格式 編碼 解碼 壓縮 JPEG簡介 JPEG是一種比較成熟的有損的圖像壓縮格式,經過JPEG壓縮,圖像質量會有所損失,但是,人眼不容易分辨出來這種差別。jpeg圖像在質量和存儲空間得到了一個相對平衡的狀態。不過jpeg文件在組織方式上略顯復雜,詳細請向下看。 JPEG文

Redis

redis codis twemproxy redis集群 redis-trib.rb 一、Redis集群介紹 Clustering:redis 3.0之後進入生產環境分布式數據庫,通過分片機制來進行數據分布,clustering 內的每個節點,僅有數據庫的一部分數據;去中心化的集群:re

CentOS 7.4 Tengine安裝配置

location、echo、fancy九、根據HTTP響應狀態碼自定義錯誤頁:1、未配置前訪問一個不存在的頁面:http://192.168.1.222/abc/def.html,按F12後刷新頁面2、在server{}配置段中新增如下location:server {listen 80;server_nam

Keepalived

集群 scrip 網絡異常 可用 size ont 監控 spa 就是 Keepalived基礎功能應用實例: 1.Keepalived基礎HA功能演示: 在默認情況下,Keepalived可以實現對系統死機、網絡異常及Keepalived本身進

HAProxy

客戶端 apr centos watermark ges -o text acl 方式 一.基於虛擬主機的HAProxy負載均衡系統配置實例 1.通過HAProxy的ACL規則配置虛擬主機: 下面將通過HAProxy的ACL功能配置一套基於虛擬主