實(shí)現(xiàn)繪制正方形同辣,主要分為創(chuàng)建Main函數(shù)、設(shè)置窗口惭载、設(shè)置顯示函數(shù)旱函、設(shè)置渲染屬性、按鍵監(jiān)聽函數(shù)等五個(gè)步驟來(lái)實(shí)現(xiàn)
第一步:
首先是Main函數(shù),主要是設(shè)置監(jiān)聽窗口尺寸函數(shù)描滔、顯示函數(shù)棒妨、按鍵監(jiān)聽的改變和設(shè)置屬性setupRC(),以及開啟線程和保護(hù)線程
#include "GLShaderManager.h"
/*
`#include<GLShaderManager.h>` 移入了GLTool 著色器管理器(shader Mananger)類。沒有著色器含长,我們就不能在OpenGL(核心框架)進(jìn)行著色券腔。著色器管理器不僅允許我們創(chuàng)建并管理著色器,還提供一組“存儲(chǔ)著色器”拘泞,他們能夠進(jìn)行一些初步?基本的渲染操作纷纫。
*/
#include "GLTools.h"
/*
`#include<GLTools.h>` GLTool.h頭文件包含了大部分GLTool中類似C語(yǔ)言的獨(dú)立函數(shù)
*/
#include <GLUT/GLUT.h>
/*
在Mac 系統(tǒng)下,`#include<glut/glut.h>`
在Windows 和 Linux上陪腌,我們使用freeglut的靜態(tài)庫(kù)版本并且需要添加一個(gè)宏
*/
// 定義一個(gè)辱魁,著色管理器
GLShaderManager shaderManager;
// 簡(jiǎn)單的批次容器烟瞧,是GLTools的一個(gè)簡(jiǎn)單的容器類
GLBatch triangleBatch;
// blockSize 邊長(zhǎng)
GLfloat blockSize = 0.1f;
//正方形的4個(gè)點(diǎn)坐標(biāo)
GLfloat vVerts[] = {
-blockSize,-blockSize,0.0f,
blockSize,-blockSize,0.0f,
blockSize,blockSize,0.0f,
-blockSize,blockSize,0.0f
};
int main(int argc, char *argv[])
{
//設(shè)置當(dāng)前工作目錄,針對(duì)MAC OS X
/*
`GLTools`函數(shù)`glSetWorkingDrectory`用來(lái)設(shè)置當(dāng)前工作目錄染簇。實(shí)際上在Windows中是不必要的参滴,因?yàn)楣ぷ髂夸浤J(rèn)就是與程序可執(zhí)行執(zhí)行程序相同的目錄。但是在Mac OS X中锻弓,這個(gè)程序?qū)?dāng)前工作文件夾改為應(yīng)用程序捆綁包中的`/Resource`文件夾砾赔。`GLUT`的優(yōu)先設(shè)定自動(dòng)進(jìn)行了這個(gè)中設(shè)置,但是這樣中方法更加安全青灼。
*/
gltSetWorkingDirectory(argv[0]);
//初始化GLUT庫(kù),這個(gè)函數(shù)只是傳說(shuō)命令參數(shù)并且初始化glut庫(kù)
glutInit(&argc, argv);
/*
初始化雙緩沖窗口暴心,其中標(biāo)志GLUT_DOUBLE、GLUT_RGBA杂拨、GLUT_DEPTH专普、GLUT_STENCIL分別指
雙緩沖窗口、RGBA顏色模式扳躬、深度測(cè)試脆诉、模板緩沖區(qū)
--GLUT_DOUBLE`:雙緩存窗口甚亭,是指繪圖命令實(shí)際上是離屏緩存區(qū)執(zhí)行的贷币,然后迅速轉(zhuǎn)換成窗口視圖,這種方式亏狰,經(jīng)常用來(lái)生成動(dòng)畫效果役纹;
--GLUT_DEPTH`:標(biāo)志將一個(gè)深度緩存區(qū)分配為顯示的一部分,因此我們能夠執(zhí)行深度測(cè)試暇唾;
--GLUT_STENCIL`:確保我們也會(huì)有一個(gè)可用的模板緩存區(qū)促脉。
深度、模板測(cè)試后面會(huì)細(xì)致講到
*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
//GLUT 窗口大小策州、窗口標(biāo)題
glutInitWindowSize(800, 600);
glutCreateWindow("Hello world!");
/*
GLUT 內(nèi)部運(yùn)行一個(gè)本地消息循環(huán)瘸味,攔截適當(dāng)?shù)南ⅰH缓笳{(diào)用我們不同時(shí)間注冊(cè)的回調(diào)函數(shù)够挂。我們一共注冊(cè)2個(gè)回調(diào)函數(shù):
1)為窗口改變大小而設(shè)置的一個(gè)回調(diào)函數(shù)
2)包含OpenGL 渲染的回調(diào)函數(shù)
*/
//注冊(cè)重塑函數(shù)
glutReshapeFunc(changeSize);
//注冊(cè)顯示函數(shù)
glutDisplayFunc(RenderScene);
//注冊(cè)特殊函數(shù)
glutSpecialFunc(SpecialKes);
/*
初始化一個(gè)GLEW庫(kù),確保OpenGL API對(duì)程序完全可用旁仿。
在試圖做任何渲染之前,要檢查確定驅(qū)動(dòng)程序的初始化過(guò)程中沒有任何問(wèn)題
*/
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error: %s\n", glewGetErrorString(status));
return 1;
}
setupRC();
//設(shè)置我們的渲染環(huán)境
//保護(hù)線程的運(yùn)行
glutMainLoop();
return 0;
}
第二步:窗口尺寸的監(jiān)聽回調(diào)
void changeSize(int w,int h)
{
/*
x,y 參數(shù)代表窗口中視圖的左下角坐標(biāo)孽糖,而寬度枯冈、高度是像素為表示,通常x,y 都是為0
*/
glViewport(0, 0, w, h);
}
第三步:渲染函數(shù),將設(shè)置的正方體渲染出窗口上
void RenderScene(void)
{
//1.清除一個(gè)或者一組特定的緩存區(qū)
/*
緩沖區(qū)是一塊存在圖像信息的儲(chǔ)存空間办悟,紅色尘奏、綠色、藍(lán)色和alpha分量通常一起分量通常一起作為顏色緩存區(qū)或像素緩存區(qū)引用病蛉。
OpenGL 中不止一種緩沖區(qū)(顏色緩存區(qū)炫加、深度緩存區(qū)和模板緩存區(qū))
清除緩存區(qū)對(duì)數(shù)值進(jìn)行預(yù)置
參數(shù):指定將要清除的緩存的
GL_COLOR_BUFFER_BIT :指示當(dāng)前激活的用來(lái)進(jìn)行顏色寫入緩沖區(qū)
GL_DEPTH_BUFFER_BIT :指示深度緩存區(qū)
GL_STENCIL_BUFFER_BIT:指示模板緩沖區(qū)
*/
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//2.設(shè)置一組浮點(diǎn)數(shù)來(lái)表示紅色
//GLfloat vRed[] = {1.0,0.0,0.0,1.0f};
//傳遞到存儲(chǔ)著色器瑰煎,即GLT_SHADER_IDENTITY著色器,這個(gè)著色器只是使用指定顏色以默認(rèn)笛卡爾坐標(biāo)第在屏幕上渲染幾何圖形
//shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
//提交著色器
//triangleBatch.Draw();
//在開始的設(shè)置openGL 窗口的時(shí)候琢感,我們指定要一個(gè)雙緩沖區(qū)的渲染環(huán)境丢间。這就意味著將在后臺(tái)緩沖區(qū)進(jìn)行渲染,渲染結(jié)束后交換給前臺(tái)驹针。這種方式可以防止觀察者看到可能伴隨著動(dòng)畫幀與動(dòng)畫幀之間的閃爍的渲染過(guò)程烘挫。緩沖區(qū)交換平臺(tái)將以平臺(tái)特定的方式進(jìn)行。
//將后臺(tái)緩沖區(qū)進(jìn)行渲染柬甥,然后結(jié)束后交換給前臺(tái)
//glutSwapBuffers();
//---------方法2--------
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f,0.0f,0.0f,0.0f};
M3DMatrix44f mFinalTransform,mTransfromMatrix,mRotationMartix;
//平移
m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);
//每次平移時(shí)饮六,旋轉(zhuǎn)5度
static float yRot = 0.0f;
yRot += 5.0f;
m3dRotationMatrix44(mRotationMartix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
//將旋轉(zhuǎn)和移動(dòng)的矩陣結(jié)果 合并到mFinalTransform (矩陣相乘)
m3dMatrixMultiply44(mFinalTransform, mTransfromMatrix, mRotationMartix);
//將矩陣結(jié)果 提交給固定著色器(平面著色器)中繪制
shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinalTransform,vRed);
triangleBatch.Draw();
//執(zhí)行交換緩存區(qū)
glutSwapBuffers();
}
第四步:設(shè)置基本屬性,設(shè)置頂點(diǎn)數(shù)據(jù)和顏色
void setupRC()
{
//設(shè)置清屏顏色(背景顏色)
glClearColor(0.98f, 0.40f, 0.7f, 1);
//沒有著色器苛蒲,在OpenGL 核心框架中是無(wú)法進(jìn)行任何渲染的卤橄。初始化一個(gè)渲染管理器。
//在前面的課程臂外,我們會(huì)采用固管線渲染窟扑,后面會(huì)學(xué)著用OpenGL著色語(yǔ)言來(lái)寫著色器
shaderManager.InitializeStockShaders();
//修改為GL_TRIANGLE_FAN ,4個(gè)頂點(diǎn)
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
第五步:按鍵監(jiān)聽回調(diào),通過(guò)按鍵可以移動(dòng)正方體的位置
void SpecialKeys(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;
}
//碰撞檢測(cè)
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();
}
到此就成功啦漏健!