|
From: Tapio V. <aa...@us...> - 2010-11-02 12:08:19
|
Module: performous
Branch: opengl2
Commit: 14be9cd9ff0485dd9c60147e27f38ddb5ab155b9
Author: Tapio Vierros <tap...@gm...>
Date: Tue Nov 2 13:59:00 2010 +0200
Shaders are now loaded from files and much more error reporting.
---
game/glshader.cc | 100 +++++++++++++++++++++++++++++++++-----
game/glshader.hh | 12 ++++-
game/glutil.hh | 1 +
game/video_driver.cc | 37 ++------------
themes/CMakeLists.txt | 4 +-
themes/default/shaders/core.frag | 19 +++++++
themes/default/shaders/core.vert | 7 +++
7 files changed, 132 insertions(+), 48 deletions(-)
diff --git a/game/glshader.cc b/game/glshader.cc
index e0e0bd9..693e253 100644
--- a/game/glshader.cc
+++ b/game/glshader.cc
@@ -1,32 +1,108 @@
#include "glshader.hh"
#include "glutil.hh"
-Shader::Shader(const char* vertex_shader, const char* fragment_shader) {
+#include <fstream>
+#include <stdexcept>
+
+
+namespace {
+ /// Loads a file into memory
+ std::string loadFile(const std::string& filepath) {
+ std::ifstream f(filepath.c_str(), std::ios::binary);
+ if (!f.is_open()) throw std::runtime_error(std::string("Couldn't open ") + filepath);
+ f.seekg(0, std::ios::end);
+ size_t size = f.tellg();
+ f.seekg(0);
+ std::vector<char> data(size+1); // +1 for terminating null
+ if (!f.read(&data[0], size)) throw std::runtime_error(std::string("Unexpected I/O error in ") + filepath);
+ data.back() = '\0';
+ return std::string(&data[0]);
+ }
+
+ /// Dumps Shader/Program InfoLog
+ void dumpInfoLog(GLuint id) {
+ int infologLength = 0;
+ int maxLength;
+
+ if (glIsShader(id)) glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
+ else glGetProgramiv(id, GL_INFO_LOG_LENGTH, &maxLength);
+
+ char infoLog[maxLength];
+
+ if (glIsShader(id)) glGetShaderInfoLog(id, maxLength, &infologLength, infoLog);
+ else glGetProgramInfoLog(id, maxLength, &infologLength, infoLog);
+
+ if (infologLength > 0) {
+ std::cout << std::endl << "Shader info log:" << std::endl;
+ std::cout << infoLog << std::endl;
+ }
+ }
+}
+
+
+Shader::Shader(): program(), vert_shader(), frag_shader() {}
+
+Shader::Shader(const std::string& vert_path, const std::string& frag_path, bool use) {
+ loadFromFile(vert_path, frag_path, use);
+}
+
+
+Shader::~Shader() {
+ glDeleteProgram(program);
+ glDeleteShader(vert_shader);
+ glDeleteShader(frag_shader);
+}
+
+
+void Shader::loadFromFile(const std::string& vert_path, const std::string& frag_path, bool use) {
+ std::string vertstr = loadFile(vert_path);
+ std::string fragstr = loadFile(frag_path);
+ const char* vert = vertstr.c_str();
+ const char* frag = fragstr.c_str();
+ loadFromMemory(vert, frag, use);
+}
+
+
+void Shader::loadFromMemory(const char* vert_source, const char* frag_source, bool use) {
+ glutil::GLErrorChecker::reset();
vert_shader = glCreateShader(GL_VERTEX_SHADER);
frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
+ glutil::GLErrorChecker shadererror("Shader::loadFromMemory - glCreateShader");
- glShaderSource(vert_shader, 1, &vertex_shader, NULL);
- glShaderSource(frag_shader, 1, &fragment_shader, NULL);
+ glShaderSource(vert_shader, 1, &vert_source, NULL);
+ glShaderSource(frag_shader, 1, &frag_source, NULL);
+ glutil::GLErrorChecker shadersourceerror("Shader::loadFromMemory - glShaderSource");
glCompileShader(vert_shader);
- glGetShaderiv(vert_shader,GL_COMPILE_STATUS, &gl_response);
- if (gl_response != GL_TRUE) std::cerr << "Something went wrong compiling the vertex shader." << std::endl;
+ glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &gl_response);
+ if (gl_response != GL_TRUE) {
+ dumpInfoLog(vert_shader);
+ throw std::runtime_error("Something went wrong compiling the vertex shader.");
+ }
glCompileShader(frag_shader);
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &gl_response);
- if (gl_response != GL_TRUE) std::cerr << "Something went wrong compiling the fragment shader." << std::endl;
+ if (gl_response != GL_TRUE) {
+ dumpInfoLog(frag_shader);
+ throw std::runtime_error("Something went wrong compiling the fragment shader.");
+ }
+ glutil::GLErrorChecker::reset();
program = glCreateProgram();
+ glutil::GLErrorChecker createprogramerror("Shader::loadFromMemory - glCreateProgram");
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
+ glutil::GLErrorChecker attachshadererror("Shader::loadFromMemory - glAttachShader");
glLinkProgram(program);
- glUseProgram(program);
-}
+ glGetProgramiv(program, GL_LINK_STATUS, &gl_response);
+ if (gl_response != GL_TRUE) {
+ dumpInfoLog(program);
+ throw std::runtime_error("Something went wrong linking shader program.");
+ }
+ glutil::GLErrorChecker linkerror("Shader::loadFromMemory - glLinkProgram");
-Shader::~Shader() {
- glDeleteProgram(program);
- glDeleteShader(vert_shader);
- glDeleteShader(frag_shader);
+ if (use) bind();
+ glutil::GLErrorChecker glerror("Shader::loadFromMemory - bind");
}
diff --git a/game/glshader.hh b/game/glshader.hh
index 24b2668..016c601 100644
--- a/game/glshader.hh
+++ b/game/glshader.hh
@@ -4,10 +4,18 @@
#include <GL/glew.h>
struct Shader {
- Shader(const char* vertex_shader, const char* fragment_shader);
- Shader() {};
+ Shader();
+ Shader(const std::string& vert_path, const std::string& frag_path, bool use = true);
~Shader();
+ /** Loads the shader from files. */
+ void loadFromFile(const std::string& vert_path, const std::string& frag_path, bool use = true);
+ /** Loads the shader from memory. */
+ void loadFromMemory(const char* vert_source, const char* frag_source, bool use = true);
+
+ /** Binds the shader into use. */
+ void bind() { glUseProgram(program); }
+
GLuint program, vert_shader, frag_shader;
int gl_response;
};
diff --git a/game/glutil.hh b/game/glutil.hh
index 58ae55f..44a2837 100644
--- a/game/glutil.hh
+++ b/game/glutil.hh
@@ -218,6 +218,7 @@ namespace glutil {
}
}
}
+ static void reset() { glGetError(); }
};
}
diff --git a/game/video_driver.cc b/game/video_driver.cc
index 63c193c..2cfd88d 100644
--- a/game/video_driver.cc
+++ b/game/video_driver.cc
@@ -31,37 +31,6 @@ namespace {
int m_value;
};
- // FIXME: In general, shaders should be loaded from theme files.
- // Does that apply to these core shaders too?
-
- const char *vertex_glsl =
- "void main()"
- "{"
- " gl_FrontColor = gl_Color;"
- " gl_BackColor = gl_Color;"
- " gl_TexCoord[0] = gl_MultiTexCoord0;"
- " gl_Position = ftransform();"
- "}\000";
-
- const char *fragment_glsl =
- "uniform int texMode;"
- "uniform sampler2D tex;"
- "uniform sampler2DRect texrect;"
- "void main()"
- "{"
- " vec4 texel;"
- " vec4 color;"
- " if (texMode == 1) {"
- " texel = texture2D(tex,gl_TexCoord[0].st).rgba;"
- " } else if (texMode == 2) {"
- " texel = texture(texrect,gl_TexCoord[0].st).rgba;"
- " } else if (texMode == 0) {"
- " texel = gl_Color;"
- " } else {"
- " texel = vec4(1.0,0.0,0.0,1.0);"
- " }"
- " gl_FragColor = vec4(texel.rgb*gl_Color.rgb,texel.a*gl_Color.a);"
- "}\000";
}
unsigned int screenW() { return s_width; }
@@ -90,9 +59,11 @@ Window::Window(unsigned int width, unsigned int height, bool fs): m_windowW(widt
std::clog << "video/info: GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
std::clog << "video/info: GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
std::clog << "video/info: GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
- std::clog << "video/info: GL_EXTENSIONS: " << glGetString(GL_EXTENSIONS) << std::endl;
+ std::clog << "video/info: GL_EXTENSIONS: " << glGetString(GL_EXTENSIONS) << std::endl;
+ // Joystick etc. initialization
input::SDL::init();
- shader = Shader(vertex_glsl, fragment_glsl);
+ // Shaders
+ shader = Shader(getThemePath("shaders/core.vert"), getThemePath("shaders/core.frag"));
}
Window::~Window() { }
diff --git a/themes/CMakeLists.txt b/themes/CMakeLists.txt
index 5636f21..800a5f9 100644
--- a/themes/CMakeLists.txt
+++ b/themes/CMakeLists.txt
@@ -1,4 +1,6 @@
FILE(GLOB THEME_FILES "default/*.ogg" "default/*.svg" "default/*.png" "default/*.bmp" "default/*.obj")
+install(FILES ${THEME_FILES} DESTINATION ${SHARE_INSTALL}/themes/default/)
-install( FILES ${THEME_FILES} DESTINATION ${SHARE_INSTALL}/themes/default/)
+FILE(GLOB SHADER_FILES "default/shaders/*.vert" "default/shaders/*.frag")
+install(FILES ${SHADER_FILES} DESTINATION ${SHARE_INSTALL}/themes/default/shaders)
diff --git a/themes/default/shaders/core.frag b/themes/default/shaders/core.frag
new file mode 100644
index 0000000..ae5a802
--- /dev/null
+++ b/themes/default/shaders/core.frag
@@ -0,0 +1,19 @@
+uniform int texMode;
+uniform sampler2D tex;
+uniform sampler2DRect texrect;
+
+void main()
+{
+ vec4 texel;
+ vec4 color;
+ if (texMode == 1) {
+ texel = texture2D(tex, gl_TexCoord[0].st).rgba;
+ } else if (texMode == 2) {
+ texel = texture(texrect, gl_TexCoord[0].st).rgba;
+ } else if (texMode == 0) {
+ texel = gl_Color;
+ } else {
+ texel = vec4(1.0,0.0,0.0,1.0);
+ }
+ gl_FragColor = vec4(texel.rgb*gl_Color.rgb, texel.a*gl_Color.a);
+}
diff --git a/themes/default/shaders/core.vert b/themes/default/shaders/core.vert
new file mode 100644
index 0000000..570a61a
--- /dev/null
+++ b/themes/default/shaders/core.vert
@@ -0,0 +1,7 @@
+void main()
+{
+ gl_FrontColor = gl_Color;
+ gl_BackColor = gl_Color;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = ftransform();
+}
|