danini-the-panini/mittsu-opengl

View on GitHub
lib/mittsu/opengl/state.rb

Summary

Maintainability
B
5 hrs
Test Coverage
C
76%
module Mittsu
  class OpenGL::State
    def initialize
      @new_attributes = Array.new(16) # Uint8Array
      @enabled_attributes = Array.new(16) # Uint8Array

      @current_blending = nil
      @current_blend_equation = nil
      @current_blend_src = nil
      @current_blend_dst = nil
      @current_blend_equation_alpha = nil
      @current_blend_src_alpha = nil
      @current_blend_dst_alpha = nil

      @current_depth_test = nil
      @current_depth_write = nil

      @current_color_write = nil

      @current_double_sided = nil
      @current_flip_sided = nil

      @current_line_width = nil

      @current_polygon_offset = nil
      @current_polygon_offset_factor = nil
      @current_polygon_offset_units = nil
    end

    def init_attributes
      @new_attributes.length.times do |i|
        @new_attributes[i] = false
      end
    end

    def enable_attribute(attribute)
      GL.EnableVertexAttribArray(attribute)
      @new_attributes[attribute] = true

      if !@enabled_attributes[attribute]
        # GL.EnableVertexAttribArray(attribute)
        @enabled_attributes[attribute] = true
      end
    end

    def disable_unused_attributes
      @enabled_attributes.length.times do |i|
        if @enabled_attributes[i] && !@new_attributes[i]
          GL.DisableVertexAttribArray(i)
          @enabled_attributes[i] = false
        end
      end
    end

    def set_blending(blending, blend_equation = nil, blend_src = nil, blend_dst = nil, blend_equation_alpha = nil, blend_src_alpha = nil, blend_dst_alpha = nil)
      if blending != @current_blending
        case blending
        when NoBlending
          GL.Disable(GL::BLEND)
        when AdditiveBlending
          GL.Enable(GL::BLEND)
          GL.BlendEquation(GL::FUNC_ADD)
          GL.BlendFunc(GL::SRC_ALPHA, GL::ONE)
        when SubtractiveBlending
          # TODO: Find blendFuncSeparate() combination ???
          GL.Enable(GL::BLEND)
          GL.BlendEquation(GL::FUNC_ADD)
          GL.BlendFunc(GL::ZERO, GL::ONE_MINUS_SRC_COLOR)
        when MultiplyBlending
          # TODO: Find blendFuncSeparate() combination ???
          GL.Enable(GL::BLEND)
          GL.BlendEquation(GL::FUNC_ADD)
          GL.BlendFunc(GL::ZERO, GL::ONE_MINUS_SRC_COLOR)
        when CustomBlending
          GL.Enable(GL::BLEND)
        else
          GL.Enable(GL::BLEND)
          GL.BlendEquationSeparate(GL::FUNC_ADD, GL::FUNC_ADD)
          GL.BlendFuncSeparate(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA, GL::ONE, GL::ONE_MINUS_SRC_ALPHA)
        end

        @current_blending = blending
      end

      if blending == CustomBlending
        blend_equation_alpha ||= blend_equation
        blend_src_alpha ||= blend_src
        blend_dst_alpha ||= blend_dst

        if blend_equation != @current_blend_equation || blend_equation_alpha != @current_blend_equation_alpha
          GL.BlendEquationSeparate(GL::MITTSU_PARAMS[blend_equation], GL::MITTSU_PARAMS[blend_equation_alpha])

          @current_blend_equation = blend_equation
          @current_blend_equation_alpha = blend_equation_alpha
        end

        if blend_src != @current_blend_src || blend_dst != @current_blend_dst || blend_src_alpha != @current_blend_src_alpha || blend_dst_alpha != @current_blend_dst_alpha
          GL.BlendFuncSeparate(GL::MITTSU_PARAMS[blend_src], GL::MITTSU_PARAMS[blend_dst], GL::MITTSU_PARAMS[blend_src_alpha], GL::MITTSU_PARAMS[blend_dst_alpha])

          @current_blend_src = nil
          @current_blend_dst = nil
          @current_blend_src_alpha = nil
          @current_blend_dst_alpha = nil
        end
      else
        @current_blend_equation = nil
        @current_blend_src = nil
        @current_blend_dst = nil
        @current_blend_equation_alpha = nil
        @current_blend_src_alpha = nil
        @current_blend_dst_alpha = nil
      end
    end

    def set_depth_test(depth_test)
      if @current_depth_test != depth_test
        if depth_test
          GL.Enable(GL::DEPTH_TEST)
        else
          GL.Disable(GL::DEPTH_TEST)
        end

        @current_depth_test = depth_test
      end
    end

    def set_depth_write(depth_write)
      if @current_depth_write != depth_write
        GL.DepthMask(depth_write ? GL::TRUE : GL::FALSE)
        @current_depth_write = depth_write
      end
    end

    def set_color_write(color_write)
      if @current_color_write != color_write
        gl_color_write = color_write ? GL::TRUE : GL::FALSE
        GL.ColorMask(gl_color_write, gl_color_write, gl_color_write, gl_color_write)
        @current_color_write = color_write
      end
    end

    def set_double_sided(double_sided)
      if @current_double_sided != double_sided
        if double_sided
          GL.Disable(GL::CULL_FACE)
        else
          GL.Enable(GL::CULL_FACE)
        end

        @current_double_sided = double_sided
      end
    end

    def set_flip_sided(flip_sided)
      if @current_flip_sided != flip_sided
        if flip_sided
          GL.FrontFace(GL::CW)
        else
          GL.FrontFace(GL::CCW)
        end

        @current_flip_sided = flip_sided
      end
    end

    def set_line_width(width)
      if width != @current_line_width
        GL.LineWidth(width)
        @current_line_width = width
      end
    end

    def set_polygon_offset(polygon_offset, factor, units)
      if @current_polygon_offset != polygon_offset
        if polygon_offset
          GL.Enable(GL::POLYGON_OFFSET_FILL)
        else
          GL.Disable(GL::POLYGON_OFFSET_FILL)
        end

        @current_polygon_offset = polygon_offset
      end

      if polygon_offset && (@current_polygon_offset_factor != factor || @current_polygon_offset_units != units)
        GL.PolygonOffset(factor, units)

        @current_polygon_offset_factor = factor
        @current_polygon_offset_units = units
      end
    end

    def reset
      @enabled_attributes.length.times do |i|
        @enabled_attributes[i] = false
      end

      @current_blending = nil
      @current_depth_test = nil
      @current_depth_write = nil
      @current_color_write = nil
      @current_double_sided = nil
      @current_flip_sided = nil
    end
  end
end