|
From: Tapio V. <aa...@us...> - 2010-11-06 20:15:51
|
Module: performous
Branch: opengl2
Commit: 801c43948ef51a3c5a24710c5e0b1ce508da07ac
Author: Tapio Vierros <tap...@gm...>
Date: Sat Nov 6 21:06:57 2010 +0200
Provide a nice interface for uniforms in Shader class.
---
game/glshader.cc | 15 ++++++++-------
game/glshader.hh | 28 ++++++++++++++++++++++------
game/screen_intro.cc | 2 +-
game/surface.hh | 11 +++++------
4 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/game/glshader.cc b/game/glshader.cc
index 3d0f965..3a38510 100644
--- a/game/glshader.cc
+++ b/game/glshader.cc
@@ -53,6 +53,7 @@ Shader::Shader(const std::string& vert_path, const std::string& frag_path, bool
Shader::~Shader() {
+ shaders[program] = NULL;
glDeleteProgram(program);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
@@ -109,13 +110,6 @@ void Shader::loadFromMemory(const char* vert_source, const char* frag_source, bo
}
glutil::GLErrorChecker linkerror("Shader::loadFromMemory - glLinkProgram");
- // Cache uniform locations
- tex = glGetUniformLocation(program, "tex");
- texRect = glGetUniformLocation(program, "texRect");
- texMode = glGetUniformLocation(program, "texMode");
- anim = glGetUniformLocation(program, "anim");
- glutil::GLErrorChecker uniformerror("Shader::loadFromMemory - glGetUniformLocation");
-
shaders[program] = this;
if (use) bind();
@@ -128,6 +122,13 @@ void Shader::bind() {
}
+GLint Shader::operator[](const std::string& uniform) {
+ UniformMap::iterator it = uniforms.find(uniform);
+ if (it == uniforms.end())
+ it->second = glGetUniformLocation(program, uniform.c_str());
+ return it->second;
+}
+
void loadShaders() {
Window::shader.reset(new Shader(getThemePath("shaders/core.vert"), getThemePath("shaders/core.frag"), true));
diff --git a/game/glshader.hh b/game/glshader.hh
index 71c285d..1499654 100644
--- a/game/glshader.hh
+++ b/game/glshader.hh
@@ -19,11 +19,19 @@ struct Shader: public boost::noncopyable {
/** Binds the shader into use. */
void bind();
- GLuint program, vert_shader, frag_shader; ///< shader object ids
- // TODO: Should probably use an std::map for these and cache on-the-fly/on-demand.
- // Also provide a nice access to setting the uniform.
- GLint tex, texRect, texMode, anim; ///< uniform locations
- int gl_response;
+ /** Get uniform location. Uses caching internally. */
+ GLint operator[](const std::string& uniform);
+
+ /** Allow setting uniforms in a chain. Shader needs to be in use.*/
+
+ Shader& setUniform(const std::string& uniform, int value) {
+ glUniform1i((*this)[uniform], value);
+ return *this;
+ }
+ Shader& setUniform(const std::string& uniform, float value) {
+ glUniform1f((*this)[uniform], value);
+ return *this;
+ }
// Some operators
operator bool() const { return program != 0; }
@@ -37,8 +45,15 @@ struct Shader: public boost::noncopyable {
return shaders[i];
}
+ GLuint program, vert_shader, frag_shader; ///< shader object ids
+ int gl_response;
+
+ private:
+ typedef std::map<std::string, GLint> UniformMap;
+ UniformMap uniforms; ///< Cached uniform locations, use operator[] to access
+
typedef std::map<GLint, Shader*> ShaderMap;
- static ShaderMap shaders;
+ static ShaderMap shaders; ///< Shader objects for reverse look-up by id
};
@@ -49,6 +64,7 @@ struct UseShader {
new_shader.bind();
}
~UseShader() { glUseProgram(m_old); }
+
private:
GLint m_old;
};
diff --git a/game/screen_intro.cc b/game/screen_intro.cc
index 61e9023..ccca31b 100644
--- a/game/screen_intro.cc
+++ b/game/screen_intro.cc
@@ -116,7 +116,7 @@ void ScreenIntro::draw() {
{
UseShader s(*ThemeIntro::shader);
float anim = std::abs((((SDL_GetTicks() % 10000) / 10000.f) - 0.5f) * 2.0f);
- glUniform1f(ThemeIntro::shader->anim, anim);
+ ThemeIntro::shader->setUniform("anim", anim);
theme->bg.draw();
}
if (m_menu.current().image) m_menu.current().image->draw();
diff --git a/game/surface.hh b/game/surface.hh
index 2a9ef6b..f173515 100644
--- a/game/surface.hh
+++ b/game/surface.hh
@@ -122,19 +122,18 @@ class UseTexture: boost::noncopyable {
/// constructor
template <GLenum Type> UseTexture(OpenGLTexture<Type> const& s):
m_shader(*Shader::current()) {
- glUniform1i(m_shader.tex, 0);
- glUniform1i(m_shader.texRect, 1);
+ m_shader.setUniform("tex", 0).setUniform("texRect", 1);
switch (Type) {
- case GL_TEXTURE_2D: glActiveTexture(GL_TEXTURE0); glUniform1i(m_shader.texMode, 1); break;
- case GL_TEXTURE_RECTANGLE_ARB: glActiveTexture(GL_TEXTURE0+1); glUniform1i(m_shader.texMode, 2); break;
- default: glUniform1i(m_shader.texMode, 3); break;
+ case GL_TEXTURE_2D: glActiveTexture(GL_TEXTURE0); m_shader.setUniform("texMode", 1); break;
+ case GL_TEXTURE_RECTANGLE_ARB: glActiveTexture(GL_TEXTURE0+1); m_shader.setUniform("texMode", 2); break;
+ default: m_shader.setUniform("texMode", 3); break;
}
glBindTexture(Type, s.id());
}
~UseTexture() {
- glUniform1i(m_shader.texMode, 0);
+ m_shader.setUniform("texMode", 0);
}
private:
|