class CyberarmEngine::OpenGLRenderer

Attributes

show_wireframe[RW]

Public Class Methods

new(width:, height:, show_wireframe: false) click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 7
def initialize(width:, height:, show_wireframe: false)
  @width = width
  @height = height
  @show_wireframe = show_wireframe

  @g_buffer = GBuffer.new(width: @width, height: @height)
end

Public Instance Methods

canvas_size_changed() click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 15
def canvas_size_changed
  @g_buffer.unbind_framebuffer
  @g_buffer.clean_up

  @g_buffer = GBuffer.new(width: @width, height: @height)
end
copy_g_buffer_to_screen() click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 99
def copy_g_buffer_to_screen
  @g_buffer.set_read_buffer(:position)
  glBlitFramebuffer(0, 0, @g_buffer.width, @g_buffer.height,
                    0, 0, @g_buffer.width / 2, @g_buffer.height / 2,
                    GL_COLOR_BUFFER_BIT, GL_LINEAR)

  @g_buffer.set_read_buffer(:diffuse)
  glBlitFramebuffer(0, 0, @g_buffer.width, @g_buffer.height,
                    0, @g_buffer.height / 2, @g_buffer.width / 2, @g_buffer.height,
                    GL_COLOR_BUFFER_BIT, GL_LINEAR)

  @g_buffer.set_read_buffer(:normal)
  glBlitFramebuffer(0, 0, @g_buffer.width, @g_buffer.height,
                    @g_buffer.width / 2, @g_buffer.height / 2, @g_buffer.width, @g_buffer.height,
                    GL_COLOR_BUFFER_BIT, GL_LINEAR)

  @g_buffer.set_read_buffer(:texcoord)
  glBlitFramebuffer(0, 0, @g_buffer.width, @g_buffer.height,
                    @g_buffer.width / 2, 0, @g_buffer.width, @g_buffer.height / 2,
                    GL_COLOR_BUFFER_BIT, GL_LINEAR)
end
draw_mesh(model) click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 235
def draw_mesh(model)
  model.objects.each_with_index do |o, _i|
    glEnable(GL_COLOR_MATERIAL)
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
    glShadeModel(GL_FLAT) unless o.faces.first[4]
    glShadeModel(GL_SMOOTH) if o.faces.first[4]
    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_COLOR_ARRAY)
    glEnableClientState(GL_NORMAL_ARRAY)

    if o.has_texture?
      glEnable(GL_TEXTURE_2D)
      glBindTexture(GL_TEXTURE_2D, o.materials.find { |mat| mat.texture_id }.texture_id)
      glEnableClientState(GL_TEXTURE_COORD_ARRAY)
      glTexCoordPointer(3, GL_FLOAT, 0, o.flattened_uvs)
    end

    glVertexPointer(4, GL_FLOAT, 0, o.flattened_vertices)
    glColorPointer(3, GL_FLOAT, 0, o.flattened_materials)
    glNormalPointer(GL_FLOAT, 0, o.flattened_normals)

    if @show_wireframe # This is kinda expensive
      glDisable(GL_LIGHTING)
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
      glPolygonOffset(2, 0.5)
      glLineWidth(3)

      glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size / 4)

      glLineWidth(1)
      glPolygonOffset(0, 0)
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
      glEnable(GL_LIGHTING)

      glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size / 4)
    else
      glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size / 4)
    end

    # glBindBuffer(GL_ARRAY_BUFFER, 0)

    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_COLOR_ARRAY)
    glDisableClientState(GL_NORMAL_ARRAY)

    if o.has_texture?
      glDisableClientState(GL_TEXTURE_COORD_ARRAY)
      glDisable(GL_TEXTURE_2D)
    end

    glDisable(GL_COLOR_MATERIAL)
  end
end
draw_model(model, shader) click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 185
def draw_model(model, shader)
  glBindVertexArray(model.vertex_array_id)
  glEnableVertexAttribArray(0)
  glEnableVertexAttribArray(1)
  glEnableVertexAttribArray(2)
  if model.has_texture?
    glEnableVertexAttribArray(3)
    glEnableVertexAttribArray(4)
  end

  if @show_wireframe
    glLineWidth(2)
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
    Shader.active_shader.uniform_boolean("disableLighting", true)

    glDrawArrays(GL_TRIANGLES, 0, model.faces.count * 3)

    Shader.active_shader.uniform_boolean("disableLighting", false)
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    glLineWidth(1)
  end

  offset = 0
  model.objects.each do |object|
    shader.uniform_boolean("hasTexture", object.has_texture?)

    if object.has_texture?
      glBindTexture(GL_TEXTURE_2D, object.materials.find { |mat| mat.texture_id }.texture_id)
    else
      glBindTexture(GL_TEXTURE_2D, 0)
    end

    glDrawArrays(GL_TRIANGLES, offset, object.faces.count * 3)
    offset += object.faces.count * 3
  end

  if model.has_texture?
    glDisableVertexAttribArray(4)
    glDisableVertexAttribArray(3)

    glBindTexture(GL_TEXTURE_2D, 0)
  end
  glDisableVertexAttribArray(2)
  glDisableVertexAttribArray(1)
  glDisableVertexAttribArray(0)

  glBindBuffer(GL_ARRAY_BUFFER, 0)
  glBindVertexArray(0)
end
lighting(lights) click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 121
def lighting(lights)
  Shader.use("lighting") do |shader|
    glBindVertexArray(@g_buffer.screen_vbo)

    glDisable(GL_DEPTH_TEST)
    glEnable(GL_BLEND)

    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:diffuse))
    shader.uniform_integer("diffuse", 0)

    glActiveTexture(GL_TEXTURE1)
    glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:position))
    shader.uniform_integer("position", 1)

    glActiveTexture(GL_TEXTURE2)
    glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:texcoord))
    shader.uniform_integer("texcoord", 2)

    glActiveTexture(GL_TEXTURE3)
    glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:normal))
    shader.uniform_integer("normal", 3)

    glActiveTexture(GL_TEXTURE4)
    glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:depth))
    shader.uniform_integer("depth", 4)

    lights.each_with_index do |light, _i|
      shader.uniform_integer("light[0].type", light.type)
      shader.uniform_vec3("light[0].direction", light.direction)
      shader.uniform_vec3("light[0].position", light.position)
      shader.uniform_vec3("light[0].diffuse", light.diffuse)
      shader.uniform_vec3("light[0].ambient", light.ambient)
      shader.uniform_vec3("light[0].specular", light.specular)

      glDrawArrays(GL_TRIANGLES, 0, @g_buffer.vertices.size)
    end

    glBindVertexArray(0)
  end
end
post_processing() click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 163
def post_processing
end
render(camera, lights, entities) click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 22
def render(camera, lights, entities)
  glViewport(0, 0, @width, @height)
  glEnable(GL_DEPTH_TEST)

  if Shader.available?("g_buffer") && Shader.available?("lighting")
    @g_buffer.bind_for_writing
    gl_error?

    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    Shader.use("g_buffer") do |shader|
      gl_error?

      entities.each do |entity|
        next unless entity.visible && entity.renderable

        shader.uniform_transform("projection", camera.projection_matrix)
        shader.uniform_transform("view", camera.view_matrix)
        shader.uniform_transform("model", entity.model_matrix)
        shader.uniform_vec3("cameraPosition", camera.position)

        gl_error?
        draw_model(entity.model, shader)
        entity.draw
      end
    end

    @g_buffer.unbind_framebuffer
    gl_error?

    @g_buffer.bind_for_reading
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)

    lighting(lights)
    gl_error?

    post_processing
    gl_error?

    # render_framebuffer
    gl_error?

    @g_buffer.unbind_framebuffer
    gl_error?
  else
    unless @@immediate_mode_warning
      puts "Shaders are disabled or failed to compile, using immediate mode for rendering..."
    end
    @@immediate_mode_warning = true

    gl_error?
    lights.each(&:draw)
    camera.draw

    glEnable(GL_NORMALIZE)
    entities.each do |entity|
      next unless entity.visible && entity.renderable

      glPushMatrix

      glTranslatef(entity.position.x, entity.position.y, entity.position.z)
      glScalef(entity.scale.x, entity.scale.y, entity.scale.z)
      glRotatef(entity.orientation.x, 1.0, 0, 0)
      glRotatef(entity.orientation.y, 0, 1.0, 0)
      glRotatef(entity.orientation.z, 0, 0, 1.0)

      gl_error?
      draw_mesh(entity.model)
      entity.draw
      glPopMatrix
    end
  end

  gl_error?
end
render_framebuffer() click to toggle source
# File lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb, line 166
def render_framebuffer
  if Shader.available?("lighting")
    Shader.use("lighting") do |shader|
      glBindVertexArray(@g_buffer.screen_vbo)

      glDisable(GL_DEPTH_TEST)
      glEnable(GL_BLEND)

      glActiveTexture(GL_TEXTURE0)
      glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:diffuse))
      shader.uniform_integer("diffuse_texture", 0)

      glDrawArrays(GL_TRIANGLES, 0, @g_buffer.vertices.size)

      glBindVertexArray(0)
    end
  end
end