diff --git a/Gemfile b/Gemfile index 07faf7c..ac4e0d6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,5 @@ source "https://rubygems.org" -gem "opengl-bindings" +gem "opengl-bindings", require: "opengl" gem "cyberarm_engine" group(:packaging) do diff --git a/lib/game_objects/camera.rb b/lib/game_objects/camera.rb index 6c06d06..773e29f 100644 --- a/lib/game_objects/camera.rb +++ b/lib/game_objects/camera.rb @@ -72,7 +72,7 @@ class IMICFPS # 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, @max_view_distance) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) - glRotatef(@orientation.z, 1, 0, 0) + glRotatef(@orientation.x, 1, 0, 0) glRotatef(@orientation.y, 0, 1, 0) glTranslatef(-@position.x, -@position.y, -@position.z) glMatrixMode(GL_MODELVIEW) # The modelview matrix is where object information is stored. @@ -87,8 +87,8 @@ class IMICFPS @orientation.y -= delta @orientation.y %= 360.0 - @orientation.z -= Float(@true_mouse.y - self.mouse_y) / (@mouse_sensitivity * @field_of_view) * 70 - @orientation.z = @orientation.z.clamp(-90.0, 90.0) + @orientation.x -= Float(@true_mouse.y - self.mouse_y) / (@mouse_sensitivity * @field_of_view) * 70 + @orientation.x = @orientation.x.clamp(-90.0, 90.0) if @entity @entity.orientation.y += delta @@ -170,27 +170,15 @@ class IMICFPS end def aspect_ratio - window.width / window.height + window.width / window.height.to_f 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 - ] - ) + Transform.perspective(@field_of_view, aspect_ratio, @min_view_distance, @max_view_distance) end def view_matrix - Transform.identity# Transform.rotate_3d(@orientation) * Transform.translate_3d(@position) + Transform.translate_3d(@position * -1) * Transform.rotate_3d(@orientation) end end end diff --git a/lib/game_objects/entity.rb b/lib/game_objects/entity.rb index 4feb353..a623b22 100644 --- a/lib/game_objects/entity.rb +++ b/lib/game_objects/entity.rb @@ -119,7 +119,7 @@ class IMICFPS end def model_matrix - Transform.rotate_3d(@orientation) * Transform.translate_3d(@position) + Transform.rotate_3d(@orientation) * Transform.scale_3d(@scale) * Transform.translate_3d(@position) end end end diff --git a/lib/model.rb b/lib/model.rb index c758d42..9292a43 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -35,9 +35,11 @@ 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 + if Shader.available?("default") + allocate_gl_objects + populate_vertex_buffer + configure_vao + end @objects.each {|o| @vertex_count+=o.vertices.size} @objects.each_with_index do |o, i| @@ -119,14 +121,14 @@ class IMICFPS end def populate_vertex_buffer - verts = [] + pos = [] colors = [] norms = [] uvs = [] tex_ids = [] @faces.each do |face| - verts << face.vertices.map { |vert| [vert.x, vert.y, vert.z] } + pos << face.vertices.map { |vert| [vert.x, vert.y, vert.z] } colors << face.colors.map { |vert| [vert.x, vert.y, vert.z] } norms << face.normals.map { |vert| [vert.x, vert.y, vert.z, vert.weight] } @@ -137,20 +139,20 @@ class IMICFPS end glBindBuffer(GL_ARRAY_BUFFER, @positions_buffer_id) - glBufferData(GL_ARRAY_BUFFER, 3 * verts.size * Fiddle::SIZEOF_FLOAT, verts.flatten.pack("f*"), GL_STATIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, pos.flatten.size * Fiddle::SIZEOF_FLOAT, pos.flatten.pack("f*"), GL_STATIC_DRAW) glBindBuffer(GL_ARRAY_BUFFER, @colors_buffer_id) - glBufferData(GL_ARRAY_BUFFER, 3 * colors.size * Fiddle::SIZEOF_FLOAT, colors.flatten.pack("f*"), GL_STATIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, colors.flatten.size * Fiddle::SIZEOF_FLOAT, colors.flatten.pack("f*"), GL_STATIC_DRAW) glBindBuffer(GL_ARRAY_BUFFER, @normals_buffer_id) - glBufferData(GL_ARRAY_BUFFER, 4 * norms.size * Fiddle::SIZEOF_FLOAT, norms.flatten.pack("f*"), GL_STATIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, norms.flatten.size * Fiddle::SIZEOF_FLOAT, norms.flatten.pack("f*"), GL_STATIC_DRAW) if has_texture? glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id) - glBufferData(GL_ARRAY_BUFFER, 3 * uvs.size * Fiddle::SIZEOF_FLOAT, uvs.flatten.pack("f*"), GL_STATIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, uvs.flatten.size * Fiddle::SIZEOF_FLOAT, uvs.flatten.pack("f*"), GL_STATIC_DRAW) glBindBuffer(GL_ARRAY_BUFFER, @textures_buffer_id) - glBufferData(GL_ARRAY_BUFFER, 1 * tex_ids.size * Fiddle::SIZEOF_FLOAT, tex_ids.flatten.pack("f*"), GL_STATIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, tex_ids.flatten.size * Fiddle::SIZEOF_FLOAT, tex_ids.flatten.pack("f*"), GL_STATIC_DRAW) end glBindBuffer(GL_ARRAY_BUFFER, 0) @@ -159,12 +161,6 @@ class IMICFPS def configure_vao glBindVertexArray(@vertex_array_id) - glEnableVertexAttribArray(0) - glEnableVertexAttribArray(1) - glEnableVertexAttribArray(2) - glEnableVertexAttribArray(3) - glEnableVertexAttribArray(4) - program = Shader.get("default").program # index, size, type, normalized, stride, pointer @@ -180,20 +176,17 @@ class IMICFPS glBindBuffer(GL_ARRAY_BUFFER, @normals_buffer_id) glVertexAttribPointer(glGetAttribLocation(program, "inNormal"), 4, GL_FLOAT, GL_FALSE, 0, nil) handleGlError - # uvs - glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id) - glVertexAttribPointer(glGetAttribLocation(program, "inUV"), 3, GL_FLOAT, GL_FALSE, 0, nil) - handleGlError - # texture ids - glBindBuffer(GL_ARRAY_BUFFER, @textures_buffer_id) - glVertexAttribPointer(glGetAttribLocation(program, "inTextureID"), 1, GL_FLOAT, GL_FALSE, 0, nil) - handleGlError - glDisableVertexAttribArray(4) - glDisableVertexAttribArray(3) - glDisableVertexAttribArray(2) - glDisableVertexAttribArray(1) - glDisableVertexAttribArray(0) + if has_texture? + # uvs + glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id) + glVertexAttribPointer(glGetAttribLocation(program, "inUV"), 3, GL_FLOAT, GL_FALSE, 0, nil) + handleGlError + # texture ids + glBindBuffer(GL_ARRAY_BUFFER, @textures_buffer_id) + glVertexAttribPointer(glGetAttribLocation(program, "inTextureID"), 1, GL_FLOAT, GL_FALSE, 0, nil) + handleGlError + end glBindBuffer(GL_ARRAY_BUFFER, 0) glBindVertexArray(0) @@ -201,6 +194,7 @@ class IMICFPS def build_collision_tree @aabb_tree = AABBTree.new + @faces.each do |face| box = BoundingBox.new box.min = face.vertices.first.dup @@ -215,10 +209,11 @@ class IMICFPS end # FIXME: Handle negatives - box.min -= Vector.new(-0.1, -0.1, -0.1) - box.max += Vector.new( 0.1, 0.1, 0.1) + box.min *= 1.5 + box.max *= 1.5 @aabb_tree.insert(face, box) end + puts @aabb_tree.inspect if $debug.get(:stats) end diff --git a/lib/renderer/opengl_renderer.rb b/lib/renderer/opengl_renderer.rb index 0c2bfad..b6c09c7 100644 --- a/lib/renderer/opengl_renderer.rb +++ b/lib/renderer/opengl_renderer.rb @@ -2,12 +2,17 @@ class IMICFPS class OpenGLRenderer include CommonMethods + def initialize + @immediate_mode_warning = false + end + def draw_object(camera, lights, object) if Shader.available?("default") Shader.use("default") do |shader| shader.set_uniform("projection", camera.projection_matrix) shader.set_uniform("view", camera.view_matrix) shader.set_uniform("model", object.model_matrix) + shader.set_uniform("hasTexture", object.model.has_texture?) # TODO: Upload and use lights @@ -16,10 +21,12 @@ class IMICFPS object.draw end else + puts "Shader 'default' failed to compile, using immediate mode for rendering..." unless @immediate_mode_warning + @immediate_mode_warning = true + handleGlError lights.each(&:draw) camera.draw - glEnable(GL_DEPTH_TEST) glEnable(GL_NORMALIZE) glPushMatrix @@ -44,14 +51,18 @@ class IMICFPS glEnableVertexAttribArray(0) glEnableVertexAttribArray(1) glEnableVertexAttribArray(2) - glEnableVertexAttribArray(3) - glEnableVertexAttribArray(4) + if model.has_texture? + glEnableVertexAttribArray(3) + glEnableVertexAttribArray(4) + end - glDrawArrays(GL_TRIANGLES, 0, model.vertices.count) - window.number_of_vertices+=model.vertices.size + glDrawArrays(GL_TRIANGLES, 0, model.faces.count * 3) + window.number_of_vertices += model.faces.count * 3 - glDisableVertexAttribArray(4) - glDisableVertexAttribArray(3) + if model.has_texture? + glDisableVertexAttribArray(4) + glDisableVertexAttribArray(3) + end glDisableVertexAttribArray(2) glDisableVertexAttribArray(1) glDisableVertexAttribArray(0) @@ -80,9 +91,6 @@ class IMICFPS glColorPointer(3, GL_FLOAT, 0, o.flattened_materials) glNormalPointer(GL_FLOAT, 0, o.flattened_normals) - # glBindBuffer(GL_ARRAY_BUFFER, model.vertices_buffer) - # glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0) - if $debug.get(:wireframe) # This is kinda expensive glDisable(GL_LIGHTING) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) diff --git a/lib/renderer/renderer.rb b/lib/renderer/renderer.rb index a82519b..07311a2 100644 --- a/lib/renderer/renderer.rb +++ b/lib/renderer/renderer.rb @@ -10,6 +10,9 @@ class IMICFPS end def draw(camera, lights, entities) + glViewport(0, 0, window.width, window.height) + glEnable(GL_DEPTH_TEST) + entities.each do |object| if object.visible && object.renderable # Render bounding boxes before transformation is applied diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb index 0b43d63..07834de 100644 --- a/lib/states/game_states/game.rb +++ b/lib/states/game_states/game.rb @@ -61,11 +61,12 @@ OpenGL Renderer: #{glGetString(GL_RENDERER)} OpenGL Version: #{glGetString(GL_VERSION)} OpenGL Shader Language Version: #{glGetString(GL_SHADING_LANGUAGE_VERSION)} -Camera pitch: #{@camera.orientation.z.round(2)} Yaw: #{@camera.orientation.y.round(2)} Roll #{@camera.orientation.x.round(2)} -Camera X:#{@camera.position.x.round(2)} Y:#{@camera.position.y.round(2)} Z:#{@camera.position.z.round(2)} -#{if @camera.entity then "Actor X:#{@camera.entity.position.x.round(2)} Y:#{@camera.entity.position.y.round(2)} Z:#{@camera.entity.position.z.round(2)}";end} -Field Of View: #{@camera.field_of_view} -Mouse Sesitivity: #{@camera.mouse_sensitivity} +Camera Pitch: #{@camera.orientation.x.round(2)} Yaw: #{@camera.orientation.y.round(2)} Roll #{@camera.orientation.z.round(2)} +Camera X: #{@camera.position.x.round(2)} Y: #{@camera.position.y.round(2)} Z: #{@camera.position.z.round(2)} +Camera Field Of View: #{@camera.field_of_view} +Camera Mouse Sesitivity: #{@camera.mouse_sensitivity} + +#{if @camera.entity then "Actor X: #{@camera.entity.position.x.round(2)} Y: #{@camera.entity.position.y.round(2)} Z: #{@camera.entity.position.z.round(2)}";end} Last Frame: #{Gosu.milliseconds - window.delta_time}ms (#{Gosu.fps} fps) Vertices: #{formatted_number(window.number_of_vertices)} diff --git a/shaders/fragment/default.glsl b/shaders/fragment/default.glsl index 60c5414..da61643 100644 --- a/shaders/fragment/default.glsl +++ b/shaders/fragment/default.glsl @@ -1,5 +1,6 @@ # version 330 core +in vec3 outPosition; in vec3 outColor; in vec4 outNormal; in vec3 outUV; @@ -11,5 +12,5 @@ vec4 lokiVar; void main() { lokiVar = vec4(outColor, 1.0) + outNormal + vec4(outUV, 1.0) + vec4(outTextureID, 1.0, 1.0, 1.0); lokiVar = normalize(lokiVar); - gl_FragColor = vec4(lokiVar); + gl_FragColor = vec4(outColor, 1.0); } \ No newline at end of file diff --git a/shaders/vertex/default.glsl b/shaders/vertex/default.glsl index 5ddbb82..c7b73b1 100644 --- a/shaders/vertex/default.glsl +++ b/shaders/vertex/default.glsl @@ -6,21 +6,26 @@ layout(location = 2) in vec4 inNormal; layout(location = 3) in vec3 inUV; layout(location = 4) in float inTextureID; +out vec3 outPosition; out vec3 outColor; out vec4 outNormal; out vec3 outUV; out float outTextureID; +out float outHasTexture; uniform mat4 projection; uniform mat4 view; uniform mat4 model; +uniform int hasTexture; void main() { // projection * view * model * position + outPosition = inPosition; outColor = inColor; outNormal= inNormal; outUV = inUV; outTextureID = inTextureID; + outHasTexture = hasTexture; gl_Position = projection * view * model * vec4(inPosition, 1.0); } \ No newline at end of file