视频特效学习01-OpenGL初探Demo

  • 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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,884评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,212评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,351评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,412评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,438评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,127评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,714评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,636评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,173评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,264评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,402评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,073评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,763评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,253评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,382评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,749评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,403评论 2 358

推荐阅读更多精彩内容