Index: trunk/nv/gl/gl_program.hh
===================================================================
--- trunk/nv/gl/gl_program.hh	(revision 40)
+++ trunk/nv/gl/gl_program.hh	(revision 41)
@@ -54,4 +54,5 @@
 	protected:
 		bool validate();
+		void update_uniforms();
 		void load_attributes();
 		void load_uniforms();
Index: trunk/nv/interface/program.hh
===================================================================
--- trunk/nv/interface/program.hh	(revision 40)
+++ trunk/nv/interface/program.hh	(revision 41)
@@ -14,4 +14,5 @@
 
 #include <unordered_map>
+#include <nv/logging.hh>
 #include <nv/common.hh>
 #include <nv/string.hh>
@@ -131,10 +132,11 @@
 		{
 			uniform_base* base = get_uniform( name );
-			if ( base == nullptr || base->get_type() != type_to_enum<T>::type )
+			// restore typechecking, but remember to accept int for float!
+			if ( base == nullptr /* || base->get_type() != type_to_enum<T>::type */ )
 			{
-				// signal error
+				NV_LOG( LOG_ERROR, "Uniform '" << name << "' not found in program!" );
 				return;
 			}
-			uniform<T>( base )->set_value( value );
+			((uniform<T>*)( base ))->set_value( value );
 		}
 	protected:
Index: trunk/src/gl/gl_program.cc
===================================================================
--- trunk/src/gl/gl_program.cc	(revision 40)
+++ trunk/src/gl/gl_program.cc	(revision 41)
@@ -8,4 +8,7 @@
 #include "nv/logging.hh"
 #include "nv/lib/gl.hh"
+
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
 
 using namespace nv;
@@ -119,4 +122,5 @@
 {
 	glUseProgram( m_name.get_value() );
+	update_uniforms();
 }
 
@@ -181,4 +185,34 @@
 }
 
+void gl_program::update_uniforms()
+{
+	for ( uniform_map::iterator i = m_uniform_map.begin(); 	i != m_uniform_map.end(); ++i ) 
+	{
+		uniform_base* ubase = i->second;
+		if ( ubase->is_dirty() )
+		{
+			int uloc = ubase->get_location();
+			switch( ubase->get_type() )
+			{
+			case FLOAT          : glUniform1f( uloc, ((uniform< enum_to_type< FLOAT >::type >*)( ubase ))->get_value() ); break;
+			case INT            : glUniform1i( uloc, ((uniform< enum_to_type< INT >::type >*)( ubase ))->get_value() ); break;
+			case FLOAT_VECTOR_2 : glUniform2fv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< FLOAT_VECTOR_2 >::type >*)( ubase ))->get_value()) ); break;
+			case FLOAT_VECTOR_3 : glUniform3fv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< FLOAT_VECTOR_3 >::type >*)( ubase ))->get_value()) ); break;
+			case FLOAT_VECTOR_4 : glUniform4fv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< FLOAT_VECTOR_4 >::type >*)( ubase ))->get_value()) ); break;
+			case INT_VECTOR_2   : glUniform2iv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< INT_VECTOR_2 >::type >*)( ubase ))->get_value()) ); break;
+			case INT_VECTOR_3   : glUniform3iv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< INT_VECTOR_3 >::type >*)( ubase ))->get_value()) ); break;
+			case INT_VECTOR_4   : glUniform4iv( uloc, 1, glm::value_ptr(((uniform< enum_to_type< INT_VECTOR_4 >::type >*)( ubase ))->get_value()) ); break;
+			case FLOAT_MATRIX_2 : glUniformMatrix2fv( uloc, 1, GL_FALSE, glm::value_ptr(((uniform< enum_to_type< FLOAT_MATRIX_2 >::type >*)( ubase ))->get_value()) ); break;
+			case FLOAT_MATRIX_3 : glUniformMatrix3fv( uloc, 1, GL_FALSE, glm::value_ptr(((uniform< enum_to_type< FLOAT_MATRIX_3 >::type >*)( ubase ))->get_value()) ); break;
+			case FLOAT_MATRIX_4 : glUniformMatrix4fv( uloc, 1, GL_FALSE, glm::value_ptr(((uniform< enum_to_type< FLOAT_MATRIX_4 >::type >*)( ubase ))->get_value()) ); break;
+			//default     : error?
+			}
+			ubase->clean();
+		}
+	}
+
+}
+
+
 bool gl_program::validate()
 {
