|
|
@@ -8,7 +8,9 @@
|
|
|
|
|
|
#include "helper.hpp"
|
|
|
|
|
|
+#include <iostream>
|
|
|
#include <memory>
|
|
|
+#include <sstream>
|
|
|
#ifdef __APPLE__
|
|
|
#include <OpenGL/gl3.h>
|
|
|
#endif
|
|
|
@@ -19,6 +21,89 @@
|
|
|
#include "game/util/env.hpp"
|
|
|
#include "game/util/files.hpp"
|
|
|
|
|
|
+namespace {
|
|
|
+ typedef void (*GLGetIntFor)(GLuint, GLenum, GLint *);
|
|
|
+ typedef void (*GLGetLog)(GLuint, GLsizei, GLsizei *, GLchar *);
|
|
|
+ struct opengl_error_formatter {
|
|
|
+ void operator()() const;
|
|
|
+ static void shader_error(GLuint id, std::string const & path);
|
|
|
+
|
|
|
+ GLuint obj;
|
|
|
+ std::string fileName, path, eNoticeMessage, eFileMessage, eWindowTitle;
|
|
|
+ GLGetIntFor getIntv;
|
|
|
+ GLGetLog getInfoLog;
|
|
|
+ };
|
|
|
+
|
|
|
+ void opengl_error_formatter::operator()() const {
|
|
|
+ std::stringstream errorString;
|
|
|
+ std::string errorLineNumber;
|
|
|
+
|
|
|
+ int infologLength = 0;
|
|
|
+ int maxLength = 0;
|
|
|
+
|
|
|
+ getIntv(obj, GL_INFO_LOG_LENGTH, &maxLength);
|
|
|
+ errorString << eNoticeMessage << "\n";
|
|
|
+
|
|
|
+ std::unique_ptr<char[]> infoLog(new char[maxLength + 1]);
|
|
|
+ getInfoLog(obj, maxLength, &infologLength, infoLog.get());
|
|
|
+
|
|
|
+ std::string errorLog(infoLog.get());
|
|
|
+ infoLog.reset();
|
|
|
+ if (infologLength <= 0) return;
|
|
|
+
|
|
|
+ std::size_t openParen = errorLog.find('(');
|
|
|
+ std::size_t closeParen = errorLog.find(')');
|
|
|
+ errorLineNumber =
|
|
|
+ errorLog.substr(openParen + 1, closeParen - openParen - 1);
|
|
|
+
|
|
|
+ errorString << fileName << " , "
|
|
|
+ << "line " << errorLineNumber << ":\n";
|
|
|
+
|
|
|
+ std::string errorStart = errorLog.find("error") != std::string::npos
|
|
|
+ ? errorLog.substr(errorLog.find("error"))
|
|
|
+ : errorLog;
|
|
|
+
|
|
|
+ errorString << errorLog << "\n";
|
|
|
+
|
|
|
+ errorString << "OpenGL Version: " << glGetString(GL_VERSION) << "\n";
|
|
|
+ errorString << "GLSL Shading Version: "
|
|
|
+ << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";
|
|
|
+
|
|
|
+ errorString << eFileMessage << "\n";
|
|
|
+ errorString << "RAW ERROR LOG: " << errorLog;
|
|
|
+
|
|
|
+ std::stringstream consoleOutput;
|
|
|
+
|
|
|
+ consoleOutput << "1>" << path << '(' << errorLineNumber << ')' << ": "
|
|
|
+ << errorStart
|
|
|
+ << "in OpenGL version: " << glGetString(GL_VERSION) << " and "
|
|
|
+ << "GLSL Shading Version: "
|
|
|
+ << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+ OutputDebugStringA(consoleOutput.str().c_str());
|
|
|
+ MessageBoxA(nullptr, errorString.str().c_str(), eWindowTitle.c_str(),
|
|
|
+ MB_OK);
|
|
|
+#else
|
|
|
+ std::cerr << consoleOutput.str() << std::endl;
|
|
|
+ std::cerr << errorString.str() << std::endl;
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ void opengl_error_formatter::shader_error(GLuint id,
|
|
|
+ std::string const & path) {
|
|
|
+ std::string fileName = path.substr(path.find_last_of("/"));
|
|
|
+ opengl_error_formatter{id,
|
|
|
+ fileName,
|
|
|
+ path,
|
|
|
+ "GLSL shader compile error!",
|
|
|
+ "File location" + path,
|
|
|
+ "GLSL Compile Error in " + fileName,
|
|
|
+ glGetShaderiv,
|
|
|
+ glGetShaderInfoLog}();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
namespace graphics { namespace textures {
|
|
|
static int glfmt(format color_fmt) {
|
|
|
switch (color_fmt) {
|
|
|
@@ -97,17 +182,22 @@ namespace graphics { namespace textures {
|
|
|
}}
|
|
|
|
|
|
namespace graphics { namespace shaders {
|
|
|
+ struct file_read_error : std::runtime_error {
|
|
|
+ using std::runtime_error::runtime_error;
|
|
|
+ };
|
|
|
+
|
|
|
+ struct compilation_error : std::runtime_error {
|
|
|
+ using std::runtime_error::runtime_error;
|
|
|
+ };
|
|
|
+
|
|
|
unsigned int init(unsigned int type, std::string const & path) {
|
|
|
unsigned int id;
|
|
|
- int return_code;
|
|
|
-
|
|
|
std::unique_ptr<char const[]> buffer;
|
|
|
|
|
|
// 1. Load the vertex shader code (text file) to a new memory buffer
|
|
|
- if ((buffer = files::load(env::resource_file(path)))) {
|
|
|
- // dbgprintf("Shader file %s could not be opened successfully.\n",
|
|
|
- // path.c_str());
|
|
|
- assert(false);
|
|
|
+ std::string const abs_path = env::resource_file(path);
|
|
|
+ if ((buffer = files::load(abs_path))) {
|
|
|
+ throw file_read_error("Could not load shader file " + abs_path);
|
|
|
}
|
|
|
|
|
|
// 2. Create a new shader ID
|
|
|
@@ -122,11 +212,12 @@ namespace graphics { namespace shaders {
|
|
|
glCompileShader(id);
|
|
|
|
|
|
// 5. Check for compile errors
|
|
|
+ int return_code;
|
|
|
glGetShaderiv(id, GL_COMPILE_STATUS, &return_code);
|
|
|
|
|
|
if (return_code != GL_TRUE) {
|
|
|
- // LogShaderError(id, path);
|
|
|
- // throw shader_instantiation_exception();
|
|
|
+ opengl_error_formatter::shader_error(id, abs_path);
|
|
|
+ throw compilation_error("Could not compile the shader file");
|
|
|
}
|
|
|
return id;
|
|
|
}
|