OpenGL 无法从我的顶点数组中正确读取颜色
OpenGL does not read the colour correctly from my vertex array
使用 OpenGL 着色器,我想在屏幕上绘制一个三角形,其中顶点颜色在数据结构中与顶点坐标一起指定。该结构的每个顶点有 7 个浮点数 -- 3 个用于坐标,然后是 4 个用于颜色:
static std::vector<GLfloat> vertices = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
};
然后我告诉 OpenGL 如何使用 glVertexAttribPointer() 解释这个结构:
// Vertex coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
// Vertex colour
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
然后告诉我的顶点着色器读取坐标和颜色:
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;
但是,无论我对颜色分量使用什么值,三角形总是以红色绘制。更改结构中的坐标会按预期影响图像,但更改结构中的颜色不会有任何效果。
我认为这是我的 C++ 代码的问题,而不是着色器代码的问题,因为我调试了着色器并且它总是读取 (1.0, 0.0, 0.0, 1.0) 颜色,即使我正在为每个顶点传递 (0.0, 0.0, 1.0, 1.0)。
对我做错了什么有什么想法吗?
这是我的完整代码:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <assert.h>
#include <vector>
#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/ext.hpp>
GLuint buffer;
GLuint projection_matrix_location;
GLuint view_matrix_location;
glm::mat4 view_matrix;
glm::mat4 projection_matrix;
int num_vertices = 0;
static void RenderScene()
{
// Clear the buffers.
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
// Set the matrices
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(projection_matrix));
glUniformMatrix4fv(view_matrix_location, 1, GL_FALSE, glm::value_ptr(view_matrix));
// Specify how to read the vertex buffer
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Vertex coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
// Vertex colour
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
// Draw the vertex buffer
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
glDisableVertexAttribArray(0);
// Swap the buffers
glutSwapBuffers();
}
static void MakeBuffers()
{
// Set the vertices
static std::vector<GLfloat> vertices = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
};
num_vertices = (1.0 / 7.0) * vertices.size();
// Fill the buffer with the vertices
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, num_vertices * 7 * sizeof(GL_FLOAT), &vertices[0], GL_STATIC_DRAW);
}
static GLuint MakeShader(GLenum shader_type, std::string shader_filename)
{
// Load the source code
std::ifstream file_in;
file_in.open(&shader_filename[0]);
std::stringstream file_stream;
file_stream << file_in.rdbuf();
std::string file_string = file_stream.str();
const GLchar* ptr_file_string = &file_string[0];
const GLchar** ptr_file_strings = &ptr_file_string;
int string_lengths[] = {(int)file_string.length()};
// Compile the shader
GLuint shader = glCreateShader(shader_type);
glShaderSource(shader, 1, ptr_file_strings, &string_lengths[0]);
glCompileShader(shader);
// Check
GLint is_success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_success);
if (!is_success)
{
std::cerr << "Error" << std::endl;
return -1;
}
return shader;
}
static void MakeShaderProgram()
{
// Make the shaders
GLuint vertex_shader = MakeShader(GL_VERTEX_SHADER, "../src/vertex-shader.glsl");
GLuint fragment_shader = MakeShader(GL_FRAGMENT_SHADER, "../src/fragment-shader.glsl");
// Create the program
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Check
GLint is_success = 0;
glGetProgramiv(program, GL_LINK_STATUS, &is_success);
if (!is_success)
{
std::cout << "Error" << std::endl;
return;
}
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &is_success);
if (!is_success)
{
std::cout << "Error" << std::endl;
return;
}
// Use the program
glUseProgram(program);
// Get the location of the uniform variables
view_matrix_location = glGetUniformLocation(program, "view_matrix");
assert(view_matrix_location != 0xFFFFFFFF);
projection_matrix_location = glGetUniformLocation(program, "projection_matrix");
assert(projection_matrix_location != 0xFFFFFFFF);
}
int main(int argc, char** argv)
{
// Initialize GLUT
glutInit(&argc, argv);
// Configure some GLUT display options:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// Specify the GLUT window parameters and create the window
glutInitWindowSize(1000, 750);
glutInitWindowPosition(500, 200);
glutCreateWindow("Test");
// Specify the display callback
glutDisplayFunc(RenderScene);
// Initialize GLEW, which must be done after GLUT is initialized.
GLenum glut_result = glewInit();
if (glut_result != GLEW_OK)
{
std::cout << "Error" << std::endl;
return -1;
}
// Set the clear colour.
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
// Enable depth testing so that only the nearest vertex is sent to the colour buffer (also needed to read the depth of each pixel using glReadPixels())).
glEnable(GL_DEPTH_TEST);
// Make the vertex and index buffers.
MakeBuffers();
// Make the shader program.
MakeShaderProgram();
// Create the view matrix.
glm::vec3 eye(0.0f, 0.0f, -3.0f);
glm::vec3 centre(0.0f, 0.0f, 0.0f);
glm::vec3 up(0.0f, 1.0f, 0.0f);
view_matrix = glm::lookAt(eye, centre, up);
// Create the projection matrix.
float fov_y = 45.0;
float aspect_ratio = 1.5;
float near_clip = 1;
float far_clip = 1000;
projection_matrix = glm::perspective(fov_y, aspect_ratio, near_clip, far_clip);
// Start the GLUT internal loop.
glutMainLoop();
}
这是我的着色器代码:
// Vertex shader
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
out vec4 frag_colour;
void main()
{
gl_Position = projection_matrix * view_matrix * vec4(position, 1.0f);
frag_colour = vertex_colour;
}
// Fragment shader
#version 330
in vec4 frag_colour;
void main()
{
gl_FragColor = frag_colour;
}
我现在无法调试您的代码,但根据我在这里看到的情况,您忘记启用第二个属性 array.See this example 以供参考。
但即使我错了,我也想指出你在 code.You 中使用的 GL 3.3 中的一些不良做法,good.This 是现代 OpenGL baseline.But 你仍在混合旧的API(pre 3.3)用新的one.From结尾:
在您的片段着色器中,您应该使用自定义输出属性而不是 gl_FragColor 中内置的 GLSL。
#version 330
in smooth vec4 frag_colour;
out vec4 frag_out;
void main()
{
frag_out = frag_colour;
}
现在,关于您的 OpenGL commands.You 不应直接绑定顶点缓冲区,而应使用 VAO 并将其绑定到 context.In 某些驱动程序版本(我在 NVIDIA 上体验过)产生的事实当 VAO 不与核心配置文件一起使用时,根本没有渲染结果。
使用 OpenGL 着色器,我想在屏幕上绘制一个三角形,其中顶点颜色在数据结构中与顶点坐标一起指定。该结构的每个顶点有 7 个浮点数 -- 3 个用于坐标,然后是 4 个用于颜色:
static std::vector<GLfloat> vertices = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
};
然后我告诉 OpenGL 如何使用 glVertexAttribPointer() 解释这个结构:
// Vertex coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
// Vertex colour
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
然后告诉我的顶点着色器读取坐标和颜色:
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;
但是,无论我对颜色分量使用什么值,三角形总是以红色绘制。更改结构中的坐标会按预期影响图像,但更改结构中的颜色不会有任何效果。
我认为这是我的 C++ 代码的问题,而不是着色器代码的问题,因为我调试了着色器并且它总是读取 (1.0, 0.0, 0.0, 1.0) 颜色,即使我正在为每个顶点传递 (0.0, 0.0, 1.0, 1.0)。
对我做错了什么有什么想法吗?
这是我的完整代码:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <assert.h>
#include <vector>
#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/ext.hpp>
GLuint buffer;
GLuint projection_matrix_location;
GLuint view_matrix_location;
glm::mat4 view_matrix;
glm::mat4 projection_matrix;
int num_vertices = 0;
static void RenderScene()
{
// Clear the buffers.
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
// Set the matrices
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(projection_matrix));
glUniformMatrix4fv(view_matrix_location, 1, GL_FALSE, glm::value_ptr(view_matrix));
// Specify how to read the vertex buffer
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Vertex coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
// Vertex colour
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
// Draw the vertex buffer
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
glDisableVertexAttribArray(0);
// Swap the buffers
glutSwapBuffers();
}
static void MakeBuffers()
{
// Set the vertices
static std::vector<GLfloat> vertices = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
};
num_vertices = (1.0 / 7.0) * vertices.size();
// Fill the buffer with the vertices
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, num_vertices * 7 * sizeof(GL_FLOAT), &vertices[0], GL_STATIC_DRAW);
}
static GLuint MakeShader(GLenum shader_type, std::string shader_filename)
{
// Load the source code
std::ifstream file_in;
file_in.open(&shader_filename[0]);
std::stringstream file_stream;
file_stream << file_in.rdbuf();
std::string file_string = file_stream.str();
const GLchar* ptr_file_string = &file_string[0];
const GLchar** ptr_file_strings = &ptr_file_string;
int string_lengths[] = {(int)file_string.length()};
// Compile the shader
GLuint shader = glCreateShader(shader_type);
glShaderSource(shader, 1, ptr_file_strings, &string_lengths[0]);
glCompileShader(shader);
// Check
GLint is_success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_success);
if (!is_success)
{
std::cerr << "Error" << std::endl;
return -1;
}
return shader;
}
static void MakeShaderProgram()
{
// Make the shaders
GLuint vertex_shader = MakeShader(GL_VERTEX_SHADER, "../src/vertex-shader.glsl");
GLuint fragment_shader = MakeShader(GL_FRAGMENT_SHADER, "../src/fragment-shader.glsl");
// Create the program
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Check
GLint is_success = 0;
glGetProgramiv(program, GL_LINK_STATUS, &is_success);
if (!is_success)
{
std::cout << "Error" << std::endl;
return;
}
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &is_success);
if (!is_success)
{
std::cout << "Error" << std::endl;
return;
}
// Use the program
glUseProgram(program);
// Get the location of the uniform variables
view_matrix_location = glGetUniformLocation(program, "view_matrix");
assert(view_matrix_location != 0xFFFFFFFF);
projection_matrix_location = glGetUniformLocation(program, "projection_matrix");
assert(projection_matrix_location != 0xFFFFFFFF);
}
int main(int argc, char** argv)
{
// Initialize GLUT
glutInit(&argc, argv);
// Configure some GLUT display options:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
// Specify the GLUT window parameters and create the window
glutInitWindowSize(1000, 750);
glutInitWindowPosition(500, 200);
glutCreateWindow("Test");
// Specify the display callback
glutDisplayFunc(RenderScene);
// Initialize GLEW, which must be done after GLUT is initialized.
GLenum glut_result = glewInit();
if (glut_result != GLEW_OK)
{
std::cout << "Error" << std::endl;
return -1;
}
// Set the clear colour.
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
// Enable depth testing so that only the nearest vertex is sent to the colour buffer (also needed to read the depth of each pixel using glReadPixels())).
glEnable(GL_DEPTH_TEST);
// Make the vertex and index buffers.
MakeBuffers();
// Make the shader program.
MakeShaderProgram();
// Create the view matrix.
glm::vec3 eye(0.0f, 0.0f, -3.0f);
glm::vec3 centre(0.0f, 0.0f, 0.0f);
glm::vec3 up(0.0f, 1.0f, 0.0f);
view_matrix = glm::lookAt(eye, centre, up);
// Create the projection matrix.
float fov_y = 45.0;
float aspect_ratio = 1.5;
float near_clip = 1;
float far_clip = 1000;
projection_matrix = glm::perspective(fov_y, aspect_ratio, near_clip, far_clip);
// Start the GLUT internal loop.
glutMainLoop();
}
这是我的着色器代码:
// Vertex shader
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
out vec4 frag_colour;
void main()
{
gl_Position = projection_matrix * view_matrix * vec4(position, 1.0f);
frag_colour = vertex_colour;
}
// Fragment shader
#version 330
in vec4 frag_colour;
void main()
{
gl_FragColor = frag_colour;
}
我现在无法调试您的代码,但根据我在这里看到的情况,您忘记启用第二个属性 array.See this example 以供参考。 但即使我错了,我也想指出你在 code.You 中使用的 GL 3.3 中的一些不良做法,good.This 是现代 OpenGL baseline.But 你仍在混合旧的API(pre 3.3)用新的one.From结尾:
在您的片段着色器中,您应该使用自定义输出属性而不是 gl_FragColor 中内置的 GLSL。
#version 330
in smooth vec4 frag_colour;
out vec4 frag_out;
void main()
{
frag_out = frag_colour;
}
现在,关于您的 OpenGL commands.You 不应直接绑定顶点缓冲区,而应使用 VAO 并将其绑定到 context.In 某些驱动程序版本(我在 NVIDIA 上体验过)产生的事实当 VAO 不与核心配置文件一起使用时,根本没有渲染结果。