美文网首页
视频特效学习01-OpenGL初探Demo

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

作者: 小破孩丫 | 来源:发表于2020-04-07 14:35 被阅读0次
  • 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

相关文章

网友评论

      本文标题:视频特效学习01-OpenGL初探Demo

      本文链接:https://www.haomeiwen.com/subject/yjfnphtx.html