OpenGL系列之1 - 初識OpenGL

前言:

這是OpenGL的的簡單介紹。分爲三個部分:

  1. OpenGL的簡單認識
  2. 本地搭建OpenGL的環境
  3. OpenGL的部分術語

內容:

一. OpenGL的簡單認識

  1. OpenGL的Wikipedia 介紹地址: https://en.wikipedia.org/wiki/OpenGL#Development

Open Graphics Library (OpenGL is a cross-language, cross-platform application programming interface (API) for rendering 2D and 3D vector graphics. The API is typically used to interact with a graphics processing unit (GPU), to achieve hardware-accelerated rendering.

  1. 官方對於OpenGL ES的介紹地址:https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008793-CH1-SW1

OpenGL ES allows an app to harness the power of the underlying graphics processor. The GPU on iOS devices can perform sophisticated 2D and 3D drawing, as well as complex shading calculations on every pixel in the final image.

  1. OpenGL的案例展示:


  2. OpenGL在iOS開發中中的應用範圍:

    開放圖形庫(Open Graphics Library:OpenGL) 被用來展示2D和3D數據,它是一個多用途的開放標準圖形庫,支持2D、3D數字內容的創建,機械和建築設計、虛擬原型、飛行模擬、視頻遊戲等多種應用。您可以使用OpenGL配置3D圖形管線並提交數據。頂點被轉換和點亮,組成原始圖像,進行光柵化後生成2D圖像。OpenGL旨在將函數調用轉換爲可發送到底層圖形硬件的圖形命令,該底層硬件專門用於處理圖形命令,因此OpenGL繪圖通常非常快。
    OpenGL for Embedded Systems(OpenGL ES)是OpenGL的簡化版本(專門爲嵌入式系統設計,在移動端操作系統中應用廣泛),該版本消除了冗餘功能,提供了更易學習且易於在移動圖形硬件中實現的庫。

二.OpenGL在Mac上面的環境搭建:
1. 搭建過程:

圖片.png

圖片.png

圖片.png

圖片.png

圖片.png

圖片.png

圖片.png

圖片.png

  1. 代碼見傳送門

三. OpenGL基本的術語瞭解:

  1. 代碼類及函數介紹:
#include "GLShaderManager.h"
/*
  固定管線!
 `#include<GLShaderManager.h>` 移入了GLTool 着色器管理器(shader Mananger)類。
沒有着色器,我們就不能在OpenGL(核心框架)進行着色。
着色器管理器不僅允許我們創建並管理着色器,還提供一組“存儲着色器”,
他們能夠進行一些初步䄦基本的渲染操作。
 */
#include "GLTools.h"
/*
 `#include<GLTools.h>`  GLTool.h頭文件包含了大部分GLTool中類似C語言的獨立函數
*/
#include <GLUT/GLUT.h>
/*
 在Mac 系統下,`#include<glut/glut.h>`
 在Windows 和 Linux上,我們使用freeglut的靜態庫版本並且需要添加一個宏
*/
//定義一個,着色管理器
GLShaderManager shaderManager;
//簡單的批次容器,是GLTools的一個簡單的容器類。
GLBatch triangleBatch;
//blockSize 1/2邊長
GLfloat blockSize = 0.1f;
GLfloat vVerts[] = {
    -blockSize,-blockSize,0.0f,
    blockSize,-blockSize,0.0f,
    blockSize,blockSize,0.0f,
    -blockSize,blockSize,0.0f
};
//x軸上移動的距離
GLfloat xPos = 0.0f;
//y軸上移動的距離
GLfloat yPos = 0.0f;
/*
 在窗口大小改變時,接收新的寬度&高度。
 */
void changeSize(int w,int h)
{
    /*
      x,y 參數代表窗口中視圖的左下角座標,而寬度、高度是像素爲表示,通常x,y 都是爲0
     */
    glViewport(0, 0, w, h);
    
}

void RenderScene(void)
{
    
    //1.清除屏幕顏色
    glClear(GL_COLOR_BUFFER_BIT);
    
    //2.設置畫筆顏色 RGBA
    GLfloat vRed[] = {1.0f,0.0f,0.0f,1.0f};
    
    //利用矩陣幫助移動
    //mFinalTransform 結果矩陣
    //mTransformMatrix 平移矩陣
    //mRotationMatrix  旋轉矩陣
    M3DMatrix44f mFinalTransform,mTransformMatrix,mRotationMatrix;
    
    //平移 x,y,z,w(縮放因子= 1)
    //3D中平移的原理與矩陣之間關係
    /*
     參數1:矩陣
     參數2、3、4:X,Y,Z上平移距離
     */
    m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f);
    
    
    //增加難度! 一邊移動,一邊旋轉
    static float yRot = 0.0f;
    
    /*
     參數1:矩陣
     參數2:弧度
     參數3:X:1,0 1:圍繞X軸旋轉,0不圍繞X軸旋轉
     參數4:Y:1,0
     參數5:Z:1,0
     */
    m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
    
    //修改旋轉度數
    yRot += 5.0f;
    
    //思考:結合2個矩陣的結果 平移矩陣 * 旋轉矩陣 = 最終結果矩陣
    m3dMatrixMultiply44(mFinalTransform, mTransformMatrix, mRotationMatrix);
    
    
    //平面着色器
    /*
     1.平移矩陣 mTransformMatrix 與 每個頂點 相乘 -> 新頂點 (頂點着色器)
     2.將片元着色紅色 (片元着色器)
     */
    shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinalTransform,vRed);
    
    
    
    //單元着色器(類型,顏色)---第一種方法用到的
    //shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
    
    triangleBatch.Draw();
    
    //從後臺緩存區進行渲染
    glutSwapBuffers();
    
    
    
    
}

//移動圖形 -- 修改圖形座標!
void SpeacialKeys(int key,int x,int y)
{
    //步長
    GLfloat stepSize = 0.025f;
    
    //計算移動距離
    if (key == GLUT_KEY_UP) {
        yPos += stepSize;
    }
    
    if (key == GLUT_KEY_DOWN) {
        yPos -= stepSize;
    }
    
    if (key == GLUT_KEY_LEFT) {
        xPos -= stepSize;
    }
    
    if (key == GLUT_KEY_RIGHT) {
        xPos += stepSize;
    }
    
    //邊界檢查
    if (xPos < -1.0f + blockSize) {
        xPos = -1.0f + blockSize;
    }
    
    if (xPos > 1.0f - blockSize) {
        xPos = 1.0f - blockSize;
    }
    
    if (yPos < -1.0f + blockSize) {
        yPos = -1.0f + blockSize;
    }
    
    if (yPos > 1.0f  - blockSize) {
        yPos = 1.0f - blockSize;
    }
    
     glutPostRedisplay();
    
   //第一種方法:通過修改座標移動物體
   /*
    //步長
    GLfloat stepSize = 0.025f;
    //相對點 D點
    GLfloat blockX = vVerts[0];
    GLfloat blockY = vVerts[10];
    //上
    if (key == GLUT_KEY_UP) {
        blockY += stepSize;
    }
    if (key == GLUT_KEY_DOWN) {
        blockY -= stepSize;
    }
    if (key == GLUT_KEY_LEFT) {
        blockX -= stepSize;
    }
    if (key == GLUT_KEY_RIGHT) {
       
        blockX += stepSize;
    }
    
    //左邊
    if (blockX < -1.0f) {
        blockX = -1.0f;
    }
    //右邊
    if (blockX > 1.0 - blockSize * 2) {
        blockX = 1.0 - blockSize * 2;
    }
    if (blockY > 1.0f) {
        blockY = 1.0f;
    }
    if (blockY < -1.0f + blockSize * 2) {
        blockY = -1.0f + blockSize * 2;
    }
    
    //計算參考點移動,藉助參考D 幫助實現4個頂點的修改。
    //A:
    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize * 2;
    //B
    vVerts[3] = blockX + blockSize * 2;
    vVerts[4] = blockY - blockSize * 2;
    //C
    vVerts[6] = blockX + blockSize * 2;
    vVerts[7] = blockY;
    //D
    vVerts[9] = blockX;
    vVerts[10] = blockY;
    triangleBatch.CopyVertexData3f(vVerts);
    glutPostRedisplay();
    */
    
}

void setupRC()
{
    //1.設置清屏顏色
    glClearColor(0.33, 0.45, 0.12, 1.0f);
    //初始化固定管線
    shaderManager.InitializeStockShaders();
    /*
    //指定三角形的頂點數據 x,y,z
    GLfloat vVerts[] = {
        -0.5f,0.0f,0.0f,
        0.5f,0.0f,0.0f,
        0.0f,0.5f,0.0f
    };
    */
    triangleBatch.Begin(GL_TRIANGLE_FAN , 4);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}

int main(int argc,char *argv[])
{
    //設置當前工作目錄,針對MAC OS X
    /*
     `GLTools`函數`glSetWorkingDrectory`用來設置當前工作目錄。實際上在Windows中是不必要的,因爲工作目錄默認就是與程序可執行執行程序相同的目錄。但是在Mac OS X中,這個程序將當前工作文件夾改爲應用程序捆綁包中的`/Resource`文件夾。`GLUT`的優先設定自動進行了這個中設置,但是這樣中方法更加安全。
     */
    gltSetWorkingDirectory(argv[0]);
    //初始化GLUT庫,這個函數只是傳說命令參數並且初始化glut庫
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    //GLUT窗口大小、窗口標題
    glutInitWindowSize(800, 600);
    glutCreateWindow("Triangle");
    /*
     GLUT 內部運行一個本地消息循環,攔截適當的消息。然後調用我們不同時間註冊的回調函數。我們一共註冊2個回調函數:
     1)爲窗口改變大小而設置的一個回調函數
     2)包含OpenGL 渲染的回調函數
     */
    //註冊重塑函數
    glutReshapeFunc(changeSize);
    //註冊顯示函數
    glutDisplayFunc(RenderScene);
    glutSpecialFunc(SpeacialKeys);
    /*
     初始化一個GLEW庫,確保OpenGL API對程序完全可用。
     在試圖做任何渲染之前,要檢查確定驅動程序的初始化過程中沒有任何問題
     */
    GLenum status = glewInit();
    if (GLEW_OK != status) {
        printf("GLEW Error:%s\n",glewGetErrorString(status));
        return 1;
    }
    //設置我們的渲染環境
    setupRC();
    glutMainLoop();
    return  0;
    
}

  1. 陌生的術語介紹:
  • 着色器

着色器(shader),專爲圖形處理單元(GPU)編譯的一種小型程序。

  • 圖元

圖元是能夠被OpenGL ES 繪製的幾何物體,如三角形、線條或者精靈。

  • 光柵化

將輸入圖元的數學描述轉換爲與屏幕位置對應的像素片元,稱爲光柵化。

  • 紋理

最通常的作用是裝飾我們的物體模型,它就像是貼紙一樣貼在物體表面,使得物體表面擁有圖案。但實際上在OpenGL中,紋理的作用不僅限於此,它可以用來存儲大量的數據,一個典型的例子就是利用紋理存儲地形信息。

  • 渲染

渲染(render),表示計算機從模型創建最終圖像的過程。

  • 幀緩存

幀緩存(framebuffer),像素(pixel),是顯示器上最小的可見單元。計算機系統將所有的像素保存到幀緩存當中,後者是有圖形硬件設備管理的一塊獨立內存區域,可以直接映射到最終的顯示設備上。

參考及拓展:

  1. https://www.jianshu.com/p/62fc87833ed5
    iOS開發-OpenGL ES魔方應用(簡友博客)
  2. https://www.jianshu.com/p/c5ad4a3ed1a9
    初識OpenGL,環境搭建 (簡友博客)
  3. https://www.jianshu.com/p/736401c03990
    第1章 OpenGL概述(簡友博客)

代碼傳送門:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章