【发布时间】:2019-03-04 16:06:02
【问题描述】:
/* 定义类着色器。 */
我正在使用 OpenGL 和 CMake 用 C++ 开发应用程序。我的目录结构是:
- 坦克
- CMakeLists.txt
- ext(包含 GLFW 和高兴)
- 源
- TanX.cpp
- TanX.h
- 数学(包含几种数学方法;与我的问题不太相关)
- 着色器
- Shader.h
- vertex.glsl
- fragment.glsl
- CMakeLists.txt
Shader.h 主要用于从文件中读取顶点和片段着色器源,编译它们并将它们链接到着色器程序。它看起来像这样:
#ifndef _SHADER_H
#define _SHADER_H
#include <string>
#include <exception>
#include <fstream>
#include <glad.h>
class shader_exception :std::exception {
private:
const char* text;
public:
shader_exception(const char* text)
: text(text) {}
virtual const char* what() const {
return text;
}
};
class Shader {
private:
std::string* vertex_source = new std::string();
std::string* fragment_source = new std::string();
unsigned int vao, vbo, vertex_shader, fragment_shader, program;
public:
Shader(const char* vertex_source_path, const char* fragment_source_path) {
std::ifstream file_reader;
file_reader.open(vertex_source_path);
std::string line;
if (file_reader.is_open()) {
while (getline(file_reader, line)) {
vertex_source->append(line + "\n");
}
file_reader.close();
}
else
throw shader_exception("Could not open vertex shader source file");
file_reader.open(fragment_source_path); // this is where I get an unhandled exception dialog box
if (file_reader.is_open()) {
while (getline(file_reader, line)) {
fragment_source->append(line + "\n");
}
file_reader.close();
}
else
throw shader_exception("Could not open fragment shader file");
const char** vertex_source_c = (const char**)malloc(vertex_source->size());
*vertex_source_c = vertex_source->c_str();
const char** fragment_source_c = (const char**)malloc(fragment_source->size());
*fragment_source_c = fragment_source->c_str();
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_source_c, NULL);
glCompileShader(vertex_shader);
int success;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
char infoLog[512];
if (!success) {
glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
throw shader_exception(infoLog);
}
glShaderSource(fragment_shader, 1, fragment_source_c, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog);
throw shader_exception(infoLog);
}
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(program, 512, NULL, infoLog);
throw shader_exception(infoLog);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}
Shader() = delete;
void use()
{
glUseProgram(program);
}
~Shader() {
glDeleteProgram(program);
}
};
#endif
在 TanX.cpp 中,我尝试像这样创建一个 Shader 对象:
Shader shader("vertex.glsl", "fragment.glsl");
如您所见,我想使用的着色器源文件是位于“Shader”文件夹中的 vertex.glsl 和 fragment.glsl。为了使它们可用于 ifstream,Shader 文件夹中的 CMakeLists.txt 文件如下所示(这是here 提到的使文件可用于程序的选项之一):
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vertex.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fragment.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
顶层 CMakeLists.txt 文件还包含
add_subdirectory("TanX/src/Shader")
以便执行Shader中的CMakeLists.txt文件。
问题是,当我尝试在 Visual Studio 中运行我的代码时,我在 Shader.h 文件的第 45 行(它试图打开 fragment.glsl)中得到一个未处理的异常。这是一个shader_exception,所以显然打开vertex.glsl 失败了。 “异常未处理”的详细信息 - 对话框:“TanX.exe 中 0x00007FFF43E4A388 处的未处理异常:Microsoft C++ 异常:内存位置 0x00000028896FF608 处的 shader_exception。发生”。现在我有两个问题
1) 我需要做什么才能让 ifstream 打开 vertex.glsl(然后是 fragment.glsl)?
2) 为什么我什至会得到一个未处理的异常错误,Shader 对象的构造不应该在抛出异常后立即失败,导致程序甚至没有到达第 45 行?
【问题讨论】: