开场白
本文主要介绍了一下OpenGL中的‘’HelloWord‘’代码逻辑,相关解释在代码注释中。
实现了键盘上下左右按键控制正方形移动以及编辑处理。
代码
#include "GLShaderManager.h"
#include "GLTools.h"
#include <GLUT/GLUT.h>
//定义一个着色器
GLShaderManager shaderManager;
//批次容器,GLTools的一个简单容器类。
GLBatch triangleBatch;
/**
正方形的边长,
OpenGL默认坐标原点是屏幕的正中心,屏幕的xy范围是(-1,-1)到(1,1)
0.1可以理解为屏幕正值总长度的的10%,(正值+负值)的总长度的5%
由于代码中设置的glut初始化窗口是500x500,所以用这种方式设置边长是正方形,如果修改成500x600,就不是正方形了
*/
GLfloat blockSize = 0.1f;
//正方形4个点 0~2:左下点 3~5:右下点 6~8:右上点 9~11:左上点
GLfloat vVerts[] = {
-blockSize, -blockSize, 0.0f,
blockSize, -blockSize, 0.0f,
blockSize, blockSize, 0.0f,
-blockSize, blockSize, 0.0f,
};
//修改窗口大小回调
void changeSize(int w, int h) {
//设置视口
glViewport(0, 0, w, h);
}
//渲染显示回调
void renderScene(void) {
/*
clear缓冲区
缓冲区是一块存在图像信息的储存空间,红色、绿色、蓝色和alpha分量通常一起分量通常一起作为颜色缓存区或像素缓存区引用。
OpenGL 中不止一种缓冲区(颜色缓存区、深度缓存区和模板缓存区)
清除缓存区对数值进行预置
参数:指定将要清除的缓存的
GL_COLOR_BUFFER_BIT :指示当前激活的用来进行颜色写入缓冲区
GL_DEPTH_BUFFER_BIT :指示深度缓存区
GL_STENCIL_BUFFER_BIT:指示模板缓冲区
*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0, 0.0, 0.0, 1.0};
//shaderManager调用固定着色器方法,参数指定着色器类型
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
//提交着色器
triangleBatch.Draw();
//在开始的设置openGL 窗口的时候,我们指定要一个双缓冲区的渲染环境。这就意味着将在后台缓冲区进行渲染,渲染结束后交换给前台。这种方式可以防止观察者看到可能伴随着动画帧与动画帧之间的闪烁的渲染过程。缓冲区交换平台将以平台特定的方式进行。
//将后台缓冲区进行渲染,然后结束后交换给前台
glutSwapBuffers();
}
void setupRC() {
//设置清屏颜色(背景颜色)
glClearColor(0.98, 0.4, 0.7, 1);
//初始化着色器管理类
shaderManager.InitializeStockShaders();
//开始批处理
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
//拷贝顶点数据
triangleBatch.CopyVertexData3f(vVerts);
//结束批处理
triangleBatch.End();
}
void SpeciaKeys(int key, int x, int y) {
GLfloat stepSize = 0.025f;
GLfloat blockX = vVerts[0];
GLfloat blockY = vVerts[10];
printf("v[0] = %f\n", blockX);
printf("v[10] = %f\n", blockY);
/**
键盘响应相关处理,对应 上下左右
GLUT_KEY_UP
GLUT_KEY_DOWN
GLUT_KEY_LEFT
GLUT_KEY_RIGHT
*/
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.0) {
blockX = -1.0f;
}
if (blockX > 1.0 - blockSize * 2) {
blockX = 1.0 - blockSize * 2;
}
if (blockY < -1.0 + blockSize * 2) {
blockY = -1.0 + blockSize * 2;
}
if (blockY > 1.0) {
blockY = 1.0;
}
printf("blockX = %f\n", blockX);
printf("blockY = %f\n", blockY);
//改变四个点的位置
vVerts[0] = blockX;
vVerts[1] = blockY - blockSize * 2;
printf("(%f, %f)\n", vVerts[0], vVerts[1]);
vVerts[3] = blockX + blockSize * 2;
vVerts[4] = blockY - blockSize * 2;
printf("(%f, %f)\n", vVerts[3], vVerts[4]);
vVerts[6] = blockX + blockSize * 2;
vVerts[7] = blockY;
printf("(%f, %f)\n", vVerts[6], vVerts[7]);
vVerts[9] = blockX;
vVerts[10] = blockY;
printf("(%f, %f)\n", vVerts[9], vVerts[10]);
triangleBatch.CopyVertexData3f(vVerts);
glutPostRedisplay();
}
int main(int argc,char *argv[]) {
//设置工作路径
gltSetWorkingDirectory(argv[0]);
//初始化glut
glutInit(&argc, argv);
/**
设置glut显示模式
GLUT_DOUBLE: 双缓存窗口,是指绘图命令实际上是离屏缓存区执行的,然后迅速转换成窗口视图,这种方式经常用来生成动画效果
GLUT_RGBA:表明欲建立RGBA模式的窗口。
GLUT_DEPTH:标志将一个深度缓存区分配为显示的一部分,因此我们能够执行深度测试
GLUT_STENCIL:确保我们也会有一个可用的模板缓存区。
*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//glut初始化窗口 500x500
glutInitWindowSize(500, 500);
//glut窗口title
glutCreateWindow("Triangle");
/**
GLUT内部运行一个本地消息循环,拦截适当的消息。然后调用注册的回调函数。
*/
//注册重塑函数,为窗口改变size的时候进行回调处理
glutReshapeFunc(changeSize);
//注册显示函数,渲染回调
glutDisplayFunc(renderScene);
//注册特殊函数,触发键盘操作
glutSpecialFunc(SpeciaKeys);
/**
初始化一个GLEW库,确保OpenGL API是可用有效的。
在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题
*/
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n", glewGetErrorString(status));
return 1;
}
//初始化设置我们的渲染环境
setupRC();
//glut启动
glutMainLoop();
return 0;
}
初入了解OpenGL,如有说明不妥的地方,还请指出。
网友评论