OpenGL之简单渲染一个三角形

资源准备

  • 环境准备:本文是基于OpenGL的开发环境搭建完成的情况下,进行一些简单图形的渲染和显示(macOS的OpenGL环境搭建,详情可参考我之前的文章:OpenGL在macOS上的环境搭建

  • 工具类(着色器管理类、GLTools函数、freeglut静态库)
    ① 着色器管理类:GLTool 着⾊管理器类(shader Mananger),创建管理着色器,进行基本的渲染(#include<GLShaderManager.h>);
    ② GLTools函数:包含了大部分GLTool中类似C语⾔的独立函数( #include<GLTools.h>);
    ③ freeglut静态库:在Windows 和 Linux上,使用freeglut的静态库版本并且需要添加⼀个宏(#include<glut/glut.h>);

图像渲染过程

  • 从OpenGL的几何图元中设置数据,用于构建形状;
  • 使用不同的着色器(Shader)对输入的图元数据执行计算操作,判断其的位置、颜色,以及其他渲染属性;
  • 将输入图元的数学描述转化为与屏幕位置对应的像素片元(Fragment),也即为光栅化(Rasterization);
  • 针对光栅化过程产生的每个片元,执行片元着色器(Fragment shader),从而决定这个片元的最终颜色和位置;
  • 如果有必要,还需要对每个片元执行一些额外的操作,比如判断片元对应的对象是否可见,或者将片元的颜色与当前屏幕位置的颜色进行融合。

函数解析

  • void changeWindowSize(int w ,int h) :⾃定义函数,通过glutReshaperFunc(函数名)注册为重塑函数,当屏幕⼤小发⽣变化/或者第⼀次创建窗⼝时,会调⽤该函数调整窗⼝大小。
  • void renderScene(void):⾃定义函数,通过
    glutDisplayFunc(函数名)注册为显示渲染函数,当屏幕发生变化/或者开发者主动渲染会调⽤此函数,来实现数据->渲染过程;
  • void setupRC():⾃定义函数,设置需要渲染的图形的相关顶点数据/颜色数据等数据准备工作;
  • int main(int argc ,char *argv[]):程序⼊口.OpenGL 是面向过程编程,利用OpenGL处理图形/图像都是链式形式,以及基于OpenGL封装的图像处理框架也是链式编程;

OpenGL的基本图元

在这里插入图片描述

实现流程

在这里插入图片描述

main函数的常用函数/方法说明

  • glutInit() 负责初始化GLUT库。它会处理向程序输入的命令行参数,并且移除其中与控制GLUT如何操作相关的部分。它必须是应用程序第一个GLUT函数,负责设置其他GLUT例程必需的数据结构。
  • glutInitDisplayMode() 设置了程序所使用的窗口类型。窗口设置更多的OpenGL 特性,例如RAGA颜色空间,使用深度缓存或动画效果。
  • glutInitWindowsSize() 设置所需的窗口大小,如果不想在这个设置一个固定值,也可以先查询显示设备的尺寸,然后根据计算机的屏幕动态设置窗口的大小。
  • glutCreateWindow(),它的功能和它的名字一样,如果当前的系统环境可以满足glutInitDisplayMode()的显示模式要求,这里就会创建一个窗口(此时会调用计算机窗口系统的接口)。只有GLUT创建了一个窗口之后(其中包含创建创建OpenGL环境的过程),才可以使用OpenGL相关的函数。
  • glewInit()函数,属于另一个辅助库GLEW(OpenGL Extention Wrangler)。GLEW可以简化获取函数地址的过程,并且包含了可以跨平台使用的其他一些OpenGL编程方法。
  • glutDisplayFunc(),它设置了一个显示回调(diplay callback),即GLUT在每次更新窗口内容的时候回自动调用该例程。
  • glutMainLoop(),这是一个无限执行的循环,它会负责一直处理窗口和操作系统的用户输入等操作。(注意:不会执行在glutMainLoop()之后的所有命令)

实现过程

  • 定义着色器和简单批次容器;
// 着色器
GLShaderManager shadermanager;
// 批次容器
GLBatch triangleBatch;
  • 设置渲染环境(main函数)
int main(int argc, char *argv[]) {
    
    // 设置当前工作目录,针对MAC OS X
    gltSetWorkingDirectory(argv[0]);
    
    // 初始化GLUT库
    glutInit(&argc, argv);
    
    /* 初始化双缓冲窗口
     * GLUT_DOUBLE : 双缓冲窗口
     * GLUT_RGBA : RGBA颜色模式
     * GLUT_DEPTH : 深度测试
     * GLUT_STENCIL : 模板缓冲区
     */
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
    
    // GLUT窗口大小,标题窗口
    glutInitWindowSize(400, 200);
    glutCreateWindow("绘制三角形");
    
    // 注册回掉函数
    glutReshapeFunc(changeWindowSize);
    glutDisplayFunc(renderScene);
    
    // 驱动程序的初始化中没有出现问题,确保API完全正常使用
    GLenum statue = glewInit();
    if (GLEW_OK != statue) {
        fprintf(stderr,"glew error:%s\n",glewGetErrorString(statue));
        return 1;
    }
    
    // 设置渲染环境
    setupRC();
    glutMainLoop();
    return 0;
}
  • 实现changeWindowSize函数:
/// 窗口大小改变时接受新的宽度和高度
/// 触发条件: 1.新建窗口  2.窗⼝尺⼨发生调整
/// 处理理业务: 1.设置OpenGL 视⼝  2. 设置OpenGL 投影⽅式等
/// @param w 像素
/// @param h 像素
void changeWindowSize(int w, int h) {
    glViewport(0, 0, w, h);
}
  • 实现setupRC函数:
void setupRC() {
    
    // 设置背景色
    glClearColor(0.98f, 0.40f, 0.0f, 1.0f);
    // 初始化着色器
    shadermanager.InitializeStockShaders();
    // 设置三角形顶点,其中数组vVerts包含所有3个顶点的x,y,z笛卡尔坐标对
    GLfloat vVerts[] = {-0.5f, 0.0f, 0.0f,
                        0.5f, 0.0f, 0.0f,
                        0.0f, 0.5f, 0.0f};
    // 批次处理,将数据传递到着⾊色器器
    triangleBatch.Begin(GL_TRIANGLES, 3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}
  • 实现renderScene函数:
/// 开始渲染(触发条件:1.系统自动触发 2.⼿动调用函数触发)
void renderScene(void) {
    // 清除一个或一组特定的缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    // 设置一组浮点数来表示颜色
    GLfloat colorRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    // 传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形
    shadermanager.UseStockShader(GLT_SHADER_IDENTITY, colorRed);
    // 提交着色器
    triangleBatch.Draw();
    // 将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();   
}
  • 通过以上的步骤和代码,即可实现一个简单三角形的渲染显示;

完整代码

  • 代码中加了详尽的注释,就不再分步解释;
#include "GLShaderManager.h"
#include "GLTools.h"
#include <GLUT/GLUT.h>

GLShaderManager shadermanager;
GLBatch triangleBatch;


/// 窗口大小改变时接受新的宽度和高度
/// 触发条件: 1.新建窗口  2.窗⼝尺⼨发生调整
/// 处理业务: 1.设置OpenGL 视⼝  2. 设置OpenGL 投影⽅式等
/// @param w 像素
/// @param h 像素
void changeWindowSize(int w, int h) {
    glViewport(0, 0, w, h);
}

void setupRC() {
    
    // 设置背景色
    glClearColor(0.98f, 0.40f, 0.0f, 1.0f);
    // 初始化着色器
    shadermanager.InitializeStockShaders();
    // 设置三角形顶点,其中数组vVerts包含所有3个顶点的x,y,z笛卡尔坐标对
    GLfloat vVerts[] = {-0.5f, 0.0f, 0.0f,
                        0.5f, 0.0f, 0.0f,
                        0.0f, 0.5f, 0.0f};
    // 批次处理,将数据传递到着⾊色器器
    triangleBatch.Begin(GL_TRIANGLES, 3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
    
}


/// 开始渲染(触发条件:1.系统自动触发 2.⼿动调用函数触发)
void renderScene(void) {
    // 清除一个或一组特定的缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    // 设置一组浮点数来表示颜色
    GLfloat colorRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    // 传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形
    shadermanager.UseStockShader(GLT_SHADER_IDENTITY, colorRed);
    // 提交着色器
    triangleBatch.Draw();
    // 将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();
    
}

int main(int argc, char *argv[]) {
    
    // 设置当前工作目录,针对MAC OS X
    gltSetWorkingDirectory(argv[0]);
    
    // 初始化GLUT库
    glutInit(&argc, argv);
    
    /* 初始化双缓冲窗口
     * GLUT_DOUBLE : 双缓冲窗口
     * GLUT_RGBA : RGBA颜色模式
     * GLUT_DEPTH : 深度测试
     * GLUT_STENCIL : 模板缓冲区
     */
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
    
    // GLUT窗口大小,标题窗口
    glutInitWindowSize(400, 200);
    glutCreateWindow("绘制三角形");
    
    // 注册回掉函数
    glutReshapeFunc(changeWindowSize);
    glutDisplayFunc(renderScene);
    
    // 驱动程序的初始化中没有出现问题,确保API完全正常使用
    GLenum statue = glewInit();
    if (GLEW_OK != statue) {
        fprintf(stderr,"glew error:%s\n",glewGetErrorString(statue));
        return 1;
    }
    
    // 设置渲染环境
    setupRC();
    glutMainLoop();
    return 0;
    
}

效果展示

在这里插入图片描述

  • 由于OpenGL的部分API已过时,但不影响使用和实现效果;这里分享一个去除警告的方法:
    在这里插入图片描述
  • 完整代码和具体逻辑传送门:OpenGL之渲染三角形

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/107109927