def load_uniforms_generic(uniforms)
      uniforms.each do |(uniform, location)|
        # needs_update property is not added to all uniforms.
        next if uniform.needs_update == false || location == -1

        type = uniform.type
        value = uniform.value

        # AAAAAHHHHH!!!!! \o/ *flips table*
        case type
        when :int
          glUniform1i(location, value)
        when :ivec2
          glUniform2i(location, value[0], value[1])
        when :ivec3
          glUniform3i(location, value[0], value[1], value[2])
        when :ivec4
          glUniform4i(location, value[0], value[1], value[2], value[3])
        when :float
          glUniform1f(location, value)
        when :vec2
          glUniform2f(location, value[0], value[1])
        when :vec3, :color
          glUniform3f(location, value[0], value[1], value[2])
        when :vec4
          glUniform4f(location, value[0], value[1], value[2], value[3])
        when :'int[]'
          glUniform1iv(location, value.length, array_to_ptr_easy(value))
        when :'ivec2[]'
          glUniform2iv(location, value.length / 2, array_to_ptr_easy(value))
        when :'ivec3[]'
          glUniform3iv(location, value.length / 3, array_to_ptr_easy(value))
        when :'ivec4[]'
          glUniform4iv(location, value.length / 4, array_to_ptr_easy(value))
        when :'float[]'
          glUniform1fv(location, value.length, array_to_ptr_easy(value))
        when :'vec2[]'
          if value[0].is_a? Vector2
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform2fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform2fv(location, value.length / 2, array_to_ptr_easy(value))
          end
        when :'vec3[]', :'color[]'
          if value.first.is_a?(Vector3) || value.first.is_a?(Color)
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform3fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform3fv(location, value.length / 3, array_to_ptr_easy(value))
          end
        when :'vec4[]'
          if value.first.is_a? Vector4
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform4fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform4fv(location, value.length / 4, array_to_ptr_easy(value))
          end
        when :mat3
          glUniformMatrix3fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
        when :mat4
          glUniformMatrix4fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
        when :'mat3[]'
          if value.first.is_a? Matrix3
            uniform.array ||= Array.new(9 * value.length) # Float32Array

            value.each_with_index do |v, i|
              value[i].flatten_to_array_offset(uniform.array, i * 9)
            end

            glUniformMatrix3fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
          else
            glUniformMatrix3fv(location, value.length / 9, GL_FALSE, array_to_ptr_easy(value))
          end
        when :'mat4[]'
          if value.first.is_a? Matrix4
            uniform.array ||= Array.new(16 * value.length) # Float32Array

            value.each_with_index do |v, i|
              value[i].flatten_to_array_offset(uniform.array, i * 16)
            end

            glUniformMatrix4fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
          else
            glUniformMatrix4fv(location, value.length / 16, GL_FALSE, array_to_ptr_easy(value))
          end
        when :texture
          # single Mittsu::Texture (2d or cube)
          texture = value
          texture_unit = get_texture_unit

          glUniform1i(location, texture_unit)

          next unless texture

          texture.set(texture_unit, self)
          # TODO: when OpenGLRenderTargetCube is defined
          # elsif texture.is_a?(OpenGLRenderTargetCube)
            # set_cube_texture_dynamic(texture, texture_unit)
        when :'texture[]'
          # array of Mittsu::Texture (2d)
          uniform.array ||= []

          uniform.value.each_index do |i|
            uniform.array[i] = get_texture_unit
          end

          glUniform1iv(location, uniform.array.length, array_to_ptr_easy(uniform.array))

          uniform.value.each_with_index do |tex, i|
            tex_unit = uniform.array[i]

            next unless tex

            tex.set(tex_unit, self)
          end
        else
          puts "WARNING: Mittsu::OpenGLRenderer: Unknown uniform type: #{type}"
        end
      end
    end
def load_uniforms_generic(uniforms)
      uniforms.each do |(uniform, location)|
        # needs_update property is not added to all uniforms.
        next if uniform.needs_update == false || location == -1

        type = uniform.type
        value = uniform.value

        # AAAAAHHHHH!!!!! \o/ *flips table*
        case type
        when :int
          glUniform1i(location, value)
        when :ivec2
          glUniform2i(location, value[0], value[1])
        when :ivec3
          glUniform3i(location, value[0], value[1], value[2])
        when :ivec4
          glUniform4i(location, value[0], value[1], value[2], value[3])
        when :float
          glUniform1f(location, value)
        when :vec2
          glUniform2f(location, value[0], value[1])
        when :vec3, :color
          glUniform3f(location, value[0], value[1], value[2])
        when :vec4
          glUniform4f(location, value[0], value[1], value[2], value[3])
        when :'int[]'
          glUniform1iv(location, value.length, array_to_ptr_easy(value))
        when :'ivec2[]'
          glUniform2iv(location, value.length / 2, array_to_ptr_easy(value))
        when :'ivec3[]'
          glUniform3iv(location, value.length / 3, array_to_ptr_easy(value))
        when :'ivec4[]'
          glUniform4iv(location, value.length / 4, array_to_ptr_easy(value))
        when :'float[]'
          glUniform1fv(location, value.length, array_to_ptr_easy(value))
        when :'vec2[]'
          if value[0].is_a? Vector2
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform2fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform2fv(location, value.length / 2, array_to_ptr_easy(value))
          end
        when :'vec3[]', :'color[]'
          if value.first.is_a?(Vector3) || value.first.is_a?(Color)
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform3fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform3fv(location, value.length / 3, array_to_ptr_easy(value))
          end
        when :'vec4[]'
          if value.first.is_a? Vector4
            uniform.array ||= value.flat_map(&:to_a) # TODO: Float32Array
            glUniform4fv(location, value.length, array_to_ptr_easy(uniform.array))
          else
            glUniform4fv(location, value.length / 4, array_to_ptr_easy(value))
          end
        when :mat3
          glUniformMatrix3fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
        when :mat4
          glUniformMatrix4fv(location, 1, GL_FALSE, array_to_ptr_easy(value.to_a))
        when :'mat3[]'
          if value.first.is_a? Matrix3
            uniform.array ||= Array.new(9 * value.length) # Float32Array

            value.each_with_index do |v, i|
              value[i].flatten_to_array_offset(uniform.array, i * 9)
            end

            glUniformMatrix3fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
          else
            glUniformMatrix3fv(location, value.length / 9, GL_FALSE, array_to_ptr_easy(value))
          end
        when :'mat4[]'
          if value.first.is_a? Matrix4
            uniform.array ||= Array.new(16 * value.length) # Float32Array

            value.each_with_index do |v, i|
              value[i].flatten_to_array_offset(uniform.array, i * 16)
            end

            glUniformMatrix4fv(location, value.length, GL_FALSE, array_to_ptr_easy(uniform.array))
          else
            glUniformMatrix4fv(location, value.length / 16, GL_FALSE, array_to_ptr_easy(value))
          end
        when :texture
          # single Mittsu::Texture (2d or cube)
          texture = value
          texture_unit = get_texture_unit

          glUniform1i(location, texture_unit)

          next unless texture

          texture.set(texture_unit, self)
          # TODO: when OpenGLRenderTargetCube is defined
          # elsif texture.is_a?(OpenGLRenderTargetCube)
            # set_cube_texture_dynamic(texture, texture_unit)
        when :'texture[]'
          # array of Mittsu::Texture (2d)
          uniform.array ||= []

          uniform.value.each_index do |i|
            uniform.array[i] = get_texture_unit
          end

          glUniform1iv(location, uniform.array.length, array_to_ptr_easy(uniform.array))

          uniform.value.each_with_index do |tex, i|
            tex_unit = uniform.array[i]

            next unless tex

            tex.set(tex_unit, self)
          end
        else
          puts "WARNING: Mittsu::OpenGLRenderer: Unknown uniform type: #{type}"
        end
      end
    end
FIXME: REFACTOR!?!?!?!?!???
 MASSIVE CASE STATEMENT OMG!!!