首页 > 其他分享 >openGL学习笔记(更新ing)

openGL学习笔记(更新ing)

时间:2024-03-31 16:58:38浏览次数:20  
标签:include openGL window 笔记 Application GL GLFW 窗体 ing

本文章暂不介绍GLFW以及GL_GLAD的配置方法。学习赵新政

初识openGL 

#include<iostream>
#include "glad/glad.h"
#include <GLFW/glfw3.h>

//以上是配置好的glad以及glfw 需注意glad需要在glfw上面

接下来看看GLFW官网提供的 Example Code

#include <GLFW/glfw3.h>

int main(void)
{
    //创建窗体对象
    GLFWwindow* window; 
    
    //初始化GLFW
    if (!glfwInit())
        return -1;

    //设置窗体的长和宽 ,以及窗体名字
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        //如果窗体创建失败则进行清理
        glfwTerminate();
        return -1;
    }

    //设置window这个窗体为“绘制舞台”
    glfwMakeContextCurrent(window);

    //执行窗体循环
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        //清理窗口
        glClear(GL_COLOR_BUFFER_BIT);

        //切换双缓存
        glfwSwapBuffers(window);

        //接受并分发窗口消息
        glfwPollEvents();
    }
    
    //清理
    glfwTerminate();
    return 0;
}

在我们使用的时候,会有些许不同,比如初始化我们可以这样写

 glfwInit();//初始化GLFW
//设置GLFW的主版本号和次版本号
 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
 //启动核心模式
 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


//使用glad加载所有opengl函数
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
    std::cout << "Failed to initialize GLAD\n";
    return -1;
}

在原来的基础上加上这些即可

事件响应函数

还记得上一节中窗体循环中的 glfwPollEvents();么。

它就是用来接受并分发窗体信息,检查消息队列是否有需要处理的鼠标,键盘等信息,如果有的话就将消息批量处理清空队列。

//我们需要用到的是这两个函数 需要在窗体循环前设置

//设置监听 事件响应
glfwSetFramebufferSizeCallback(window, frameBufferSizeCallBack);
glfwSetKeyCallback(window, keyCallBack);
//其中第一个参数是窗体对象,第二个参数是函数指针

让我们进入定义,看看我们需要提供什么样的回调函数

这些参数比较简单,除了窗体对象。我们还需要宽 和 高

这些有点难懂,简单了解一下。key:字母按键码,scancode:物理按键码(不重要),action:按下还是抬起,mods:是否有Shift 或者 Ctrl

接下来我们就可以自己写回调函数啦,以下仅供参考。你们可以写自己的

void frameBufferSizeCallBack(GLFWwindow* window, int width, int height)
{
    std::cout << "窗体最新大小:" << width << "," << height << std::endl;
}

void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_W); //是否按下w
    if (action == GLFW_PRESS);// 按压行为
    if (action == GLFW_RELEASE);//松开行为
    if (mods == GLFW_MOD_CONTROL);//control模式
    std::cout << "按下了:" << key << std::endl;
    std::cout << "action:" << action << std::endl;
    std::cout << "mods" << mods << std::endl;
}

效果so COOL

函数初体验

OpenGL的运行环境是一个大的状态机,每个函数都会改变状态机的状态或者使其执行某个行为

glViewport(GLint x, GLint y,GLsizei width, GLsizei height);

设置窗口中OpenGL负责渲染的区域,即视口Viewport 

x,y:表示相对窗口左下角的起始位置. width,height 表示渲染区域的长度,高度

glClearColor(GLfloat red,GLfloat green, GLfloat blue, GLfloat alpha);

设置画布清理的颜色

glClear(GL_COLOR_BUFFER_BIT); 

执行画布清理工作

双缓冲:DoubleBuffer

如果直接在一张画板上绘制每一帧,就会“露馅”

双缓冲技术,在每一帧绘制任务完成后,需要把“幕后”的画布放到台前,把台前的撤到“幕后”

void glfwSwapBuffers(GLFWwindow* window);

//设置opengl视口以及清理颜色
glViewport(0, 0, 400, 600);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
//窗体循环中  切换双缓存
glfwSwapBuffers(window);

错误检查与封装

如果我们不小心写错了某个参数会怎么样?比如glClear(-1)

opengl 不会因为参数错误轻易崩溃,但错误也更难查找!OpenGL提供了错误检查函数

GLenum glGetError(); 用于检查之前的调用是否发生了问题,如果有问题则返回最近一个问题的错误码

所以我们可以根据这一特性,将其封装成CheckError文件

// 这里是头文件
#pragma once
#include<iostream>
#include <glad/glad.h>
#include<string>
#include<assert.h>

#define DEBUG
//预编译宏定义
#ifdef DEBUG
#define GL_CALL(func) func;checkError();
#else
#define GL_CALL(func) func;
#endif

void checkError();

这里的define DEBUG是为了方便是否启用检查,否则在发布时我们还得一个个删除GL_CALL

// checkError.cpp
#include "checkError.h"

void checkError() {
    GLenum errorCode = glGetError();
    std::string error = "";
    if (errorCode != GL_NO_ERROR) {
        switch (errorCode)
        {
        case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
        case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
        case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
        case GL_OUT_OF_MEMORY: error = "OUT OF MEMORY"; break;
        default:
            error = "UNKNOWN";
            break;
        }
        std::cout << error << "\n";

        //assert会根据传入的bool值来决定程序是否停止
        assert(false);
    }
}

这里列举了常见的四种错误,ENUM,VALUE,OPERATION,MEMORY. 封装好之后我们就可以给每条语句套上,例如GL_CALL(glClear(-1) );

Application类设计

OpenGL的绘制代码会很长,所以需要做必要的封装,让代码优雅整洁

所以我们需要封装一个Application类,将窗体相关代码锁在里面,并且暴露必要的接口。

思路:3D程序都是帧循环驱动,每个对象都应该先初始化(initial),之后的每一帧更新数据或处理事件(update),退出前打扫战场(destroy)。

单例类

这里简单介绍一下单例模式。

单例模式是一种设计模式,用于确保类只有一个实例,并提供一个全局访问点。在许多情况下,单例类被用来管理全局状态或提供全局访问点。

#include <iostream>

class Singleton {
public:
    // 公共静态方法,用于获取单例实例
    static Singleton& getInstance() {
        // 使用静态局部变量确保只创建一个实例
        static Singleton instance;
        return instance;
    }

    // 防止复制构造函数
    Singleton(Singleton const&) = delete;
    void operator=(Singleton const&) = delete;

    // 其他公共方法和成员变量可以在这里添加
    void doSomething() {
        std::cout << "Singleton is doing something." << std::endl;
    }

private:
    // 私有构造函数,防止外部实例化
    Singleton() {}
};

int main() {
    // 获取单例实例
    Singleton& singleton = Singleton::getInstance();

    // 调用单例方法
    singleton.doSomething();

    return 0;
}

因此我们可以模仿上面的单例类实现Application类的封装。

#pragma once

#include<iostream>
#include <GLFW/glfw3.h>

#define app Application::getInstance()

class Application
{
public:
	static Application* mInstance; //一定要放在private里面吗
    //可以放在getInstance内部
	~Application();
	static Application* getInstance();
	//访问实例的静态函数
}
private:
	Application();

	GLFWwindow* mWindow = nullptr;

};

cpp文件

#include"checkError.h"
#include"Application.h"

Application* Application::mInstance = nullptr;

Application* Application::getInstance() {
	// 如果mInstance 已经实例化了,就直接返回 
	//否则先new出来 再返回
	if (mInstance == nullptr) {
		mInstance = new Application();
	}
	return mInstance;
}

Application::Application() {

}

Application::~Application() {

}

最后 我们可以在源文件中#include"Application.h" 并且#define app Application::getInstance()可以用来简化语句。我们就可以像app-> xxx 来访问类了。

成员变量与成员函数设计

成员变量思路,要有描述窗体长,宽。还要存储当前窗体对象。

mWidth, mHeight.  mWindow 

对外接口设计 init 负责初始化当前对象的各类参数。1,设置初始信息。2、生成窗体。3、载入OpenGL函数。

update负责每一帧更新信息或者执行工作。1、更新双缓冲。2、接受并分发窗体消息

destroy负责退出前打扫战场。执行glfwTerminate 退出gl环境

在头文件中添加这些即可,并在private: 中添加mWidth, mHeight. 

先写init函数 将初始化的部分封装到init函数中(前面有展示)

bool Application::init(const int& Width,const int& Height) {
	mWidth = Width; mHeight = Height;
	glfwInit();

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);

	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGLStudy", NULL, NULL);

	if (mWindow == NULL) {
		return false;
	}
	glfwMakeContextCurrent(mWindow);
    
//也可以把加载glad 放进来,但是需要在Application中 #include<glad/glad.h>
	return true;
}

标签:include,openGL,window,笔记,Application,GL,GLFW,窗体,ing
From: https://blog.csdn.net/qq_66236459/article/details/137180664

相关文章

  • Minio 笔记
    一、安装minio#安装方式or直接下二进制执行文件chomod+xminio运行sudowgethttps://dl.min.io/server/minio/release/linux-amd64/archive/minio-20240326221045.0.0-1.x86_64.rpm-Ominio.rpmsudodnfinstallminio.rpm#mkdir/usr/miniodata文件夹#启动一#......
  • 目前国内全地形能力最强的双足机器人 —— 逐际动力 —— 提出迭代式预训练(Iterative
    相关:https://weibo.com/1255595687/O5k4Aj8l2该公司对其产品的强化学习训练算法给出了较少的描述:提出迭代式预训练(IterativePre-training)方法,把通用机器人的基础运动能力划分为不同级别,进行循序渐进的预训练,这个过程让训练的结果更可控,从而高效地产出和收集有效数据,训练......
  • 基于Springboot框架高校学校自习室教室座位预约系统设计与实现(安装部署+源码+文档)
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书、P......
  • Fiddler系列课程笔记(三): HTTPS及安卓&iOS设备APP抓包
    Fiddler系列课程笔记(三):HTTPS及安卓&iOS设备APP抓包1.HTTPS抓包1.1什么是HTTPS?HTTPS(全称:HyperTextTransferProtocoloverSecureSocketLayer),HTTPS协议是由HTTP加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技......
  • [附源码]计算机毕业设计电影播放器开发与设计(JSP+java+springmvc+mysql+MyBatis)
    本项目包含程序+源码+数据库+LW+调试部署环境,文末可获取一份本项目的java源码和数据库参考。项目文件图项目介绍随着数字媒体技术的发展,电影播放器已成为人们日常生活中不可或缺的娱乐工具。一个功能丰富的电影播放器不仅需要支持各种视频格式、提供高清流畅的播放体验,还应......
  • [附源码]计算机毕业设计在线直播管理系统(JSP+java+springmvc+mysql+MyBatis)
    本项目包含程序+源码+数据库+LW+调试部署环境,文末可获取一份本项目的java源码和数据库参考。项目文件图项目介绍在线直播管理系统,帮我写150字的选题背景的内容随着互联网技术的飞速发展,在线直播已成为新兴的媒体传播方式,尤其在娱乐、教育、电商等领域得到广泛应用。一个高......
  • [附源码]计算机毕业设计基于ssm的会议室预约系统(JSP+java+springmvc+mysql+MyBatis)
    本项目包含程序+源码+数据库+LW+调试部署环境,文末可获取一份本项目的java源码和数据库参考。项目文件图项目介绍基于SSM(Spring,SpringMVC,MyBatis)框架的会议室预约系统,旨在通过现代化的信息技术手段解决企业和机构中会议室资源分配和使用的问题。随着企业规模的扩大和办......
  • [附源码]计算机毕业设计高校多媒体教室预约系统(JSP+java+springmvc+mysql+MyBatis)
    本项目包含程序+源码+数据库+LW+调试部署环境,文末可获取一份本项目的java源码和数据库参考。项目文件图项目介绍随着信息技术在教育领域的广泛应用,多媒体教室成为高校教学资源的重要组成部分。合理高效的预约管理系统对于充分利用多媒体教室资源、提高教学质量和效率具有显......
  • 9.折磨了一周的springboot样式跳转
    大致是这样的springboot一个项目将头部和侧部公共部分都提取出来但是一点击员工怎么侧边样式一直失败我看F12报错说的什么cavas渲染加上了还是错啊因为我是侧边栏的问题我的Controller跳转肯定没错这个真是让我难受了一周多因为还差增删改查就设计完毕了这个坑一......
  • Fiddler系列课程笔记(二):Fiddler工具详解及应用实战
    Fiddler系列课程笔记(二):Fiddler工具详解及应用实战1.Fiddler的安装2.Fiddler的组成部分2.1Fiddler的菜单栏2.1.1Hide:隐藏掉一些不必要的请求资源的数据展示2.1.2Fiddler修改端口2.1.3Fiddler快速打开IE设置2.2Fiddler的工具条工具栏快捷按钮介绍:2.2.1[......