Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualLightness1024

Posted 28 September 2012 - 03:15 PM

my personal solution, but frankly I hate it, I think it is just a failed moment of having fun with C++, and that you can just go implement duplicated functions it is just a small part of the underlying layers of en engine you rarely need to put your nose into anyways. once its written its written.

anyways:

http://paste.blixt.org/8871931

PS note: the code=cpp tag in that forum is reaaaally buggy. impossible to post my snippet of code without losing entire lines !!

#2Lightness1024

Posted 28 September 2012 - 03:13 PM

my personal solution, but frankly I hate it, I think it is just a failed moment of having fun with C++, and that you can just go implement duplicated functions it is just a small part of the underlying layers of en engine you rarely need to put your nose into anyways. once its written its written.

anyways:

[source lang="cpp"]/*********************************************************************** File : shader_objects.hpp* Author: Lightness1024!* Date : 01/10/2009*********************************************************************/#ifndef SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_#define SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_ 1#include <manager_base.hpp>#include <boost/format.hpp>#include <boost/mpl/vector.hpp>#include <boost/mpl/contains.hpp>#include <boost/mpl/find.hpp>#include <boost/mpl/size.hpp>#include <boost/utility/enable_if.hpp>#include <boost/array.hpp>#include <boost/scoped_ptr.hpp>#include <stdio.h>#include <GL/glew.h>#include <iostream>#include <math/glm/virtrev/address.hpp>#include <gl_tbx.hpp>#include <tbx/config.hpp>extern boost::scoped_ptr<tbx::config> conf;namespace gfx{ namespace detail { char* get_shader_source(const char * szfilename); int load_program(char const* vtx_code_src, char const* frag_code_src); } namespace mpl = boost::mpl; // forwarders of type, one will just copy the input into the return value if the argument is of the // same type than the required output. the second will ignore the argument, and return a default constructed return type. // these function exist to enable compilation of function working of 'mat' when the argument is of type 'vec', which are incompatible. template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::enable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return val; } template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::disable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return target_t(); } //! represents a GLSL program that contains code for vertex and fragment shaders. class glsl_program { public: glsl_program(char const* vtx_code_src, char const* frag_code_src) { prog_glname_ = detail::load_program(vtx_code_src, frag_code_src); if (prog_glname_ == 0){ throw std::runtime_error( (boost::format("couldn't load shader files: %1% and/or %2%") % vtx_code_src % frag_code_src).str()); } } void set(){ glUseProgram(prog_glname_); last_set_prog_ = prog_glname_; } //! all uniform types we can manage: typedef mpl::vector< float, // 0 glm::vec2, // 1 glm::vec3, // 2 glm::vec4, // 3 glm::mat3, // 4 glm::mat4, int > uniform_types; typedef mpl::vector< glm::vec2, glm::vec3, glm::vec4> vec_types; typedef mpl::vector< glm::mat3, glm::mat4> mat_types; template< typename check_against_t > struct is_type_handled_uniform{ static bool const value = mpl::contains< uniform_types, check_against_t >::type::value; }; template< typename uniform_t > void update_uniform(char const* name, uniform_t const& value){ // check that the function is not used outside of its managed types (c.f. uniform_types): static_assert(( is_type_handled_uniform< uniform_t >::value && "YOU CANNOT COMPILE A CALL TO UPDATE_UNIFORM FUNCTION WITH A NON RECOGNIZED TYPE")); // other checks: assert(name && "CANNOT PASS NULL AS NAME"); assert(prog_glname_ > 0 && "CANNOT USE UPDATE_UNIFORM ON NON-LINKED PROGRAM"); assert(last_set_prog_ == prog_glname_ && "CANNOT USE UPDATE_UNIFORM ON NON-ATTACHED PROGRAM"); // type of functions from the gl specification: typedef void (*gl_func_fv_t) (GLint, GLsizei, GLfloat const*); // vectors typedef void (*gl_func_mat_t) (GLint, GLsizei, GLboolean, GLfloat const*); // matrices // define an array of functions for vectors: boost::array< gl_func_fv_t, 3 > const set_uniform_fv = {{glUniform2fv, glUniform3fv, glUniform4fv}}; // array of functions for matrices: boost::array< gl_func_mat_t, 2 > const set_uniform_mat = {{glUniformMatrix3fv, glUniformMatrix4fv}}; // find client's type position in sequence: size_t type_pos = mpl::find< uniform_types, uniform_t >::type::pos::value; // find uniform location in the shader program: size_t uniform_location = glGetUniformLocation(prog_glname_, name); if (uniform_location == -1) { std::string err_msg = (boost::format("attempt to modify uniform \"%1%\", but wasn't found in the shader program." "\n note: this is a hard error. you can make it soft by adding\"continue_on_uniform_issues=bool:true\" to your scud.conf") % name).str(); if (!conf->property<bool>("continue_on_uniform_issues", false)) throw std::runtime_error(err_msg); else std::cout << err_msg << std::endl; } // execute appropriate gl function to set the uniform: assert(type_pos <= mpl::size<uniform_types>::type::value); //std::cout << "type pos:" << type_pos << std::endl; switch (type_pos){ case 0: { // float GLfloat buildable = forward<GLfloat, uniform_t>(value); glUniform1f(uniform_location, buildable); break; } case 1: case 2: case 3: { // vecs // clamp uniform_t to a vec type to avoid build error typedef typename mpl::contains< vec_types, uniform_t >::type is_vec; typedef typename mpl::find< vec_types, uniform_t >::type found_among_vecs_iter; typedef typename mpl::deref<found_among_vecs_iter>::type found_among_vecs_t; typedef typename mpl::if_< is_vec, found_among_vecs_t, glm::vec4 >::type best_vec_t; best_vec_t buildable = forward<best_vec_t, uniform_t>(value); set_uniform_fv[type_pos - 1](uniform_location, 1, glm::address(buildable)); break; } case 4: case 5: { // mats typedef typename mpl::contains< mat_types, uniform_t >::type is_mat; typedef typename mpl::find< mat_types, uniform_t >::type found_among_mats_iter; typedef typename mpl::deref< found_among_mats_iter >::type found_among_mats_t; typedef typename mpl::if_< is_mat, found_among_mats_t, glm::mat4 >::type best_mat_t; best_mat_t buildable = forward<best_mat_t, uniform_t>(value); set_uniform_mat[type_pos - 4](uniform_location, 1, GL_FALSE, glm::address(buildable)); break; } case 6: { // int GLint buildable = forward<GLint, uniform_t>(value); glUniform1i(uniform_location, buildable); } } check_gl_error(SCUD_PROG_POS); } static void unset(){ glUseProgram(0); last_set_prog_ = 0; } private: GLuint prog_glname_; static GLuint last_set_prog_; };}#endif //SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_[/source]

#1Lightness1024

Posted 28 September 2012 - 03:06 PM

my personal solution, but frankly I hate it, I think it is just a failed moment of having fun with C++, and that you can just go implement duplicated functions it is just a small part of the underlying layers of en engine you rarely need to put your nose into anyways. once its written its written.

anyways:

[source lang="cpp"]/********************************************************************** * File : shader_objects.hpp * Author: Lightness1024! * Date : 01/10/2009 *********************************************************************/#ifndef SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_#define SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_ 1#include <manager_base.hpp>#include <boost/format.hpp>#include <boost/mpl/vector.hpp>#include <boost/mpl/contains.hpp>#include <boost/mpl/find.hpp>#include <boost/mpl/size.hpp>#include <boost/utility/enable_if.hpp>#include <boost/array.hpp>#include <boost/scoped_ptr.hpp>#include <stdio.h>#include <GL/glew.h>#include <iostream>#include <math/glm/virtrev/address.hpp>#include <gl_tbx.hpp>#include <tbx/config.hpp>extern boost::scoped_ptr<tbx::config> conf;namespace gfx{ namespace detail { char* get_shader_source(const char * szfilename); int load_program(char const* vtx_code_src, char const* frag_code_src); } namespace mpl = boost::mpl; // forwarders of type, one will just copy the input into the return value if the argument is of the // same type than the required output. the second will ignore the argument, and return a default constructed return type. // these function exist to enable compilation of function working of 'mat' when the argument is of type 'vec', which are incompatible. template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::enable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return val; } template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::disable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return target_t(); } //! represents a GLSL program that contains code for vertex and fragment shaders. class glsl_program { public: glsl_program(char const* vtx_code_src, char const* frag_code_src) { prog_glname_ = detail::load_program(vtx_code_src, frag_code_src); if (prog_glname_ == 0){ throw std::runtime_error( (boost::format("couldn't load shader files: %1% and/or %2%") % vtx_code_src % frag_code_src).str()); } } void set(){ glUseProgram(prog_glname_); last_set_prog_ = prog_glname_; } //! all uniform types we can manage: typedef mpl::vector< float, // 0 glm::vec2, // 1 glm::vec3, // 2 glm::vec4, // 3 glm::mat3, // 4 glm::mat4, int > uniform_types; typedef mpl::vector< glm::vec2, glm::vec3, glm::vec4> vec_types; typedef mpl::vector< glm::mat3, glm::mat4> mat_types; template< typename check_against_t > struct is_type_handled_uniform{ static bool const value = mpl::contains< uniform_types, check_against_t >::type::value; }; template< typename uniform_t > void update_uniform(char const* name, uniform_t const& value){ // check that the function is not used outside of its managed types (c.f. uniform_types): static_assert(( is_type_handled_uniform< uniform_t >::value && "YOU CANNOT COMPILE A CALL TO UPDATE_UNIFORM FUNCTION WITH A NON RECOGNIZED TYPE")); // other checks: assert(name && "CANNOT PASS NULL AS NAME"); assert(prog_glname_ > 0 && "CANNOT USE UPDATE_UNIFORM ON NON-LINKED PROGRAM"); assert(last_set_prog_ == prog_glname_ && "CANNOT USE UPDATE_UNIFORM ON NON-ATTACHED PROGRAM"); // type of functions from the gl specification: typedef void (*gl_func_fv_t) (GLint, GLsizei, GLfloat const*); // vectors typedef void (*gl_func_mat_t) (GLint, GLsizei, GLboolean, GLfloat const*); // matrices // define an array of functions for vectors: boost::array< gl_func_fv_t, 3 > const set_uniform_fv = {{glUniform2fv, glUniform3fv, glUniform4fv}}; // array of functions for matrices: boost::array< gl_func_mat_t, 2 > const set_uniform_mat = {{glUniformMatrix3fv, glUniformMatrix4fv}}; // find client's type position in sequence: size_t type_pos = mpl::find< uniform_types, uniform_t >::type::pos::value; // find uniform location in the shader program: size_t uniform_location = glGetUniformLocation(prog_glname_, name); if (uniform_location == -1) { std::string err_msg = (boost::format("attempt to modify uniform \"%1%\", but wasn't found in the shader program." "\n note: this is a hard error. you can make it soft by adding\"continue_on_uniform_issues=bool:true\" to your scud.conf") % name).str(); if (!conf->property<bool>("continue_on_uniform_issues", false)) throw std::runtime_error(err_msg); else std::cout << err_msg << std::endl; } // execute appropriate gl function to set the uniform: assert(type_pos <= mpl::size<uniform_types>::type::value); //std::cout << "type pos:" << type_pos << std::endl; switch (type_pos){ case 0: { // float GLfloat buildable = forward<GLfloat, uniform_t>(value); glUniform1f(uniform_location, buildable); break; } case 1: case 2: case 3: { // vecs // clamp uniform_t to a vec type to avoid build error typedef typename mpl::contains< vec_types, uniform_t >::type is_vec; typedef typename mpl::find< vec_types, uniform_t >::type found_among_vecs_iter; typedef typename mpl::deref<found_among_vecs_iter>::type found_among_vecs_t; typedef typename mpl::if_< is_vec, found_among_vecs_t, glm::vec4 >::type best_vec_t; best_vec_t buildable = forward<best_vec_t, uniform_t>(value); set_uniform_fv[type_pos - 1](uniform_location, 1, glm::address(buildable)); break; } case 4: case 5: { // mats typedef typename mpl::contains< mat_types, uniform_t >::type is_mat; typedef typename mpl::find< mat_types, uniform_t >::type found_among_mats_iter; typedef typename mpl::deref< found_among_mats_iter >::type found_among_mats_t; typedef typename mpl::if_< is_mat, found_among_mats_t, glm::mat4 >::type best_mat_t; best_mat_t buildable = forward<best_mat_t, uniform_t>(value); set_uniform_mat[type_pos - 4](uniform_location, 1, GL_FALSE, glm::address(buildable)); break; } case 6: { // int GLint buildable = forward<GLint, uniform_t>(value); glUniform1i(uniform_location, buildable); } } check_gl_error(SCUD_PROG_POS); } static void unset(){ glUseProgram(0); last_set_prog_ = 0; } private: GLuint prog_glname_; static GLuint last_set_prog_; };}#endif //SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_[/source]

PARTNERS