OpenGL实战-调试

news2024/12/22 20:35:48

glGetError()

 OpenGL文档,可以查询函数出现的错误的对应原因。
在这里插入图片描述
 默认情况下glGetError只会打印错误数字,如果你不去记忆的话会非常难以理解。通常我们会写一个助手函数来简便地打印出错误字符串以及错误检测函数调用的位置。

GLenum glCheckError_(const char *file, int line)
{
    GLenum errorCode;
    while ((errorCode = glGetError()) != GL_NO_ERROR)
    {
        std::string 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_STACK_OVERFLOW:                error = "STACK_OVERFLOW"; break;
            case GL_STACK_UNDERFLOW:               error = "STACK_UNDERFLOW"; break;
            case GL_OUT_OF_MEMORY:                 error = "OUT_OF_MEMORY"; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
        }
        std::cout << error << " | " << file << " (" << line << ")" << std::endl;
    }
    return errorCode;
}
#define glCheckError() glCheckError_(__FILE__, __LINE__) 

 防止你不知道__FILE__和__LINE__这两个预处理指令(Preprocessor Directive)是什么,它们会在编译的时候被替换成编译时对应的文件与行号。如果我们坚持在代码中使用大量glGetError的调用,这就会让我们更加准确地知道哪个glGetError调用返回了错误(译注:记得glGetError显示的错误会发生在该次调用与上次调用之间,如果间隔太大的话需要检查的地方就太多了)。

调试输出

在这里插入图片描述

GLFW中的调试输出

 在GLFW中请求一个调试输出非常简单,我们只需要传递一个提醒到GLFW中,告诉它我们需要一个调试输出上下文即可。我们需要在调用glfwCreateWindow之前完成这一请求。

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

在这里插入图片描述

    GLint flags;
    glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
    if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
        std::cout << "启用调试上下文成功" << std::endl;
        glEnable(GL_DEBUG_OUTPUT);
        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
        glDebugMessageCallback(glDebugOutput, nullptr);
        glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
    }

在这里插入图片描述

void APIENTRY glDebugOutput(GLenum source, 
                            GLenum type, 
                            GLuint id, 
                            GLenum severity, 
                            GLsizei length, 
                            const GLchar *message, 
                            void *userParam)
{
    // 忽略一些不重要的错误/警告代码
    if(id == 131169 || id == 131185 || id == 131218 || id == 131204) return; 

    std::cout << "---------------" << std::endl;
    std::cout << "Debug message (" << id << "): " <<  message << std::endl;

    switch (source)
    {
        case GL_DEBUG_SOURCE_API:             std::cout << "Source: API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   std::cout << "Source: Window System"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout << "Source: Shader Compiler"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY:     std::cout << "Source: Third Party"; break;
        case GL_DEBUG_SOURCE_APPLICATION:     std::cout << "Source: Application"; break;
        case GL_DEBUG_SOURCE_OTHER:           std::cout << "Source: Other"; break;
    } std::cout << std::endl;

    switch (type)
    {
        case GL_DEBUG_TYPE_ERROR:               std::cout << "Type: Error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout << "Type: Deprecated Behaviour"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  std::cout << "Type: Undefined Behaviour"; break; 
        case GL_DEBUG_TYPE_PORTABILITY:         std::cout << "Type: Portability"; break;
        case GL_DEBUG_TYPE_PERFORMANCE:         std::cout << "Type: Performance"; break;
        case GL_DEBUG_TYPE_MARKER:              std::cout << "Type: Marker"; break;
        case GL_DEBUG_TYPE_PUSH_GROUP:          std::cout << "Type: Push Group"; break;
        case GL_DEBUG_TYPE_POP_GROUP:           std::cout << "Type: Pop Group"; break;
        case GL_DEBUG_TYPE_OTHER:               std::cout << "Type: Other"; break;
    } std::cout << std::endl;

    switch (severity)
    {
        case GL_DEBUG_SEVERITY_HIGH:         std::cout << "Severity: high"; break;
        case GL_DEBUG_SEVERITY_MEDIUM:       std::cout << "Severity: medium"; break;
        case GL_DEBUG_SEVERITY_LOW:          std::cout << "Severity: low"; break;
        case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout << "Severity: notification"; break;
    } std::cout << std::endl;
    std::cout << std::endl;
}

过滤调试输出

在这里插入图片描述

回溯调试错误源

在这里插入图片描述

自定义错误输出

在这里插入图片描述

调试着色器输出

在这里插入图片描述

OpenGL GLSL参考编译器

官方的标准使用OpenGL的GLSL参考编译器(Reference Compiler)来检查。你可以从这里下载所谓的GLSL语言校验器(GLSL Lang Validator)的可执行版本。
在这里插入图片描述
 注意如果没有检测到错误的话则没有输出。它不会显示AMD,NVidia,以及Intel的GLSL编译器之间的细微差别,也不能保证你的着色器完全没有Bug,但它至少能够帮你对着直接的GLSL规范进行检查。
 使用到的cmd命令如下:

  • 切换到D盘 d:
  • 转到某地址目录下 cd /d 地址

帧缓冲输出

在这里插入图片描述
 着色器:

// 顶点着色器
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texCoords;

out vec2 TexCoords;

void main()
{
    gl_Position = vec4(position, 0.0f, 1.0f);
    TexCoords = texCoords;
}

// 片段着色器
#version 330 core
out vec4 FragColor;
in  vec2 TexCoords;

uniform sampler2D fboAttachment;

void main()
{
    FragColor = texture(fboAttachment, TexCoords);
}

 主程序:

void DisplayFramebufferTexture(GLuint textureID)
{
    if(!notInitialized)
    {
        // 在屏幕右上角,使用NDC顶点坐标初始化着色器和VAO
        [...]
    }

    glActiveTexture(GL_TEXTURE0);   
    glUseProgram(shaderDisplayFBOOutput);
        glBindTexture(GL_TEXTURE_2D, textureID);
        glBindVertexArray(vaoDebugTexturedRect);
            glDrawArrays(GL_TRIANGLES, 0, 6);
        glBindVertexArray(0);
    glUseProgram(0);
}

int main()
{
    [...]
    while (!glfwWindowShouldClose(window))
    {
        [...]
        DisplayFramebufferTexture(fboAttachment0);

        glfwSwapBuffers(window);
    }
}

外部调试软件

  • gDebugger
  • RenderDoc
  • CodeXL
  • NVIDIA Nsight
    黑屏原因
    调试输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot——RESTful风格以及如何快速发送不同方式的请求

RESTful风格&#xff1a; 简单来说&#xff0c;RESTful就是一种将请求方式融合到路径中的一种请求路径书写风格&#xff0c;注意这里是风格&#xff0c;不是规定&#xff0c;我们也可以不使用他或者不是非常严格的按照他规定的样式来写&#xff0c;但是由于行业中大多数的人在…

Boost电路的参数设计

本文以实例方式介绍Boost电路的参数设计方法。项目需求&#xff1a;12V升压至50V&#xff0c;功率35W。 先看示例电路图&#xff0c;如下图所示。 在进行具体的参数计算之前&#xff0c;我们先简要的分析一下Boost电路的工作原理。 1、我们假设&#xff0c;C3和C4的容值相对于负…

发挥数据潜能,为在金融服务行业进行创新做好准备

发挥数据潜能&#xff0c;为在金融服务行业进行创新做好准备 为何选择 NetApp 的金融服务&#xff1f; 作为云专家&#xff0c;我们将确保始终适时适地提供财务数据&#xff0c;以推动转型。我们将消除数据孤岛&#xff0c;提供实时的市场就绪分析&#xff0c;借助经验证的 AI…

易基因:多组学关联分析及组学分子实验验证方法(表观组+转录组+微生物组)|干货系列

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 生物过程具有复杂性和整体性&#xff0c;单组学数据难以系统全面解析复杂生理过程的分子调控机制。而多组学&#xff08;Multi-omics&#xff09;联合分析可同时实现从“因”和“果”两个…

Cartographer源码阅读---后端优化思路

Cartographer的后端优化是借用SPA&#xff08;Sparse Pose Adjustment&#xff09;优化算法的思想. 其主要步骤如下: 确定两个节点在global坐标系下的相对位姿变换.通过其它方式再次获取这两个节点的相对位姿变化对这两个相对位姿变换的差的最小二乘问题进行求解进行求解后得到…

nifi DBCPconnectpool 连接oracle 死链接

nifi DBCPconnectpool 连接oracle 死链接 问题展示问题解决后言官网中文网Groovy脚本学习 问题展示 原因&#xff0c;nifi 连接oracle因为网络波动出现死链接&#xff0c;我的数据同步停止于前一天晚上一点半左右&#xff0c;因为最近一致出现这个问题&#xff0c;综合判断之下…

SAP HUM 嵌套HU初探 II (TCODE:POP1, POF1,HU03) <转载>

SAP HUM 嵌套HU初探 II 这里以物料号ZFG0003为例&#xff0c;做一个阐述。 1&#xff0c;维护好包装指令主数据&#xff08;POP1/POP2/POP3&#xff09; 包装指令ZFG0003A 包装指令ZFG0003B 然后维护好PI 确定记录主数据&#xff08;POF1/POF2/POF3&#xff09; 2, COR1/…

老域名挖掘方法-网站老域名批量查询

老域名挖掘方法 老域名对于SEO优化非常重要&#xff0c;可以提高网站的排名和曝光度。因此&#xff0c;很多SEO从业者会使用专门的老域名挖掘工具来挖掘高质量的老域名。以下介绍一种常用且有效的老域名挖掘方法&#xff0c;以及推荐一款优秀的老域名挖掘工具——147SEO老域名…

饿了么在即时零售的胜算

平台商家越多&#xff0c;消费者的选择就会越多&#xff0c;然后就会吸引更多的消费者来消费。与此同时&#xff0c;平台商家越多&#xff0c;平台订单量就会越多&#xff0c;相应的骑手的订单配送响应时效就越快&#xff0c;然后还会吸引更多的商家入驻。如此循环&#xff0c;…

Rust每日一练(leetDay0001) 两数之和、两数相加、最长子串

目录 1. 两数之和 Two Sum &#x1f31f; 2. 两数相加 Add Two Numbers &#x1f31f;&#x1f31f; 3. 无重复字符的最长子串 Longest substring without repeating characters &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练…

如何在Windows11下开启IE浏览器

在Windows11下开启IE浏览器 Microsoft 发布 Windows 11 之后&#xff0c;系统使用基于 Chromium 内核的 Edge 浏览器来代替被人唾骂已久的 IE 浏览器&#xff0c;IE 浏览器入口也已经被屏蔽掉了。通过任何常规方式打开 IE 浏览器都会自动使用 Edge 浏览器打开。 最新消息&…

语音与语言处理技术交流会(深圳)

嘉宾介绍 嘉宾介绍&#xff1a;罗艺&#xff0c;2021年在美国哥伦比亚大学获得博士学位后加入腾讯AI Lab Shenzhen任高级研究员&#xff0c;研究方向主要为音频前端处理&#xff0c;包括但不限于音频分离、单/多通道语音增强等。 报告题目&#xff1a;腾讯AI Lab音频与语音前端…

网站备案:阿里云ICP备案服务码是什么?申请流程来了

阿里云备案服务码是什么&#xff1f;ICP备案服务码怎么获取&#xff1f;阿里云备案服务码分为免费和付费两种&#xff0c;申请备案服务码是有限制条件的&#xff0c;需要你的阿里云账号下有可用于申请备案服务码的云产品&#xff0c;如云服务器、建站产品、虚拟主机等&#xff…

关于扇区、簇、块、页等概念的区分

1、什么是扇区和&#xff08;磁盘&#xff09;块&#xff1f; 物理层面&#xff1a;一个磁盘按层次分为 &#xff1a; 磁盘组合 -> 单个磁盘 -> 某一盘面 &#xff08;platter&#xff09;-> 某一磁道 &#xff08;track&#xff09;-> 某一扇区&#xff08;secto…

未针对内部单位 D 的语言 ZH 定义任何语言特定的单位

在写ABAP程序的时候调用功能函数或者调用BDC的时候会要求输入单位。当我们正常输入单位后调用函数就会报错 提示&#xff1a;未针对内部单位 ** 的语言 ZH 定义任何语言特定的单位。但是我们检查表T006和T006A两个后台表的时候&#xff0c; 发现单位在两个表中都存在&#xff0…

vue通过sync标识符 在子组件中更便捷的修改父组件的值

这里 我们创了一个vue2 项目 根组件 App.vue参考代码如下 <template><div><span>{{ name }}</span><text-data :name "name" /></div> </template><script> import textData from "/components/textData&quo…

python网络爬虫笔记20:批量下载图片并将其转换为pdf文档

对于有些网页,你可以预览所有的页面内容,并且也可以通过F12获取到页面的URL,但是面对动辄几十页的图片,手动下载显然是不可行的。 在这里我们给出一个人机交互的通用解决策略。 第一步:使用F12获取页面所有感兴趣图片的URL 这一步看似简单,其实也暗藏玄机。因为有些网…

Java的继承与组合

继承可以帮助实现类的复用。 所以&#xff0c;很多开发人员在要复用代码时会自然的使用类的继承的方式。 但是&#xff0c;遇到想要复用的场景就直接使用继承&#xff0c;这样做是不对的。长期大量的使用继承会给代码带来很高的维护成本。 本文将介绍一种可以帮助复用的新的…

速锐得解码奔驰Actros 系列网关CAN总线应用车载互联微系统

近年来&#xff0c;改变信号处理方式的低成本高速电子电路和制造技术的进步推动了传感技术的发展。借助这些协同领域内的新发展&#xff0c;传感器和制造商可以采用一套全新的方法&#xff0c;如远程自监控和自校准系统智能化&#xff0c;来提高产品的性能。 类似的&#xff0c…

数据结构与算法lab1-哈工大

title: 数据结构lab1-一元多项式的代数运算 date: 2023-05-16 11:42:26 tags: 数据结构与算法 git地址&#xff1a;https://github.com/944613709/HIT-Data-Structures-and-Algorithms 哈尔滨工业大学计算机科学与技术学院 实验报告 课程名称&#xff1a;数据结构与算法 课…