From 6aeee41a71ac831e25038075f132e685255eddc9 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 5 Dec 2019 17:23:02 -0600 Subject: [PATCH] Progress towards modern gl made --- lib/ext/load_opengl.rb | 8 ++--- lib/game_objects/camera.rb | 39 ++++++++++++++++++----- lib/game_objects/entity.rb | 8 +++-- lib/map.rb | 9 ++---- lib/model.rb | 6 ++-- lib/renderer/opengl_renderer.rb | 41 +++++++++++++------------ lib/renderer/renderer.rb | 18 +++++------ lib/states/game_states/loading_state.rb | 18 ++++++++--- shaders/fragment/default.glsl | 2 +- shaders/vertex/default.glsl | 10 +++--- 10 files changed, 97 insertions(+), 62 deletions(-) diff --git a/lib/ext/load_opengl.rb b/lib/ext/load_opengl.rb index 2696e54..3b3240d 100644 --- a/lib/ext/load_opengl.rb +++ b/lib/ext/load_opengl.rb @@ -7,10 +7,10 @@ when :OPENGL_PLATFORM_MACOSX GLU.load_lib("libGLU.dylib", "/System/Library/Frameworks/OpenGL.framework/Libraries") when :OPENGL_PLATFORM_LINUX # Black magic to get GLSL 3.30 support on older Intel hardware - # if `glxinfo | egrep "OpenGL vendor|OpenGL renderer"`.include?("Intel") - # ENV["MESA_GL_VERSION_OVERRIDE"] = "3.3" - # ENV["MESA_GLSL_VERSION_OVERRIDE"] = "330" - # end + if ARGV.join.include?("--mesa-override") && `glxinfo | egrep "OpenGL vendor|OpenGL renderer"`.include?("Intel") + ENV["MESA_GL_VERSION_OVERRIDE"] = "3.3" + ENV["MESA_GLSL_VERSION_OVERRIDE"] = "330" + end gl_library_path = nil diff --git a/lib/game_objects/camera.rb b/lib/game_objects/camera.rb index d867726..6c06d06 100644 --- a/lib/game_objects/camera.rb +++ b/lib/game_objects/camera.rb @@ -4,11 +4,12 @@ class IMICFPS attr_accessor :field_of_view, :mouse_sensitivity attr_reader :entity, :position, :orientation, :mouse_captured - def initialize(position:, orientation: Vector.new(0, 0, 0), fov: 70.0, view_distance: 155.0) + def initialize(position:, orientation: Vector.new(0, 0, 0), fov: 70.0, min_view_distance: 0.1, max_view_distance: 155.0) @position = position @orientation = orientation @field_of_view = fov - @view_distance = view_distance + @min_view_distance = min_view_distance + @max_view_distance = max_view_distance @constant_pitch = 20.0 @entity = nil @@ -69,7 +70,7 @@ class IMICFPS glMatrixMode(GL_PROJECTION) # The projection matrix is responsible for adding perspective to our scene. glLoadIdentity # Resets current modelview matrix # Calculates aspect ratio of the window. Gets perspective view. 45 is degree viewing angle, (0.1, 100) are ranges how deep can we draw into the screen - gluPerspective(@field_of_view, window.width / window.height, 0.1, @view_distance) + gluPerspective(@field_of_view, window.width / window.height, 0.1, @max_view_distance) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glRotatef(@orientation.z, 1, 0, 0) glRotatef(@orientation.y, 0, 1, 0) @@ -158,14 +159,38 @@ class IMICFPS elsif InputMapper.is?(:increase_view_distance, id) # @field_of_view += 1 # @field_of_view = @field_of_view.clamp(1, 100) - @view_distance += 1 - @view_distance = @view_distance.clamp(1, 1000) + @max_view_distance += 1 + @max_view_distance = @max_view_distance.clamp(1, 1000) elsif InputMapper.is?(:decrease_view_distance, id) # @field_of_view -= 1 # @field_of_view = @field_of_view.clamp(1, 100) - @view_distance -= 1 - @view_distance = @view_distance.clamp(1, 1000) + @max_view_distance -= 1 + @max_view_distance = @max_view_distance.clamp(1, 1000) end end + + def aspect_ratio + window.width / window.height + end + + def projection_matrix + fov = 1 / Math.tan(@field_of_view / 2) # field of view + zn = @max_view_distance - @min_view_distance # near plane + zf = @max_view_distance + @min_view_distance # far plane + z_num = -(2 * @max_view_distance * @min_view_distance) / zn # something + + Transform.new( + [ + fov / aspect_ratio, 0, 0, 0, + 0, fov, 0, 0, + 0, 0, -zf / zn, z_num, + 0, 0, -1, 0 + ] + ) + end + + def view_matrix + Transform.identity# Transform.rotate_3d(@orientation) * Transform.translate_3d(@position) + end end end diff --git a/lib/game_objects/entity.rb b/lib/game_objects/entity.rb index 0e25911..4feb353 100644 --- a/lib/game_objects/entity.rb +++ b/lib/game_objects/entity.rb @@ -5,8 +5,8 @@ class IMICFPS class Entity include CommonMethods - attr_accessor :scale, :visible, :renderable, :backface_culling - attr_accessor :position, :orientation, :velocity + attr_accessor :visible, :renderable, :backface_culling + attr_accessor :position, :orientation, :scale, :velocity attr_reader :name, :debug_color, :bounding_box, :drag, :camera, :manifest def initialize(manifest:, map_entity: nil, spawnpoint: nil, backface_culling: true, auto_manage: true) @@ -117,5 +117,9 @@ class IMICFPS def normalize_bounding_box @bound_model.model.bounding_box.normalize(self) end + + def model_matrix + Transform.rotate_3d(@orientation) * Transform.translate_3d(@position) + end end end diff --git a/lib/map.rb b/lib/map.rb index f8eab9e..dadd8bb 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -13,7 +13,7 @@ class IMICFPS @lights = [] @collision_manager = CollisionManager.new(map: self) - @renderer = Renderer.new(map: self) + @renderer = Renderer.new Publisher.new end @@ -55,12 +55,7 @@ class IMICFPS glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen and the depth buffer glError? - @lights.each(&:draw) - - camera.draw - glEnable(GL_DEPTH_TEST) - - @renderer.draw + @renderer.draw(camera, @lights, @entities) end end diff --git a/lib/model.rb b/lib/model.rb index af17e24..e8b1482 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -37,9 +37,9 @@ class IMICFPS puts "#{@file_path.split('/').last} took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)-start_time)/1000.0).round(2)} seconds to parse" if $debug.get(:stats) - # allocate_gl_objects - # populate_vertex_buffer - # configure_vao + allocate_gl_objects + populate_vertex_buffer + configure_vao @objects.each {|o| @vertex_count+=o.vertices.size} @objects.each_with_index do |o, i| diff --git a/lib/renderer/opengl_renderer.rb b/lib/renderer/opengl_renderer.rb index 2534e0d..97b2e2f 100644 --- a/lib/renderer/opengl_renderer.rb +++ b/lib/renderer/opengl_renderer.rb @@ -2,37 +2,40 @@ class IMICFPS class OpenGLRenderer include CommonMethods - def draw_object(object) - handleGlError - - glEnable(GL_NORMALIZE) - glPushMatrix - - glTranslatef(object.position.x, object.position.y, object.position.z) - glScalef(object.scale.x, object.scale.y, object.scale.z) - glRotatef(object.orientation.x, 1.0, 0, 0) - glRotatef(object.orientation.y, 0, 1.0, 0) - glRotatef(object.orientation.z, 0, 0, 1.0) - - handleGlError - + def draw_object(camera, lights, object) if Shader.available?("ddefault") Shader.use("default") do |shader| - glUniform3f(shader.attribute_location("worldPosition"), object.position.x, object.position.y, object.position.z) + shader.set_uniform("projection", camera.projection_matrix) + shader.set_uniform("view", camera.view_matrix) + shader.set_uniform("model", object.model_matrix) + + # TODO: Upload and use lights handleGlError - draw_mesh(object.model) - # draw_model(object.model) + draw_model(object.model) object.draw end else + handleGlError + lights.each(&:draw) + camera.draw + glEnable(GL_DEPTH_TEST) + + glEnable(GL_NORMALIZE) + glPushMatrix + + glTranslatef(object.position.x, object.position.y, object.position.z) + glScalef(object.scale.x, object.scale.y, object.scale.z) + glRotatef(object.orientation.x, 1.0, 0, 0) + glRotatef(object.orientation.y, 0, 1.0, 0) + glRotatef(object.orientation.z, 0, 0, 1.0) + handleGlError draw_mesh(object.model) object.draw + glPopMatrix end - handleGlError - glPopMatrix handleGlError end diff --git a/lib/renderer/renderer.rb b/lib/renderer/renderer.rb index 87c490f..a82519b 100644 --- a/lib/renderer/renderer.rb +++ b/lib/renderer/renderer.rb @@ -4,25 +4,23 @@ class IMICFPS attr_reader :opengl_renderer, :bounding_box_renderer - def initialize(map:) - @map = map - - @bounding_box_renderer = BoundingBoxRenderer.new(map: map) + def initialize + # @bounding_box_renderer = BoundingBoxRenderer.new(map: map) @opengl_renderer = OpenGLRenderer.new end - def draw - @map.entities.each do |object| + def draw(camera, lights, entities) + entities.each do |object| if object.visible && object.renderable # Render bounding boxes before transformation is applied - @bounding_box_renderer.create_bounding_box(object, object.model.bounding_box, object.debug_color, object.object_id) if $debug.get(:boundingboxes) + # @bounding_box_renderer.create_bounding_box(object, object.model.bounding_box, object.debug_color, object.object_id) if $debug.get(:boundingboxes) - @opengl_renderer.draw_object(object) + @opengl_renderer.draw_object(camera, lights, object) end end - @bounding_box_renderer.draw_bounding_boxes if $debug.get(:boundingboxes) - window.number_of_vertices+=@bounding_box_renderer.vertex_count if $debug.get(:boundingboxes) + # @bounding_box_renderer.draw_bounding_boxes if $debug.get(:boundingboxes) + # window.number_of_vertices+=@bounding_box_renderer.vertex_count if $debug.get(:boundingboxes) # @bounding_box_renderer.bounding_boxes.clear end diff --git a/lib/states/game_states/loading_state.rb b/lib/states/game_states/loading_state.rb index 2498fdb..915fb93 100644 --- a/lib/states/game_states/loading_state.rb +++ b/lib/states/game_states/loading_state.rb @@ -13,7 +13,7 @@ class IMICFPS @dummy_entity = nil @assets = [] @asset_index = 0 - # add_asset(:shader, nil, "default") + add_asset(:shader, nil, "default") add_asset(:model, @map_loader.terrain.package, @map_loader.terrain.name) add_asset(:model, @map_loader.skydome.package, @map_loader.skydome.name) @@ -55,7 +55,8 @@ class IMICFPS when :model ModelLoader.new(manifest: hash[:manifest], entity: @dummy_entity) when :shader - Shader.new(name: hash[:name], vertex: "shaders/vertex/#{hash[:name]}.glsl", fragment: "shaders/fragment/#{hash[:name]}.glsl") + shader = Shader.new(name: hash[:name], vertex: "shaders/vertex/#{hash[:name]}.glsl", fragment: "shaders/fragment/#{hash[:name]}.glsl") + Shader.add(hash[:name], shader) if shader.compiled? else warn "Unknown asset: #{hash}" end @@ -79,9 +80,16 @@ class IMICFPS end def add_asset(type, package, name) - manifest = Manifest.new(manifest_file: IMICFPS.assets_path + "/#{package}/#{name}/manifest.yaml") - add_required_assets(manifest) - @assets << {type: type, manifest: manifest, package: package, name: name} + case type + when :model + manifest = Manifest.new(manifest_file: IMICFPS.assets_path + "/#{package}/#{name}/manifest.yaml") + add_required_assets(manifest) + @assets << {type: type, manifest: manifest, package: package, name: name} + when :shader + @assets << {type: type, manifest: manifest, package: package, name: name} + else + raise TypeError "Unable to load asset of type #{type}" + end end def add_required_assets(manifest) diff --git a/shaders/fragment/default.glsl b/shaders/fragment/default.glsl index 27cda02..60c5414 100644 --- a/shaders/fragment/default.glsl +++ b/shaders/fragment/default.glsl @@ -1,4 +1,4 @@ -# version 330 +# version 330 core in vec3 outColor; in vec4 outNormal; diff --git a/shaders/vertex/default.glsl b/shaders/vertex/default.glsl index d81d831..5ddbb82 100644 --- a/shaders/vertex/default.glsl +++ b/shaders/vertex/default.glsl @@ -1,4 +1,4 @@ -# version 330 +# version 330 core layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; @@ -11,14 +11,16 @@ out vec4 outNormal; out vec3 outUV; out float outTextureID; -uniform vec3 worldPosition; +uniform mat4 projection; +uniform mat4 view; +uniform mat4 model; void main() { - // projection * view * model * + // projection * view * model * position outColor = inColor; outNormal= inNormal; outUV = inUV; outTextureID = inTextureID; - gl_Position = vec4(worldPosition + inPosition, 1.0); + gl_Position = projection * view * model * vec4(inPosition, 1.0); } \ No newline at end of file