- 5.三角形渲染Demo(实践)
- 6.正方形图形移动Demo(实践)
- 7.绘制图形:三角形、正方形、圆、正弦函数(实践)
5. 三角形渲染Demo
//着色器管理类
#include "GLShaderManager.h"
//包含了大部分GLTools中类似C语言的独立函数
#include "GLTools.h"
#include <GLUT/GLUT.h>
//着色器管理器
GLShaderManager shaderManager;
//简单的批次容器,是GLTools的一个简单容器类
GLBatch triangleBatch;
/// 重塑函数 窗口大小改变时,会接受新的宽度和高度,w和h随之改变。通过glutReshaperFunc(函数名)注册,当屏幕大小发生变化或者第一次创建窗口时,会调用改函数。
/// @param w 宽度
/// @param h 高度
void reshape(int w, int h){
glViewport(0, 0, w, h);
}
/// 显示函数,通过glutDisplayFunc(函数名)注册,当屏幕发生变化/或者开发者主动渲染会调⽤此函数,用来实现数据->渲染过程
void display(void){
//1.清除缓存区。缓冲区是一块存储图像信息的储存空间,缓冲区包括颜色、深度、模板缓冲区。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);
//2.设置颜色 GLT_SHADER_IDENTITY:存储着色器,指定颜色以默认笛卡尔坐标系在屏幕上渲染集合图形
GLfloat vRed[] = {1.0, 0, 0, 1.0f};
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
//3.提交着色器,传递颜色到存储着色器
triangleBatch.Draw();
//4.将后台缓冲区进行渲染,结束后交换给前台
glutSwapBuffers();
}
//设置渲染环境,设置需要渲染的图形的相关顶点数据、颜色数据等数据装备工作
void setupRC(void){
//1.设置清屏颜色(背景颜色)
glClearColor(0.8f, 0.5f, 0.7f, 1.0f);
//2.初始化一个着色器
shaderManager.InitializeStockShaders();
//3.指定定点
GLfloat vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
//4.批次类开始绘制 GLBatch三角形批次类
triangleBatch.Begin(GL_TRIANGLES, 3);
//5.批次绘制
triangleBatch.CopyVertexData3f(vVerts);
//6.批次类结束绘制
triangleBatch.End();
}
//初始化一个GLEW库,确保OpenGL API对程序完全可用。在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题.
int checkOpenGLInit(void){
GLenum status = glewInit();
if(status != GLEW_OK){
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
return 0;
}
/*
程序的入口。OpenGL是面向过程编程,处理图形、图像都是链式形式。
*/
int main(int argc,char *argv[])
{
//1.初始化GLUT库,这个函数只是传输命令参数并初始化glut库
glutInit(&argc, argv);
//2.初始化显示模式 GLUT_DOUBLE:双缓冲窗口 GLUT_RGBA:RGBA颜色模式 GLUT_DEPTH:深度测试 GLUT_STENCIL:模板缓冲区
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//3.设置GLUT窗口的大小、标题
glutInitWindowSize(500, 500);
glutCreateWindow("Triangle");
//4.注册重塑函数
glutReshapeFunc(reshape);
//5.注册显示函数
glutDisplayFunc(display);
//6.判断OpenGl API对程序是否可用
checkOpenGLInit();
//7.设置渲染环境
setupRC();
//8.类似于iOS runloop 运⾏行行循环
glutMainLoop();
return 0;
}
运行结果:
三角形渲染.png
6.正方形图形移动Demo
#include <GLShaderManager.h>
#include <GLTools.h>
#include <GLUT/GLUT.h>
GLShaderManager shaderManager;
GLBatch triangleBatch;
//正方形边长
GLfloat blockSize = 0.1f;
//正方形的4个顶点坐标
GLfloat vVerts[] = {
-blockSize,-blockSize,0,
blockSize,-blockSize,0,
blockSize,blockSize,0,
-blockSize,blockSize,0
};
//重塑函数
void reshape(int w, int h){
glViewport(0, 0, w, h);
}
//显示函数
void display(void){
//1.清除一个或者一组特定的缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//2.设置颜色
GLfloat vRed[] = {1.0, 0.0, 0.0, 1.0f};
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
//3.提交着色器
triangleBatch.Draw();
//4.交换缓冲区
glutSwapBuffers();
}
// 设置渲染环境
void setupRC(void){
//1.设置背景颜色
glClearColor(0.0f, 0.0f, 0.0f, 1);
//2.初始化着色器
shaderManager.InitializeStockShaders();
//3.指定定点,正方形的4个定点
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
//4.批次绘制
triangleBatch.CopyVertexData3f(vVerts);
//5.批次类结束绘制
triangleBatch.End();
}
//检查OpenGL API是否安全可用
int checkOpenGLInit(void){
GLenum status = glewInit();
if(status != GLEW_OK){
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
return 0;
}
//特殊函数 这里负责处理移动
void specialKeys(int key, int x, int y){
GLfloat stepSize = 0.025f;
GLfloat blockX = vVerts[6];
GLfloat blockY = vVerts[7];
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 < 2 * blockSize - 1) {
blockX = 2 * blockSize - 1;
}
//当正方形移动到最右边时
if (blockX > 1.0f) {
blockX = 1.0f;
}
//当正方形移动到最上面时
if (blockY > 1.0f) {
blockY = 1.0f;
}
//当正方形移动到最下面时
if (blockY < 2 * blockSize - 1) {
blockY = 2 * blockSize - 1;
}
vVerts[0] = blockX - 2 * blockSize;
vVerts[1] = blockY - 2 * blockSize;
vVerts[3] = blockX;
vVerts[4] = blockY - 2 * blockSize;
vVerts[6] = blockX;
vVerts[7] = blockY;
vVerts[9] = blockX - 2 * blockSize;
vVerts[10] = blockY;
printf("blockX = %f\n",blockX);
printf("blockY = %f\n",blockY);
triangleBatch.CopyVertexData3f(vVerts);
glutPostRedisplay();
}
int main(int argc,char *argv[])
{
//设置当前的工作目录,针对Mac OS X,为了安全 GLTools函数glSetWorkingDirectory用来设置当前工作目录。在Windows中是不需要的,因为工作目录默认就是与可执行程序相同目录。但是在MAC OS X中,这个程序当前工作文件夹改为应用程序捆包中的/Resource文件夹。GLUT的优先设定自动进行了设置,这个方法是为了更安全。
gltSetWorkingDirectory(argv[0]);
//1.初始化GLUT库
glutInit(&argc, argv);
//2.初始化显示模式
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//3.设置GLUT窗口大小、标题
glutInitWindowSize(500, 500);
glutCreateWindow("Rectangle");
//4.注册重塑函数
glutReshapeFunc(reshape);
//5.注册显示函数
glutDisplayFunc(display);
//6.注册特殊函数,此处是移动控制函数
glutSpecialFunc(specialKeys);
//7.判断OpenGL API是否可用
checkOpenGLInit();
//8.设置渲染环境
setupRC();
//开启runloop循环
glutMainLoop();
return 0;
}
运行结果:
正方形图形移动.png
7.绘制图形:三角形、正方形、圆、正弦函数
#include <iostream>
#include <GLUT/GlUT.h>
#include "math3d.h"
//正方形
void drawSquare(void){
//1.设置背景颜色(窗口的)
glClearColor(0.8, 0.5, 0.5, 1);
//2.清除缓冲区
glClear(GL_COLOR_BUFFER_BIT);
//3.设置正方形颜色
glColor3f(0.4f, 0.2f, 0.8f);
//4.设置绘图时的坐标系统
//左、右、上、下、近、远
glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
//5.开始渲染
glBegin(GL_POLYGON);
//6.设置多边形的4个顶点
glVertex3f(.2f, .2f, .0f);
glVertex3f(.6f, .2f, .0f);
glVertex3f(.6f, .6f, .0f);
glVertex3f(.2f, .6f, .0f);
//7.结束渲染
glEnd();
//8.强制刷新缓冲区,保证绘制命令得以执行
glFlush();
}
//画圆
void drawCircle(void){
//1.设置窗口的背景颜色
glClearColor(0.2, 0.35, 0.65, 1);
//2.清除缓冲区
glClear(GL_COLOR_BUFFER_BIT);
//3.设置圆的颜色
glColor3f(0.23, 0.6, 0.9);
//4.开始渲染
glBegin(GL_POLYGON);
//5.设置顶点
const int n = 100; //n为3时三角形;为4时四边形;n越大越接近圆
const GLfloat R = 0.5f; //圆的半径
const GLfloat pi = 3.1415926f; //圆周率
for (int i = 0; i < n; i++) {
//圆的坐标((R * cos(α),(R * sin(α))
// α = 2 * π / n * i 把圆的角度分为n份,获取第i份的角度
glVertex2f(R*cos(2 * pi / n*i), R*sin(2 * pi / n*i));
}
//6.结束渲染
glEnd();
//7.强制刷新缓冲区
glFlush();
}
//五角形
void drawPentagon(void){
/*
设五角星的五个顶点分布位置关系如下:
A
E B
D C
首先,根据余弦定理列方程,计算五角星的中心到顶点的距离a
(假设五角星对应正五边形的边长为.0)
a = 1 / (2-2*cos(72*Pi/180));
然后,根据正弦和余弦的定义,计算B的x坐标bx和y坐标by,以及C的y坐标
(假设五角星的中心在坐标原点)
bx = a * cos(18 * Pi/180);
by = a * sin(18 * Pi/180);
cy = -a * cos(18 * Pi/180);
五个点的坐标就可以通过以上四个量和一些常数简单的表示出来
*/
const GLfloat Pi = 3.1415926536f;
GLfloat a = 1 / (2-2*cos(72*Pi/180));
GLfloat bx = a * cos(18 * Pi/180);
GLfloat by = a * sin(18 * Pi/180);
GLfloat cy = -a * cos(18 * Pi/180);
GLfloat
PointA[2] = { 0, a },
PointB[2] = { bx, by },
PointC[2] = { 0.5, cy },
PointD[2] = { -0.5, cy },
PointE[2] = { -bx, by };
glClear(GL_COLOR_BUFFER_BIT);
// 按照A->C->E->B->D->A的顺序,可以一笔将五角星画出
glBegin(GL_LINE_LOOP);
glVertex2fv(PointA);
glVertex2fv(PointC);
glVertex2fv(PointE);
glVertex2fv(PointB);
glVertex2fv(PointD);
glEnd();
glFlush();
}
//画出正弦函数的图形
void drawSin(void){
//1.设置窗口的背景颜色
glClearColor(0.2, 0.35, 0.65, 1);
//2.清除缓冲区
glClear(GL_COLOR_BUFFER_BIT);
//3.画出X轴和Y轴
glBegin(GL_LINES);
glVertex2f(-1.0f, 0.0f);
glVertex2f(1.0f, 0.0f);
glVertex2f(0.0f, -1.0f);
glVertex2f(0.0f, 1.0f);
glEnd();
//4.画出正弦曲线
//正弦坐标 (x,sin(x))
//由于OpenGL默认坐标值只能从-1到1,所以我们设置一个因子factor,把所有的坐标值等比例缩小,这样就可以画出更多个正弦周期试修改factor的值,观察变化情况
const GLfloat factor = 0.1f;
GLfloat x;
glBegin(GL_LINE_STRIP);
for (x = -1.0/factor; x<1.0f/factor; x+= 0.01f) {
glVertex2f(x*factor, sin(x)*factor);
}
glEnd();
glFlush();
}
int main(int argc,char *argv[]){
//1.初始化GLUT库
glutInit(&argc, (char **)argv);
//2.创建一个窗口 并命名设置大小
glutInitWindowSize(500, 500);
glutCreateWindow("多边形");
//3.注册绘图函数
//glutDisplayFunc(drawSquare);
//glutDisplayFunc(drawCircle);
//glutDisplayFunc(drawPentagon);
glutDisplayFunc(drawSin);
//开启循环
glutMainLoop();
return 0;;
}
运行结果如下:正方形.png
圆.png
五角形.png
正弦.png