3D Computer Grapihcs Using OpenGL - 10 Color Buffer

來源:互聯網
上載者:User

標籤:rda   att   注意   margin   製作   dice   資料   signed   data   

本節我們將嘗試利用三角形製作一個“走馬燈”效果。

一個三角形示方式,從左向右依次移動。

先看一下代碼:

MyGlWindow.cpp

 1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 #include <iostream> 4 #include <fstream> 5  6 float triangleWidth = 0.1f; 7 float bytesPerTriangle = sizeof(GLfloat) * 18; 8 uint triangleIndex = 0; 9 uint maxTriangleCount = 20;10 11 void MyGlWindow::sendDataToOpenGL()12 {13     //GLfloat verts[] =14     //{15     //    -1.0f, -1.0f, +0.5f,//Vertex 016     //    +1.0f, +0.0f, +0.0f,//Color  017     //    +0.0f, +1.0f, -0.5f,//Vertex 118     //    +0.0f, +1.0f, +0.0f,//Color  119     //    +1.0f, -1.0f, +0.5f,//Vertex 220     //    +0.0f, +0.0f, +1.0f,//Color  221 22     //    -1.0f, +1.0f, +0.5f,//Vertex 323     //    +0.5f, +0.3f, +0.1f,//Color  324     //    +0.0f, -1.0f, -0.5f,//Vertex 425     //    +0.1f, +0.4f, +0.2f,//Color  426     //    +1.0f, +1.0f, +0.5f,//Vertex 527     //    +1.0f, +0.5f, +0.2f,//Color  528     //};29 30     GLuint vertexBufferID;31     glGenBuffers(1, &vertexBufferID);32     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);33     glBufferData(GL_ARRAY_BUFFER, maxTriangleCount * bytesPerTriangle, NULL, GL_STATIC_DRAW);34 35     //GLushort indices[] =36     //{37     //    0,1,2,38     //    3,4,5,39     //};40     //GLuint indexBufferID;41     //glGenBuffers(1, &indexBufferID);42     //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);43     //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);44 45     glEnableVertexAttribArray(0);46     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);47 48     glEnableVertexAttribArray(1);49     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (char*)(sizeof(GLfloat) * 3));50 }51 52 void MyGlWindow::installShaders()53 {54     //未修改,省略...55 }56 57 void MyGlWindow::initializeGL()58 {59     glewInit();60     glEnable(GL_DEPTH_TEST);61     sendDataToOpenGL();62     installShaders();63 }64 65 void MyGlWindow::paintGL()66 {67     glClear(GL_DEPTH_BUFFER_BIT);68     glViewport(0, 0, width(), height());69     //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);70     sendAnotherTriangle();71     glDrawArrays(GL_TRIANGLES, (triangleIndex-1)*3, triangleIndex * bytesPerTriangle);72 }73 74 void MyGlWindow::sendAnotherTriangle()75 {76     if (triangleIndex == maxTriangleCount)77         return;78     GLfloat xVal = -1 + triangleIndex * triangleWidth;79     GLfloat newTriangle[] = 80     {81         xVal, 1.0f, 0.0f,82         1.0f, 0.0f, 0.0f,83 84         xVal + triangleWidth, 1.0f, 0.0f,85         0.0f, 1.0f, 0.0f,86 87         xVal, 0.0f, 0.0f,88         0.0f, 0.0f, 1.0f,89     };90 91     glBufferSubData(GL_ARRAY_BUFFER, bytesPerTriangle * triangleIndex, bytesPerTriangle, newTriangle);92 93     triangleIndex++;94 }95 96 std::string MyGlWindow::ReadShaderCode(const char* fileName)97 {98     //未修改,省略...99 }

MyGlWindow.h

 1 #pragma once 2 #include <QtOpenGL\qgl.h> 3 #include <string> 4 class MyGlWindow :public QGLWidget 5 { 6 protected: 7     void sendDataToOpenGL(); 8     void installShaders(); 9     void initializeGL();10     void paintGL();11     std::string ReadShaderCode(const char* fileName);12     void sendAnotherTriangle();13 };

重點看cpp檔案裡的變化。

先定義了幾個變數(其實也可以定義成常量),方便後面使用,他們分別是:

  • float triangleWidth = 0.1f 表示三角形的寬度
  • float bytesPerTriangle = sizeof(GLfloat) * 18 表示每個三角形包含的頂點資訊資料位元組數,一個三角形使用了3個頂點,每個頂點有6個GLfloat類型資料
  • uint triangleIndex = 0 表示當前繪製的三角形的索引
  • uint maxTriangleCount = 20 “走馬燈”最多有多少個三角形

此前我們是在sendDataToOpenGL()函數中建立一個verts數組,把所有的資料一次性發送到OpenGL中進行繪製,本次我們需要動態改變繪製的內容,所以就不事先將資料一次性發送了。首先刪除掉sendDataToOpenGL函數中的verts數組。(13-28行)

另外也不需要所以數組了,也把索引數組相關的內容刪除掉。(35-43行以及69行)

33行也做了修改,首先我們要給VertexArrayBuffer分配足夠的空間,所以第二個參數改成了maxTriangleCount * bytesPerTriangle,提供20個三角形需要的空間。而我們在這個階段不需要提供任何資料(後面會講如何提供),所以第三個參數直接給個空值NULL。

在71行繪製Array之前,我們調用了一個新添加的函數sendAnotherTriangle(),這個函數的前半部分(78-89行)是準備資料,準備每次走馬燈要繪製的三角形的資料,由資料內容也能看出來,主要區別就是位置向右移動了。

重點是91行的函數

glBufferSubData(GL_ARRAY_BUFFER, bytesPerTriangle * triangleIndex, bytesPerTriangle, newTriangle);

glBufferSubData 這個OpenGL函數的作用是“部分填充” Array Buffer。可以對比觀察33行的glBufferData(一次性全部填充), 名字只是多了一個Sub,但是兩者的參數還是有些區別的。

  • 第一個參數和glBufferData是一樣的,表示設定哪個綁定點的資料。
  • 第二個參數是一個繪製的起始位置,因為我們右了一個三角形的索引triangleIndex,所以起始值就是它乘以每個三角形的位元組數。
  • 第三個參數表示每個元素的長度,正好使用我們一開始定義的每個三角形的位元組數 bytesPerTriangle
  • 第四個參數是資料本身

71行繪製Array Buffer, 注意第二個參數是每個三角形的起始點。

 

完成後編譯運行,發現畫面並沒有變化,主要原因是畫面沒有重繪,為了啟用重繪,最簡單的辦法就是讓視窗失去焦點和得到焦點,也就是可以在opengl視窗和其他任意視窗之間點擊切換。

但是看到的效果仍然不是我們期望的。效果如下:

這是什麼原因呢?

原因是OpenGL使用了雙重緩衝。一個Front Buffer, 一個Back Buffer。

繪製工作都是在Back Buffer上進行的,以免使用者看到繪製的過程,繪製好以後,會和Front Buffer進行一次交換。這就是為什麼我們看到了似乎有兩副不同的圖在反覆切換。

另外,我們明確指定了每次只繪製一個三角形,但是為什麼之前的三角形都儲存下來了?

原因是我們沒有進行一次“清理”。

找到MyGlWindow.cpp的67行,我們對它進行如下修改:

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

既然要清理Depth Buffer,我們順便使用一個"位或" 運算子把 Color Buffer也添加上。

這樣修改以後,就可以實現"走馬燈"效果了!(效果就不了,動圖太難弄了)

 

3D Computer Grapihcs Using OpenGL - 10 Color Buffer

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.