gpt4 book ai didi

c++ - glReadPixels 始终在 glClearColor 中返回相同的值

转载 作者:太空狗 更新时间:2023-10-29 21:12:41 26 4
gpt4 key购买 nike

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

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

enter image description here

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

#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);

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

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

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

最佳答案

在我的 Debian Stretch box 上运行良好:

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 降为 130 因为 Mesa 在非核心上下文中不支持任何超过 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;
}

关于c++ - glReadPixels 始终在 glClearColor 中返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46610617/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com