我写完了第一个 OpenGL 代码,虽然在使用包含红色三角形的较小输入缓冲区时它似乎可以正常工作,但在使用较大的输入缓冲区时它根本不起作用。下面的缓冲区仅显示 RED 通道,因此每个都00对应于00 00 00,并且每个FF对应于FF 00 00。
下面也是我的整个 OpenGL 代码。我不知道可能出了什么问题,然后最好分享一切。
调用main时Screen::initialize为窗口宽度和高度传递 500 和 500,然后Screen::display_image在使用小缓冲区时为图像宽度和高度调用传递 12,在使用较大缓冲区时调用传递 23。
知道我做错了什么吗?
小缓冲区
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 FF FF FF FF FF 00
00 00 00 00 00 00 FF FF FF FF 00 00
00 00 00 00 00 00 FF FF FF 00 00 00
00 00 00 00 00 00 FF FF 00 00 00 00
00 00 00 00 00 00 FF 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)
大缓冲区
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <GLFW/glfw3.h>
#include <stdint.h>
#include <string>
namespace Screen
{
class Screen
{
public:
Screen(){};
~Screen(){};
bool initialize(uint32_t ScreenWidth, uint32_t ScreenHeight, std::string& Title);
void display_image(uint8_t* ImageData, uint32_t ImageWidth, uint32_t ImageHeight);
void deinitialize();
private:
GLFWwindow* _window = nullptr;
uint32_t _shader_program = 0u;
uint32_t _object_vertex_array = 0u;
uint32_t _object_vertex_buffer = 0u;
uint32_t _object_element_buffer = 0u;
uint8_t* _image_data = nullptr;
};
}
#endif // _SCREEN_H_
Run Code Online (Sandbox Code Playgroud)
#include <GL/glew.h>
#include <stdint.h>
#include <string>
#include "Screen.h"
namespace Screen
{
namespace
{
bool build_shader_vertex(uint32_t& ShaderVertex)
{
const char* source_shader_vertex =
"#version 330 core\n"
"layout (location = 0) in vec4 input_position;\n"
"layout (location = 1) in vec2 input_texture;\n"
"out vec2 output_texture;\n"
"void main()\n"
"{\n"
"gl_Position = input_position;\n"
"output_texture = input_texture;\n"
"}\n"
"\0";
ShaderVertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(ShaderVertex, 1, &source_shader_vertex, NULL);
glCompileShader(ShaderVertex);
GLint success = 0;
glGetShaderiv(ShaderVertex, GL_COMPILE_STATUS, &success);
if (!success)
{
fprintf(stderr, "%s:%d:%s: Failed to compile vertex shader\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
return true;
}
bool build_shader_fragment(uint32_t& ShaderFragment)
{
const char* source_shader_fragment =
"#version 330 core\n"
"out vec4 fragment_color;\n"
"in vec2 output_texture;\n"
"uniform sampler2D sampled_texture;\n"
"void main()\n"
"{\n"
"fragment_color = texture(sampled_texture, output_texture);\n"
"}\n"
"\0";
ShaderFragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(ShaderFragment, 1, &source_shader_fragment, NULL);
glCompileShader(ShaderFragment);
GLint success = 0;
glGetShaderiv(ShaderFragment, GL_COMPILE_STATUS, &success);
if (!success)
{
fprintf(stderr, "%s:%d:%s: Failed to compile fragment shader\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
return true;
}
bool build_program(uint32_t& ShaderProgram)
{
bool ret_val = true;
uint32_t shader_vertex = 0u;
uint32_t shader_fragment = 0u;
GLint success = 0;
if (!build_shader_vertex(shader_vertex))
{
fprintf(stderr, "%s:%d:%s: Failed to build shader\n", __FILE__, __LINE__, __FUNCTION__);
ret_val = false;
goto terminate;
}
if (!build_shader_fragment(shader_fragment))
{
fprintf(stderr, "%s:%d:%s: Failed to build shader\n", __FILE__, __LINE__, __FUNCTION__);
ret_val = false;
goto terminate;
}
ShaderProgram = glCreateProgram();
glAttachShader(ShaderProgram, shader_vertex);
glAttachShader(ShaderProgram, shader_fragment);
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
fprintf(stderr, "%s:%d:%s: Failed to link shader program\n", __FILE__, __LINE__, __FUNCTION__);
ret_val = false;
goto terminate;
}
terminate:
glDeleteShader(shader_vertex);
glDeleteShader(shader_fragment);
return ret_val;
}
}
bool Screen::initialize(uint32_t ScreenWidth, uint32_t ScreenHeight, std::string& Title)
{
constexpr int32_t major_number = 3;
constexpr int32_t minor_number = 3;
uint32_t shader_program = 0u;
if (glfwInit() != GLFW_TRUE)
{
fprintf(stderr, "%s:%d:%s: Failed to initialize GLFW\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major_number);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor_number);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
_window = glfwCreateWindow(ScreenWidth, ScreenHeight, Title.c_str(), NULL, NULL);
if (!_window)
{
fprintf(stderr, "%s:%d:%s: Failed to create window\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
glfwMakeContextCurrent(_window);
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "%s:%d:%s: Failed to initialize GLEW\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
if (!build_program(shader_program))
{
fprintf(stderr, "%s:%d:%s: Failed to initialize GLEW\n", __FILE__, __LINE__, __FUNCTION__);
return false;
}
float vertices[] =
{
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
};
unsigned int indices[] =
{
0, 1, 3,
1, 2, 3,
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(4 * sizeof(float)));
glEnableVertexAttribArray(1);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUseProgram(shader_program);
return true;
}
void Screen::display_image(uint8_t* ImageData, uint32_t ImageWidth, uint32_t ImageHeight)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ImageWidth, ImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, ImageData);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(_window);
glfwPollEvents();
}
void Screen::deinitialize()
{
if (_image_data)
{
delete[] _image_data;
}
glDeleteVertexArrays(1, &_object_vertex_array);
glDeleteBuffers (1, &_object_vertex_buffer);
glDeleteBuffers (1, &_object_element_buffer);
_image_data = nullptr;
glfwTerminate();
}
}
Run Code Online (Sandbox Code Playgroud)
GL_UNPACK_ALIGNMENT
指定内存中每个像素行开头的对齐要求。允许的值为 1(字节对齐)、2(行与偶数字节对齐)、4(字对齐)和 8(行从双字边界开始)。
在 OpenGL 4.6 中,该值默认为 4(请参阅特定页面上的表)。
小图像的行长度是 4 的倍数,但大图像的行长度不是 4 的倍数,因此会失真。
根据您的情况,添加行
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //byte-alignment
Run Code Online (Sandbox Code Playgroud)
在上传图像数据(glTexImage2D)之前,这应该可以解决问题。
为了更好地理解,请阅读OpenGL 规范的第8 章纹理和采样器(至少 8.4 和 8.5)。
| 归档时间: |
|
| 查看次数: |
62 次 |
| 最近记录: |