學習書籍: OpenGL 超級寶典(中文第五版) 密碼:fu4w
書籍源碼:OpenGL 超級寶典第五版源代碼 密碼:oyb4
環(huán)境搭建:OpenGL 學習 01 - Mac 搭建 OpenGL 環(huán)境
基本概念
多邊形偏移
上一節(jié)在 OpenGL 學習 05 - 花托 中,我們通過深度測試實現(xiàn)真實視覺并提高性能牲证,但會遇到一些麻煩胶滋,比如我們想將2個幾何圖形繪制在同一個位置量瓜,我們想要畫一架大飛機,然后在飛機上繪制一個五角星圖案妇汗,這叫做“貼花”孩革。這 2 個圖形的深度值 z 相同或者幾乎相同,這種情況稱為 深度值沖突 惶翻。
處理深度值沖突的方法:
- 手動調整 z 值進行一點點偏移姑蓝,但可能會出現(xiàn)圖形懸浮(不推薦)
- 利用 多邊形偏移 調節(jié)片段的深度值,但實際不改變 3D 空間物理位置(推薦)
應用到片段上的總偏移方程式如下吕粗,其中 DZ 是深度值相對多邊形屏幕區(qū)域的變化量纺荧,r 是使深度緩沖區(qū)值產生變化的最小值,這2個值都是 OpenGL 內部的值颅筋,我們不用關心宙暇,我們是通過控制 factor 和 units 達到效果:
// 設置多邊形偏移
void glPolygonOffset(GLfloat factor, GLfloat units);
裁剪
除了深度測試,還有一種提高渲染性能的方法议泵,那就是 只刷新屏幕上發(fā)生變化的部分占贫,即裁剪。OpenGL 允許我們在將要進行渲染的窗口中指定一個裁剪框先口,只刷新裁剪框里面的變化型奥。默認裁剪框和窗口大小一致,并不會進行裁剪測試碉京。
//設置裁剪框位置和大小
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
混合
通常情況下厢汹,OpenGL 渲染時會把顏色值放在顏色緩存區(qū)中,任何繪制操作都是完全覆蓋原來的顏色值谐宙,比如我們在一個紅色圖形前面畫一個藍色圖形烫葬,在重疊的部分,藍色覆蓋紅色卧惜。但如果我們想在重疊區(qū)顯示重疊顏色(比如紅藍混合色)怎么辦厘灼?這時就需要使用到 OpenGL 的混合功能。
目標顏色:已經(jīng)存儲在顏色緩沖區(qū)中的顏色
源顏色:將要加入進行混合的顏色
混合方程式:目標顏色和源顏色的組合方式咽瓷,用來生成混合后的顏色
其中 Cf 是最終產生顏色设凹,Cs 為源顏色,Cd 為目標顏色茅姜,S 和 D 分別為源顏色和目標顏色的混合因子
// 我們通過控制 S 和 D 混合因子控制混合方程式輸出闪朱,S 和 D 都是枚舉值
void glBlendFunc(CLenum S, GLenum D);
看到上面的混合因子表月匣,一開始是懵逼的,我們來簡單計算一下奋姿,到底表示的意義是什么锄开,下面是其中一種情況的計算過程,其他類推:
/*
Rs/Gs/Bs/As - 源顏色 RGBA 各個通道的混合因子
Rd/Gd/Bd/Ad - 目標顏色 RGBA 各個通道的混合因子
Rc/Gc/Bc/Ac - 常量顏色 RGBA 各個通道的混合因子
Cs = 源顏色 = { 0.0f, 0.0f, 1.0f, 0.6f }
Cd = 目標顏色 = { 1.0f, 0.0f, 0.0f, 1.0f }
As = 源顏色 alpha 值 = 0.6f
Ad = 目標顏色 alpha 值 = 1.0f
S = 源顏色混合因子 = GL_SRC_ALPHA = As = 0.6f
D = 目標顏色混合因子 = GL_ONE_MINUS_SRC_COLOR = 1.0f - As = 0.4f
Cf = 最終產生顏色 = Cs * 0.6f + Cd * 0.4f = {
0.0f * 0.6f + 1.0f * 0.4f,
0.0f * 0.6f + 0.0f * 0.4f,
1.0f * 0.6f + 0.0f * 0.4f,
0.6f * 0.6f + 1.0f * 0.4f
} = { 0.4f, 0.6f, 0.0f, 0.76f }
*/
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
但是這會帶來一個問題称诗,當我們進行了顏色混合后萍悴,最終目標顏色分量 Alpha 通道同時也被改變了——原來 Alpha 是 0.6,混合后變成了 0.76寓免。這時我們就需要另外一個函數(shù) glBlendFuncSeparate
:
//允許分別為 RGB 通道和 Alpha 通道設置混合因子(OpenGL 2.0 開始支持)
void glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
除了上面默認的混合方程式癣诱,也有其他混合方程式:
//改變混合方程式等式結構
void glBlendEquation(GLenum mode);
//修改常量顏色,即上面表中的 Rc袜香、Gc撕予、Bc、Ac
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
抗鋸齒
OpenGL 混合的另外一種用途就是抗鋸齒蜈首。圖形邊緣會出現(xiàn)一些吸引眼睛的注意力而讓人感覺圖形不自然的像素點实抡,稱為鋸齒。我們需要盡可能的逼真欢策,尤其在游戲吆寨、模擬和藝術創(chuàng)造中。為了消除圖元之間的鋸齒猬腰,OpenGL 利用混合功能鸟废,把像素的目標顏色和周圍像素的顏色進行混合猜敢。
抗鋸齒功能開啟條件:
- 開啟混合功能
- 設置混合方程式為
GL_ADD
- 設置混合方程式因子為
S = GL_SRC_ALPHA
,D = GL_ONE_MINUS_SRC_ALPHA
- 開啟抗鋸齒功能(點/線/多邊形)
源碼解析
多邊形偏移
核心代碼:
//設置多邊形偏移的總偏移
glPolygonOffset(-1.0f, -1.0f);
//開啟多邊形偏移
glEnable(GL_POLYGON_OFFSET_POINT); // 點
glEnable(GL_POLYGON_OFFSET_LINE); // 線
glEnable(GL_POLYGON_OFFSET_UNITS); // 圖形
//關閉多邊形偏移
glDisable(GL_POLYGON_OFFSET_POINT); // 點
glDisable(GL_POLYGON_OFFSET_LINE); // 線
glDisable(GL_POLYGON_OFFSET_UNITS); // 圖形
Demo 源碼: 之前文章的 03-Primitives Demo 中的三角形帶中有運用到姑荷,這里就不重復拷貝了。
裁剪
核心代碼:
//開啟裁剪
glEnable(GL_SCISSOR_TEST);
//設置顏色緩沖區(qū)背景為紅色
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
//裁剪出(x: 100, y: 100, w: 600, h: 400)區(qū)域
glScissor(100, 100, 600, 400);
//清空顏色緩存區(qū)缩擂,同步到后臺緩沖區(qū)鼠冕,注意這里會設置的是裁剪區(qū)域
glClear(GL_COLOR_BUFFER_BIT);
//關閉裁剪
glDisable(GL_SCISSOR_TEST);
Demo 源碼: 05-Scissor
#include <GLTools.h> // OpenGL toolkit
#include <glut/glut.h>
//渲染畫面
void RenderScene(void) {
//設置顏色緩沖區(qū)背景色為藍色
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
//清空顏色緩存區(qū),設置到后臺緩存區(qū)胯盯,執(zhí)行完這步才繪制了背景顏色
glClear(GL_COLOR_BUFFER_BIT);
//開啟裁剪
glEnable(GL_SCISSOR_TEST);
//設置顏色緩沖區(qū)背景色為紅色
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
//裁剪出(x: 100, y: 100, w: 600, h: 400)區(qū)域
glScissor(100, 100, 600, 400);
//清空顏色緩存區(qū)懈费,設置到后臺緩沖區(qū),注意這里會設置的是裁剪區(qū)域
glClear(GL_COLOR_BUFFER_BIT);
//設置顏色緩沖區(qū)背景色為綠色
glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
//裁剪出(x: 200, y: 200, w: 400, h: 200)區(qū)域
glScissor(200, 200, 400, 200);
//清空顏色緩存區(qū)博脑,設置到后臺緩沖區(qū)憎乙,注意這里會設置的是裁剪區(qū)域
glClear(GL_COLOR_BUFFER_BIT);
//關閉裁剪
glDisable(GL_SCISSOR_TEST);
//將在后臺緩沖區(qū)進行渲染,然后在結束時交換到前臺
glutSwapBuffers();
}
//窗口大小改變時接受新的寬度和高度
void ChangeSize(int w, int h) {
//設置視圖窗口位置
glViewport(0, 0, w, h);
}
//程序入口
int main(int argc, char* argv[]) {
//設置當前工作目錄叉趣,針對MAC OS X
gltSetWorkingDirectory(argv[0]);
//初始化GLUT庫
glutInit(&argc, argv);
/*初始化渲染模式泞边,其中標志GLUT_DOUBLE、GLUT_RGBA疗杉、GLUT_DEPTH阵谚、GLUT_STENCIL分別指
雙緩沖窗口、RGBA顏色模式、深度測試梢什、模板緩沖區(qū)*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
//初始化窗口大小
glutInitWindowSize(800, 600);
//創(chuàng)建窗口
glutCreateWindow("OpenGL Scissor");
//注冊回調函數(shù)
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
//確保驅動程序的初始化中沒有出現(xiàn)任何問題奠蹬。
GLenum err = glewInit();
if(GLEW_OK != err) {
fprintf(stderr, "glew error:%s\n", glewGetErrorString(err));
return 1;
}
//進入調用循環(huán)
glutMainLoop();
return 0;
}
混合
核心源碼:
//開啟顏色混合
glEnable(GL_BLEND);
//配置混合方程式,默認為 GL_FUNC_ADD 方程
glBlendEquation(GL_FUNC_ADD);
//配置混合方程式混合因子
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//分別設置 RGB 通道和 Alpha 通道混合因子
glBlendFuncSeparate(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//改變常量顏色
glBlendColor(1.0f, 0.0f, 0.0f, 1.0f);
//關閉顏色混合
glDisable(GL_BLEND);
Demo 源碼: 06-Blending
#include <GLTools.h> // OpenGL toolkit
#include <GLShaderManager.h>
#include <glut/glut.h>
GLBatch squareBatch;
GLBatch greenBatch;
GLBatch redBatch;
GLBatch blueBatch;
GLBatch blackBatch;
GLShaderManager shaderManager;
GLfloat blockSize = 0.2f;
GLfloat vVerts[] = {
-blockSize, -blockSize, 0.0f,
blockSize, -blockSize, 0.0f,
blockSize, blockSize, 0.0f,
-blockSize, blockSize, 0.0f
};
//程序一次性初始化
void SetupRC() {
//設置窗口背景為黑色
glClearColor(1.0f, 1.0f, 1.0f, 1.0f );
//初始化著色器管理者
shaderManager.InitializeStockShaders();
//創(chuàng)建移動矩形批次
squareBatch.Begin(GL_TRIANGLE_FAN, 4);
squareBatch.CopyVertexData3f(vVerts);
squareBatch.End();
//綠色矩形批次
GLfloat vBlock[] = {
0.25f, 0.25f, 0.0f,
0.75f, 0.25f, 0.0f,
0.75f, 0.75f, 0.0f,
0.25f, 0.75f, 0.0f
};
greenBatch.Begin(GL_TRIANGLE_FAN, 4);
greenBatch.CopyVertexData3f(vBlock);
greenBatch.End();
//紅色矩形批次
GLfloat vBlock2[] = {
-0.75f, 0.25f, 0.0f,
-0.25f, 0.25f, 0.0f,
-0.25f, 0.75f, 0.0f,
-0.75f, 0.75f, 0.0f
};
redBatch.Begin(GL_TRIANGLE_FAN, 4);
redBatch.CopyVertexData3f(vBlock2);
redBatch.End();
//藍色矩形批次
GLfloat vBlock3[] = {
-0.75f, -0.75f, 0.0f,
-0.25f, -0.75f, 0.0f,
-0.25f, -0.25f, 0.0f,
-0.75f, -0.25f, 0.0f
};
blueBatch.Begin(GL_TRIANGLE_FAN, 4);
blueBatch.CopyVertexData3f(vBlock3);
blueBatch.End();
//黑色矩形批次
GLfloat vBlock4[] = {
0.25f, -0.75f, 0.0f,
0.75f, -0.75f, 0.0f,
0.75f, -0.25f, 0.0f,
0.25f, -0.25f, 0.0f
};
blackBatch.Begin(GL_TRIANGLE_FAN, 4);
blackBatch.CopyVertexData3f(vBlock4);
blackBatch.End();
}
//特殊按鈕監(jiān)聽
void SpecialKeys(int key, int x, int y) {
GLfloat stepSize = 0.025f;
//左上角的 X 坐標和右下角的 Y 坐標
GLfloat blockX = vVerts[0];
GLfloat blockY = vVerts[7];
//根據(jù)移動方向移動位置
switch (key) {
case GLUT_KEY_UP: blockY += stepSize; break;
case GLUT_KEY_DOWN: blockY -= stepSize; break;
case GLUT_KEY_LEFT: blockX -= stepSize; break;
case GLUT_KEY_RIGHT: blockX += stepSize; break;
default: break;
}
//移動邊界處理
if(blockX < -1.0f) blockX = -1.0f;
if(blockX > (1.0f - blockSize * 2)) blockX = 1.0f - blockSize * 2;;
if(blockY < -1.0f + blockSize * 2) blockY = -1.0f + blockSize * 2;
if(blockY > 1.0f) blockY = 1.0f;
//矩形四個頂點位置
vVerts[0] = blockX;
vVerts[1] = blockY - blockSize*2;
vVerts[3] = blockX + blockSize*2;
vVerts[4] = blockY - blockSize*2;
vVerts[6] = blockX + blockSize*2;
vVerts[7] = blockY;
vVerts[9] = blockX;
vVerts[10] = blockY;
//批次頂點數(shù)據(jù)編號
squareBatch.CopyVertexData3f(vVerts);
//觸發(fā)渲染
glutPostRedisplay();
}
//渲染畫面
void RenderScene(void) {
//清理各個緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//定義4種顏色
GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
GLfloat vBlue[] = { 0.0f, 0.0f, 1.0f, 0.6f };
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
//畫綠色矩形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);
greenBatch.Draw();
//畫紅色矩形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
redBatch.Draw();
//畫藍色矩形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlue);
blueBatch.Draw();
//畫黑色矩形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlack);
blackBatch.Draw();
//開啟顏色混合
glEnable(GL_BLEND);
//配置混合方程式
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//畫移動矩形嗡午,本身半透明藍色
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlue);
squareBatch.Draw();
//關閉顏色混合
glDisable(GL_BLEND);
//將在后臺緩沖區(qū)進行渲染囤躁,然后在結束時交換到前臺
glutSwapBuffers();
}
//窗口大小改變時接受新的寬度和高度
void ChangeSize(int w, int h) {
//設置視圖窗口位置
glViewport(0, 0, w, h);
}
//程序入口
int main(int argc, char* argv[]) {
//設置當前工作目錄,針對MAC OS X
gltSetWorkingDirectory(argv[0]);
//初始化GLUT庫
glutInit(&argc, argv);
/*初始化渲染模式荔睹,其中標志GLUT_DOUBLE割以、GLUT_RGBA、GLUT_DEPTH应媚、GLUT_STENCIL分別指
雙緩沖窗口严沥、RGBA顏色模式、深度測試中姜、模板緩沖區(qū)*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
//初始化窗口大小
glutInitWindowSize(800, 600);
//創(chuàng)建窗口
glutCreateWindow("Move Block with Arrow Keys to see blending");
//注冊回調函數(shù)
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
//確保驅動程序的初始化中沒有出現(xiàn)任何問題消玄。
GLenum err = glewInit();
if(GLEW_OK != err) {
fprintf(stderr, "glew error:%s\n", glewGetErrorString(err));
return 1;
}
//初始化設置
SetupRC();
//進入調用循環(huán)
glutMainLoop();
return 0;
}
抗鋸齒
核心代碼:
//開啟抗鋸齒處理,必須先開啟顏色混合模式
glBlendEquation(GL_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//抗鋸齒開啟
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
//設置抗鋸齒處理達到效果最好(另外一個是效果最快)
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
//關閉抗鋸齒處理
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
Demo 源碼: 07-Smoother
#include <GLTools.h> // OpenGL toolkit
#include <GLFrustum.h>
#include <glut/glut.h>
GLShaderManager shaderManager;
GLFrustum viewFrustum;
GLBatch smallStarBatch;
GLBatch mediumStarBatch;
GLBatch largeStarBatch;
GLBatch mountainRangeBatch;
GLBatch moonBatch;
//常量宏
#define SMALL_STARS 100
#define MEDIUM_STARS 40
#define LARGE_STARS 15
#define SCREEN_X 800
#define SCREEN_Y 600
//點擊菜單選項觸發(fā)的回調方法
void ProcessMenu(int value) {
switch(value) {
case 1:
//開啟抗鋸齒處理丢胚,必須先開啟顏色混合模式
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//點抗鋸齒
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
//線抗鋸齒
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
//多邊形抗鋸齒
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
break;
case 2:
//關閉抗鋸齒處理
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
break;
default:
break;
}
//觸發(fā)渲染
glutPostRedisplay();
}
//渲染畫面
void RenderScene(void) {
//清除緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//設置著色器為單位黑色
GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_FLAT, viewFrustum.GetProjectionMatrix(), vWhite);
//畫小點
glPointSize(1.0f);
smallStarBatch.Draw();
//畫大點
glPointSize(4.0f);
mediumStarBatch.Draw();
//畫超大點
glPointSize(8.0f);
largeStarBatch.Draw();
//畫月亮
moonBatch.Draw();
//畫山的輪廓
glLineWidth(3.5);
mountainRangeBatch.Draw();
//將在后臺緩沖區(qū)進行渲染翩瓜,然后在結束時交換到前臺
glutSwapBuffers();
}
//初始化小點批次
void SetupSmallStarBatch() {
M3DVector3f vVerts[SMALL_STARS];
for(int i = 0; i < SMALL_STARS; i++) {
vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
vVerts[i][2] = 0.0f;
}
smallStarBatch.Begin(GL_POINTS, SMALL_STARS);
smallStarBatch.CopyVertexData3f(vVerts);
smallStarBatch.End();
}
//初始化大點批次
void SetupMeiumStarBatch() {
M3DVector3f vVerts[MEDIUM_STARS];
for(int i = 0; i < MEDIUM_STARS; i++) {
vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
vVerts[i][2] = 0.0f;
}
mediumStarBatch.Begin(GL_POINTS, MEDIUM_STARS);
mediumStarBatch.CopyVertexData3f(vVerts);
mediumStarBatch.End();
}
//初始化超大點批次
void SetupLargeStarBatch() {
M3DVector3f vVerts[LARGE_STARS];
for(int i = 0; i < LARGE_STARS; i++) {
vVerts[i][0] = (GLfloat)(rand() % SCREEN_X);
vVerts[i][1] = (GLfloat)(rand() % (SCREEN_Y - 100)) + 100.0f;
vVerts[i][2] = 0.0f;
}
largeStarBatch.Begin(GL_POINTS, LARGE_STARS);
largeStarBatch.CopyVertexData3f(vVerts);
largeStarBatch.End();
}
//初始化山輪廓批次
void SetupMountainRangeBatch() {
M3DVector3f vMountains[12] = {
0.0f, 25.0f, 0.0f,
50.0f, 100.0f, 0.0f,
100.0f, 25.0f, 0.0f,
225.0f, 125.0f, 0.0f,
300.0f, 50.0f, 0.0f,
375.0f, 100.0f, 0.0f,
460.0f, 25.0f, 0.0f,
525.0f, 100.0f, 0.0f,
600.0f, 20.0f, 0.0f,
675.0f, 70.0f, 0.0f,
750.0f, 25.0f, 0.0f,
800.0f, 90.0f, 0.0f
};
mountainRangeBatch.Begin(GL_LINE_STRIP, 12);
mountainRangeBatch.CopyVertexData3f(vMountains);
mountainRangeBatch.End();
}
//初始化月亮批次
void SetupMoonBatch() {
GLfloat x = 700.0f;
GLfloat y = 500.0f;
GLfloat r = 50.0f;
M3DVector3f vVerts[SMALL_STARS];
int nVerts = 0;
vVerts[nVerts][0] = x;
vVerts[nVerts][1] = y;
vVerts[nVerts][2] = 0.0f;
for(GLfloat angle = 0; angle < M3D_2PI; angle += 0.2f) {
nVerts++;
vVerts[nVerts][0] = x + float(cos(angle)) * r;
vVerts[nVerts][1] = y + float(sin(angle)) * r;
vVerts[nVerts][2] = 0.0f;
}
nVerts++;
vVerts[nVerts][0] = x + r;;
vVerts[nVerts][1] = y;
vVerts[nVerts][2] = 0.0f;
moonBatch.Begin(GL_TRIANGLE_FAN, 34);
moonBatch.CopyVertexData3f(vVerts);
moonBatch.End();
}
//程序化一次性初始化
void SetupRC() {
//設置背景色為黑色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
//初始化著色器
shaderManager.InitializeStockShaders();
//初始化各個圖元批次
SetupSmallStarBatch();
SetupMeiumStarBatch();
SetupLargeStarBatch();
SetupMountainRangeBatch();
SetupMoonBatch();
}
//窗口大小改變時接受新的寬度和高度
void ChangeSize(int w, int h) {
glViewport(0, 0, w, h);
//正投影
viewFrustum.SetOrthographic(0.0f, SCREEN_X, 0.0f, SCREEN_Y, -1.0f, 1.0f);
}
//程序入口
int main(int argc, char* argv[]) {
//設置當前工作目錄,針對MAC OS X
gltSetWorkingDirectory(argv[0]);
//GLUT初始化
glutInit(&argc, argv);
/*初始化渲染模式携龟,其中標志GLUT_DOUBLE兔跌、GLUT_RGBA、GLUT_DEPTH峡蟋、GLUT_STENCIL分別指
雙緩沖窗口坟桅、RGBA顏色模式、深度測試蕊蝗、模板緩沖區(qū)*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
//創(chuàng)建窗口大小仅乓、標題
glutInitWindowSize(800, 600);
glutCreateWindow("Smoothing Out The Jaggies");
//創(chuàng)建菜單并綁定回調函數(shù),添加選項蓬戚,確定右鍵觸發(fā)
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("Antialiased Rendering",1);
glutAddMenuEntry("Normal Rendering",2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
//注冊回調函數(shù)
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
//判斷驅動是否正常
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
//初始化
SetupRC();
//運行循環(huán)
glutMainLoop();
return 0;
}
上面的 Demo 源碼全部都放在我的 github/OpenGLDemo 上夸楣,大家可以去下載和調試。
有什么問題可以在下方評論區(qū)提出子漩,寫得不好可以提出你的意見豫喧,我會合理采納的,O(∩_∩)O哈哈~幢泼,求關注求贊