glReadPixels 总是在 glClearColor 中返回相同的值

2024-03-10

我一直在努力理解 glReadPixels 的输出,它在理论上似乎很简单,但实际上产生了令人费解的结果(至少对我来说)。

假设我有一个简单的片段着色器,它绘制一个颜色值为 vec4(0.2, 0, 0, 0) 的三角形,而背景颜色设置为 (0.3, 1.0, 1.0, 0.0),如下所示:

下面是我用来生成上面图像的完整代码(除了着色器构造):

#include "shader.h" // shader compile/link/use 
#include <GLFW\glfw3.h>
#include <iostream>

const int DISPLAY_WIDTH = 16; 
const int DISPLAY_HEIGHT = 16; 

//============= shader code ==========================

const GLchar *vertexShaderSource = R"glsl(#version 440
in vec2 position;
void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
})glsl";

const GLchar *fragmentShaderSource = R"glsl(#version 440
out vec4 outColor;

void main()
{   
    outColor = vec4(0.2,0.,0.,0.);
})glsl";

//============= c++ entry point ==========================

int main(int argc, char** argv) {

    glfwInit();
    GLFWwindow* window = glfwCreateWindow(DISPLAY_WIDTH, DISPLAY_HEIGHT, "test", NULL, NULL);
    glfwMakeContextCurrent(window);

    GLenum res = glewInit();

    // triangle data (xy-position)
    float vertices[] = {
    0.0f, 0.5f, 
    0.5f, -0.5f, 
    -0.5f, -0.5f  
    };

    GLuint vbo;
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // enable vertex xy-position attribute 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    // compile, link and use shader program
    Shader shader(vertexShaderSource, fragmentShaderSource);
    shader.Use();

    // rendering loop
    while (!glfwWindowShouldClose(window)) {

       glClearColor(0.3f, 1.0f, 1.0f, 0.0f);
       glClear(GL_COLOR_BUFFER_BIT);

       glDrawArrays(GL_TRIANGLES, 0, 3);
       glFlush();

       // read pixels from backbuffer 
       GLubyte data[DISPLAY_WIDTH * DISPLAY_HEIGHT];
       glReadPixels(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, GL_RED, GL_UNSIGNED_BYTE, data);

       for (int i = 0; i < DISPLAY_WIDTH * DISPLAY_HEIGHT; i++) {
           int a = data[i]; // implicit conversion of unsigned char to int
           std::cout << a << std::endl;
       }
       std::getchar(); // wait for user input

       glfwSwapBuffers(window);
       glfwPollEvents();
    }

   glfwTerminate(); 
   return 0;
}

请注意,我使用的是默认帧缓冲区,它将把我的颜色值视为标准化有符号整数,并将它们转换为 [0-255] 之间的范围,即我的背景颜色将为 (76, 255, 255, 0 ),而我的几何颜色将为 (51, 0, 0, 0)。

因此,在绘制几何图形并交换缓冲区后,我得到了图像。现在我想读出颜色值。为此,我在交换缓冲区之前插入必要的 glReadPixels 相关代码:

GLubyte* data = new GLubyte[DISPLAY_WIDTH * DISPLAY_HEIGHT];
glReadPixels(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, GL_RED, GL_UNSIGNED_BYTE, data);

为了便于检查从帧缓冲区读出的像素值的过程,我只提取红色通道,因此容纳像素数据所需的数据大小为DISPLAY_WIDTH * DISPLAY_HEIGHT。此外,这意味着我打印出来的值应该是背景颜色的“76”,几何形状的值应该是“51”。

令人惊讶的是,我打印出来的每个红色通道像素数据(所有 DISPLAY_WIDTH * DISPLAY_HEIGHT 像素都被打印)恰好是“76”,就好像几何被忽略一样。请注意,我在绘制调用之后和交换缓冲区之前读取像素。

如果您能让我知道我在这里缺少什么,我将不胜感激。


在我的 Debian Stretch 盒子上运行良好:

GLEW version: 2.0.0
GLFW version: 3.2.1 X11 GLX EGL clock_gettime /dev/js Xf86vm shared
GL_VERSION  : 3.0 Mesa 13.0.6
GL_VENDOR   : Intel Open Source Technology Center
GL_RENDERER : Mesa DRI Intel(R) Kabylake GT2 

76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 51 51 51 51 51 51 51 51 76 76 76 76 
76 76 76 76 76 51 51 51 51 51 51 76 76 76 76 76 
76 76 76 76 76 51 51 51 51 51 51 76 76 76 76 76 
76 76 76 76 76 76 51 51 51 51 76 76 76 76 76 76 
76 76 76 76 76 76 51 51 51 51 76 76 76 76 76 76 
76 76 76 76 76 76 76 51 51 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 51 51 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 
76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76

一起(放弃着色器#version to 130因为 Mesa 在非 Core 环境中不支持 GL 3.0 之后的任何内容):

// g++ main.cpp -lGLEW -lGL -lglfw
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdarg>

struct Program
{
    static GLuint Load( const char* shader, ... )
    {
        GLuint prog = glCreateProgram();
        va_list args;
        va_start( args, shader );
        while( shader )
        {
            const GLenum type = va_arg( args, GLenum );
            AttachShader( prog, type, shader );
            shader = va_arg( args, const char* );
        }
        va_end( args );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( EXIT_FAILURE );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

const GLchar *vertexShaderSource = R"glsl(#version 130
in vec2 position;
void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
})glsl";

const GLchar *fragmentShaderSource = R"glsl(#version 130
out vec4 outColor;

void main()
{   
    outColor = vec4(0.2,0.,0.,0.);
})glsl";


const int DISPLAY_WIDTH = 16; 
const int DISPLAY_HEIGHT = 16; 


int main(int argc, char** argv)
{
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(DISPLAY_WIDTH, DISPLAY_HEIGHT, "test", NULL, NULL);
    glfwMakeContextCurrent(window);

    GLenum res = glewInit();

    std::cout << "GLEW version: " << glewGetString(GLEW_VERSION) << std::endl;
    std::cout << "GLFW version: " << glfwGetVersionString() << std::endl;
    std::cout << "GL_VERSION  : " << glGetString( GL_VERSION ) << std::endl;
    std::cout << "GL_VENDOR   : " << glGetString( GL_VENDOR ) << std::endl;
    std::cout << "GL_RENDERER : " << glGetString( GL_RENDERER ) << std::endl;

    // triangle data (xy-position)
    float vertices[] =
    {
        0.0f, 0.5f, 
        0.5f, -0.5f, 
        -0.5f, -0.5f  
    };

    GLuint vbo;
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // enable vertex xy-position attribute 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    // compile, link and use shader program
    GLuint program = Program::Load
        (
        vertexShaderSource, GL_VERTEX_SHADER,
        fragmentShaderSource, GL_FRAGMENT_SHADER,
        NULL
        );
    glUseProgram( program );

    // rendering loop
    while (!glfwWindowShouldClose(window)) {

    glClearColor(0.3f, 1.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLES, 0, 3);
    glFlush();

    // read pixels from backbuffer 
    GLubyte data[DISPLAY_WIDTH * DISPLAY_HEIGHT];
    glReadPixels(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, GL_RED, GL_UNSIGNED_BYTE, data);

    int i = 0;
    for (int y = 0; y < DISPLAY_HEIGHT; y++)
    {
        for (int x = 0; x < DISPLAY_WIDTH; x++)
        {
            int a = data[i]; // implicit conversion of unsigned char to int
            std::cout << a << " ";;
            i++;
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;

    glfwSwapBuffers(window);
    glfwPollEvents();
    }

    glfwTerminate(); 
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

glReadPixels 总是在 glClearColor 中返回相同的值 的相关文章

  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • python中的Turtle模块未导入[重复]

    这个问题在这里已经有答案了 这是我第一次在 python 中使用turtle模块 但我似乎无法导入它 这是我的代码 from turtle import pen1 Pen pen2 Pen pen1 screen bgcolour 2928
  • 将重复项移动到已排序数组的末尾

    我在一次采访中被问到这个问题 有一个包含重复项的已排序数组 目标是首先返回具有唯一元素的数组 并在最后返回重复的元素并保持顺序 例如 1 1 2 3 4 4 5 应该成为 1 2 3 4 5 1 4 我能够用额外的空间 O n 空间 和线性
  • 在 python3 中使用用户设置的密码进行正确的数据加密

    我一直在寻找合适的数据加密库 用python好久了 今天又需要了 不行 找到任何东西 那么有什么方法可以使用 用户设置的密码 如果我发现一些通常不安全的东西 如果我找到一个好的解决方案 它不支持用户设置密码 这意味着我被困住了 有什么办法吗
  • 在代码片段库中添加代码片段 (Xcode 10)

    最近我在使用的时候Xcode 10 测试版 3 我尝试过了制作一个代码片段并将其添加到代码片段库中 But the 由于代码片段库在 Xcode 10 中分离 因此无法进行拖放 并在我单击代码时隐藏 如何在 Xcode 10 的代码片段库中
  • yocto 中图像版本控制的最佳方法

    在 Yocto 中维护映像版本的最佳方法是什么 我的意思是假设我们构建一个图像并将其提供给客户 将来我们会向客户提供错误修复 我们如何知道客户正在使用哪个版本的 yocto 图像 有没有任何标准方法可以实现这一点 谢谢你的时间 赞赏你的努力
  • 在 for 循环中使用 bash wait [重复]

    这个问题在这里已经有答案了 我已经搜索过并期望以前有人问过这个问题 但找不到类似的问题 尽管有很多类似的问题 我希望这个 for 循环在 3 个不同的线程 进程中运行 并且wait似乎是正确的命令 for file in 1 txt 2 t
  • 我的实体加载速度超慢有什么问题吗?

    我有以下实体 Entity Table name Order public class Order Id SequenceGenerator name order id seq sequenceName order id seq alloc
  • std::tuple 与 std::array 作为 std::vector 的项

    我有这样一个案例 std vector lt 4 integers gt v 什么最适合这里 std tuple解决方案 std vector
  • JIT 编译器在角度更新后不可用

    我已经从 Angular 更新了 Angular 应用程序10到有角度的12 更新开发模式后工作正常 但在生产构建中我得到了 JIT compiler unavailable 错误 我已经进口了 angular compiler 在里面ma
  • xpath 在 div 元素中查找伪元素 ::after 且不带任何内容

    我正在尝试编写 xpath 来查找是否选中了一个复选框 该复选框正在使用 css after 元素进行更改 以下是我拥有的两个元素 div class FormBlock formItem2 and text Scoped In div c
  • 如何在 numpy Python 中启用和禁用 Intel MKL?

    我想测试和比较使用英特尔 MKL 和不使用英特尔 MKL 的 Numpy 矩阵乘法和特征分解性能 我已经使用安装了 MKLpip install mkl Windows 10 64 位 Python 3 8 然后我使用了来自的例子here
  • 范围内的最低值

    我想找到某个范围内的最低值 我每次都必须迭代数组还是有任何动态方法 假设我有输入数组 index 0 1 2 3 4 5 6 7 value 1 4 6 1 6 7 2 3 然后我必须选择范围 包括 中最小的 例如 min 0 7 1 mi
  • 将 MathML 复制到 Word 中以用作方程

    我可以成功地将使用 MS Word 2013 中的插入方程工具创建的方程以 MathML 格式复制到剪贴板 以便在其他地方使用 不过我主要需要导入到Word中 有没有办法将MathML格式的方程导入到word中作为方程使用 您是否刚刚尝试粘
  • 当我将 FusionTablesLayer 与 Google Maps JavaScript API v3 结合使用时出现空白页

    我使用融合表的数据准备了一个简单的页面 FusionTablesLayer 与 Google Maps JavaScript API v3 但不显示地图 您可以在此处查看该页面 http www siterary com 0test htm
  • Xamarin Forms 图像大小不匹配

    我正在使用 Xamarin Forms 实现一个跨平台应用程序 但我遇到了一个奇怪的错误 我正在尝试创建一个带有文本的按钮 为了实现它 我正在使用AbsoluteLayout 我已为每种 iOS 分辨率类型 png 2x png 3x pn
  • System.InvalidCastException:对象无法从 DBNull 转换为其他类型

    我的代码中有一个例外 我已经尝试将 int64 更改为 int32 但这并没有改变它 在数据库中 表示 column ID 的单元格的数据类型为 NUMBER 问题出在这段代码的第 7 行 private void dataGridView
  • 如何将 numpy.array 作为新列添加到 pyspark.SQL DataFrame 中?

    这是创建 pyspark sql DataFrame 的代码 import numpy as np import pandas as pd from pyspark import SparkContext from pyspark sql
  • 如何使 geom_line 和 geom_point 抖动相同的幅度?

    我有一个ggplot2具有显着重叠的两条线的折线图 我正在尝试使用position jitterdodge 这样它们就更明显了 但我无法以相同的方式让线条和点都抖动 我试图仅水平抖动点和线 因为我不想建议 y 轴上的任何更改 这是一个 MW
  • JQuery 选择框和循环帮助

    谢谢阅读 我对 jQuery 有点陌生 我正在尝试制作一个可以包含在我所有网站中的脚本来解决一个总是让我发疯的问题 问题 带有长选项的选择框在 Internet Explorer 中会被截断 例如 这些选择框 http discoverfi
  • glReadPixels 总是在 glClearColor 中返回相同的值

    我一直在努力理解 glReadPixels 的输出 它在理论上似乎很简单 但实际上产生了令人费解的结果 至少对我来说 假设我有一个简单的片段着色器 它绘制一个颜色值为 vec4 0 2 0 0 0 的三角形 而背景颜色设置为 0 3 1 0