我一直在关注YouTube上关于使用OpenGL的教程,并将其整合到现有的项目中。当我将着色器源代码声明为硬编码的c字符串时,一切都正确绘制,但当我看到this视频将着色器抽象到自己的类和文件中时,我突然只得到白色三角形。我不知道我做错了什么,因为我复制粘贴到一个文本文件的确切着色器代码。
我使用上面来自this博客的视频中建议的代码来读取文件:
#include <fstream>
#include <string>
#include <cerrno>
std::string get_file_contents(const char *filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::string contents;
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return(contents);
}
throw(errno);
}
字符串
我在编译、链接或阅读着色器文件时没有错误,所以我很困惑。我已经在这里研究了一些类似的问题,所有的答案要么不适合我的用法,要么不能解决这个问题。下面列出了着色器文件以及我如何使用着色器。我很感激你能给予我的任何帮助!<3
default.vert
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 col;
out vec4 vertColor;
void main()
{
gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
vertColor = vec4(col.x, col.y, col.z, 1.0);
}
型
default.frag
#version 330 core
in vec4 vertColor;
out vec4 FragColor;
void main()
{
FragColor = vertColor;
}
型
shader.h
#include "gl/glew.h"
class Shader {
public:
GLuint ID;
Shader(const char*, const char*);
~Shader();
void activate();
void deactivate();
};
型
shader.cpp
#include "shader.h"
#include "gl/glew.h"
#include "GLFW/glfw3.h"
#include <fstream>
#include <string>
#include <cerrno>
std::string get_file_contents(const char* filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::string contents;
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return(contents);
}
throw(errno);
}
Shader::Shader(const char* vertexFilename, const char* fragmentFilename) {
// read in the shader files
std::string vertexSourceString = get_file_contents(vertexFilename);
std::string fragmentSourceString = get_file_contents(fragmentFilename);
const char* vertexSource = vertexSourceString.c_str();
const char* fragmentSource = fragmentSourceString.c_str();
// create vertex shader
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
// create fragment shader
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
// link shaders together
ID = glCreateProgram();
glAttachShader(ID, vertexShader);
glAttachShader(ID, fragmentShader);
glLinkProgram(ID);
// cleanup
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
Shader::~Shader() {
glDeleteProgram(ID);
}
void Shader::activate() {
glUseProgram(ID);
}
void Shader::deactivate() {
glUseProgram(0);
}
型
在main.cpp中
const char* defaultVertexShaderSource = "../../../res/shaders/default.vert";
const char* defaultFragmentShaderSource = "../../../res/shaders/default.frag";
Shader defaultShader = Shader(defaultVertexShaderSource, defaultFragmentShaderSource);
型
然后,我通过渲染函数传递这个着色器对象,在那里它被用来绘制代表棋盘上空间的正方形。着色器的使用方式如下:
shader.activate();
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, vertex_buffer_data.size() / 2);
shader.deactivate();
型
Edit:Per Botje's comment:下面是完整的图形管道代码:
GLuint vertex_buffer, vertex_array;
glGenVertexArrays(1, &vertex_array);
glGenBuffers(1, &vertex_buffer);
std::vector<float> vertex_buffer_data;
glm::vec3 top_right_corner = top_left_corner + square_top_right_offset;
glm::vec3 bottom_left_corner = top_left_corner + square_bottom_left_offset;
glm::vec3 bottom_right_corner = top_left_corner + square_bottom_right_offset;
glm::vec3 color = (is_black) ? BLACK_SQUARE_COLOR : WHITE_SQUARE_COLOR;
std::vector<glm::vec3*> vertices = {&top_left_corner, &top_right_corner, &bottom_left_corner, &top_right_corner, &bottom_left_corner, &bottom_right_corner};
for (auto vertex : vertices) {
vertex_buffer_data.push_back(vertex->x);
vertex_buffer_data.push_back(vertex->y);
vertex_buffer_data.push_back(vertex->z);
vertex_buffer_data.push_back(color.x);
vertex_buffer_data.push_back(color.y);
vertex_buffer_data.push_back(color.z);
}
glBindVertexArray(vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data.size() * sizeof(float), vertex_buffer_data.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
shader.activate();
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, vertex_buffer_data.size() / 2);
shader.deactivate();
glBindVertexArray(0);
glDeleteVertexArrays(1, &vertex_array);
glDeleteBuffers(1, &vertex_buffer);
型
1条答案
按热度按时间yftpprvb1#
正如Botje指出的那样,问题在于着色器初始化在使用之前就被删除了。通过将着色器声明为堆变量,程序可以按预期工作。