iOS 渲染学习(二)
OpenGL渲染正方形&平移
渲染
// 定义一个着色器管理器
GLShaderManager shaderManager;
//简单的批次容器,是GLTools的一个简单的容器类
GLBatch triangleBatch;
//设定的边长
GLfloat blockSize = 0.1f;
//正方形的四个点的坐标
GLfloat vVerts[] = {
-blockSize,-blockSize,0.1f,
blockSize,-blockSize,0.1f,
blockSize,blockSize,0.1f,
-blockSize,blockSize,0.1f,
};
//窗口大小改变时,接收新的宽度和高度
void changeSize(int w,int h){
glViewport(0, 0, w, h);
}
核心代码
// 显示函数
void RenderScene(void){
// 1. 首先需要清除一个或一组特定的缓存区
// 清屏
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// 2. 设置一组浮点数 设定颜色
GLfloat vRed[] = {0.0f,1.0f,0.0f,1.0f};
// 3. 传递给存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色 以默认笛卡尔坐标在屏幕上渲染几何图形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
// 4. 提交着色器 绘制
triangleBatch.Draw();
// 在开始设置OpenGL窗口的时候,指定一个双缓冲区的渲染环境,这就意味着将在后台缓冲区进行渲染,渲染结束后交还给前台,这种方式可以防止观察者看到 可能伴随着动画帧与动画帧之间 闪烁的渲染过程,缓冲区交换平台将以平台特定的方式进行
// 5.将后台缓冲区进行渲染,结束后交还给前台
glutSwapBuffers();
}
void setupRC(){
// 设置清屏颜色(背景颜色)
glClearColor(0.98f, 0.3f, 0.8f, 1.0f);
// 初始化一个渲染管理器
shaderManager.InitializeStockShaders();
// 指定顶点 GL_TRIANGLE_FAN 绘制连接方式。
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
绘制连接方式
实现
int main(int argc, char *argv[]){
// 设置当前工作目录,针对MACOSX
gltSetWorkingDirectory(argv[0]);
// 初始化GLUT库
glutInit(&argc, argv);
// 初始化双缓冲窗口,其中标志GLUT_DOUBLE(双缓冲窗口),GLUT_RGBA(RGBA颜色模式),GLUT_DEPTH(深度测试),GLUT_STENCIL(模版缓冲区)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
// GLUT窗口大小 标题窗口
glutInitWindowSize(500, 500);
glutCreateWindow("Triangle");
/*
GLUT内部会运行一个本地消息循环,拦截适当的消息,然后调用我们不同时间注册的回调函数,我们一共注册了2个回调函数
1.为窗口改变大小而设置的一个回调函数
2.包含OpenGL 渲染的回调函数
*/
// 注册重塑函数
glutReshapeFunc(changeSize);
// 注册显示函数
glutDisplayFunc(RenderScene);
GLenum status = glewInit();
// 驱动程序的初始化是否出现问题
if (GLEW_OK != status) {
printf("GLEW error : %s
",glewGetErrorString(status));
return 1;
}
// 设置渲染环境
setupRC();
glutMainLoop();
return 0;
}
平移
1.坐标更新方式
void specialKeys(int key, int x, int y){
// 每次移动的长度
GLfloat stepSize = 0.025f;
// blockX/blockY: 相对移动顶点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.0f-blockSize*2) {
blockX = 1.0f-blockSize*2;
}
// 最上边
if (blockY >= 1.0f) {
blockY = 1.0f;
}
// 最下边
if (blockY <= -1.0f+blockSize*2) {
blockY = -1.0f+blockSize*2;
}
// 四个顶点坐标进行更新
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;
//将顶点数组通过GLBatch帮助类将顶点传输到存储着⾊器中,并⼿动触发渲染函数.
triangleBatch.CopyVertexData3f(vVerts);
glutPostRedisplay();
}
// 注册特殊函数
glutSpecialFunc(specialKeys);
2.矩阵方式
相比坐标更新的方式,矩阵方式适合顶点很多的图形,因为它不需要对每一个顶点的坐标都进行更新,更像根据图形的中心点xPos&yPos的移动进行平移.
添加中心点
// 记录x y 平移的距离
GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;
修改RenderScene和specialKeys函数
void RenderScene(void){
// 矩阵计算
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {0.0f,1.0f,0.0f,1.0f};
// 矩阵
M3DMatrix44f mTransfromMatrix;
m3dTranslationMatrix44(mTransfromMatrix, xPos , yPos, 0.0f);
// 平面着色器
shaderManager.UseStockShader(GLT_SHADER_FLAT,mTransfromMatrix,vRed);
triangleBatch.Draw();
glutSwapBuffers();
}
void specialKeys(int key, int x, int y){
// 每次移动的长度
GLfloat stepSize = 0.025f;
GLfloat blockX = vVerts[0];
GLfloat blockY = vVerts[10];
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();
}