mirror of
https://github.com/cyberarm/i-mic-fps.git
synced 2025-12-15 15:42:35 +00:00
Fixed lighting artifacts caused by untransformed normals, added 'Scene' for holding objects for rendering, added turn table models to menus using a scene, misc other changes.
This commit is contained in:
@@ -100,6 +100,9 @@ require_relative "lib/map_parser"
|
||||
require_relative "lib/manifest"
|
||||
require_relative "lib/map"
|
||||
|
||||
require_relative "lib/scene"
|
||||
require_relative "lib/scenes/turn_table"
|
||||
|
||||
require_relative "lib/crosshair"
|
||||
require_relative "lib/demo"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class IMICFPS
|
||||
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)
|
||||
def initialize(manifest:, map_entity: nil, spawnpoint: nil, backface_culling: true, run_scripts: true)
|
||||
@manifest = manifest
|
||||
|
||||
if map_entity
|
||||
@@ -41,7 +41,7 @@ class IMICFPS
|
||||
@last_position = Vector.new(@position.x, @position.y, @position.z)
|
||||
|
||||
@sandboxes = []
|
||||
load_scripts
|
||||
load_scripts if run_scripts
|
||||
|
||||
setup
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class IMICFPS
|
||||
id:,
|
||||
type: Light::POINT,
|
||||
ambient: Vector.new(0.5, 0.5, 0.5, 1),
|
||||
diffuse: Vector.new(1, 0.5, 0, 1),
|
||||
diffuse: Vector.new(1, 1, 1, 1),
|
||||
specular: Vector.new(0.2, 0.2, 0.2, 1),
|
||||
position: Vector.new(0, 0, 0, 0),
|
||||
intensity: 1
|
||||
|
||||
@@ -14,7 +14,7 @@ class IMICFPS
|
||||
@lights = []
|
||||
|
||||
@collision_manager = CollisionManager.new(map: self)
|
||||
@renderer = Renderer.new
|
||||
@renderer = window.renderer
|
||||
Publisher.new
|
||||
end
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class IMICFPS
|
||||
# @g_buffer.bind_for_writing
|
||||
gl_error?
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
# glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
|
||||
Shader.use("default") do |shader|
|
||||
lights.each_with_index do |light, i|
|
||||
@@ -42,7 +42,7 @@ class IMICFPS
|
||||
end
|
||||
end
|
||||
|
||||
# @g_buffer.unbind_framebuffer
|
||||
@g_buffer.unbind_framebuffer
|
||||
gl_error?
|
||||
else
|
||||
puts "Shader 'default' failed to compile, using immediate mode for rendering..." unless @@immediate_mode_warning
|
||||
|
||||
@@ -9,6 +9,18 @@ class IMICFPS
|
||||
@opengl_renderer = OpenGLRenderer.new
|
||||
end
|
||||
|
||||
def preload_default_shaders
|
||||
shaders = ["default"]
|
||||
shaders.each do |shader|
|
||||
Shader.new(
|
||||
name: shader,
|
||||
includes_dir: "shaders/include",
|
||||
vertex: "shaders/vertex/#{shader}.glsl",
|
||||
fragment: "shaders/fragment/#{shader}.glsl"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def draw(camera, lights, entities)
|
||||
glViewport(0, 0, window.width, window.height)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
22
lib/scene.rb
Normal file
22
lib/scene.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
class IMICFPS
|
||||
class Scene
|
||||
attr_reader :camera, :entities, :lights
|
||||
|
||||
def initialize
|
||||
@camera = Camera.new(position: Vector.new)
|
||||
@entities = []
|
||||
@lights = []
|
||||
|
||||
setup
|
||||
end
|
||||
|
||||
def setup
|
||||
end
|
||||
|
||||
def draw
|
||||
end
|
||||
|
||||
def update(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
40
lib/scenes/turn_table.rb
Normal file
40
lib/scenes/turn_table.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
class IMICFPS
|
||||
class TurnTableScene < Scene
|
||||
def setup
|
||||
camera.field_of_view = 45
|
||||
lights << (Light.new(id: OpenGL::GL_LIGHT1, position: Vector.new(30, 10.0, 30), diffuse: Color.new(0, 0, 0), specular: Color.new(0, 0, 0)))
|
||||
lights << (Light.new(id: OpenGL::GL_LIGHT2, position: Vector.new(0, 10, 5), diffuse: Color.new(1.0, 1.0, 1.0), specular: Color.new(0, 0, 0)))
|
||||
|
||||
options = {
|
||||
"character": 0.25,
|
||||
"information_panel": 0.25,
|
||||
"purchase_terminal": 0.35,
|
||||
"door": 0.2,
|
||||
"ttank": 0.13,
|
||||
"alternate_tank": 0.065,
|
||||
"tree": 0.08,
|
||||
# "evergreen_tree": 0.08,
|
||||
"power_plant": 0.025,
|
||||
"war_factory": 0.03,
|
||||
"randomish_terrain": 0.004,
|
||||
"river_terrain": 0.004,
|
||||
}
|
||||
choice = options.keys.sample
|
||||
|
||||
@entity = Entity.new(manifest: Manifest.new(package: "base", name: choice), run_scripts: false)
|
||||
@entity.scale = Vector.new(1, 1, 1) * options[choice]
|
||||
@entity.position.x = 0.75
|
||||
@entity.position.y = -0.5
|
||||
@entity.position.z = -1.5
|
||||
@entity.bind_model
|
||||
|
||||
entities << @entity
|
||||
|
||||
@max_tilt = 5.0
|
||||
end
|
||||
|
||||
def update(dt)
|
||||
@entity.orientation.y += 10 * dt
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -13,7 +13,6 @@ class IMICFPS
|
||||
@dummy_entity = nil
|
||||
@assets = []
|
||||
@asset_index = 0
|
||||
add_asset(:shader, nil, "default")
|
||||
|
||||
add_asset(:model, @map_parser.terrain.package, @map_parser.terrain.name)
|
||||
add_asset(:model, @map_parser.skydome.package, @map_parser.skydome.name)
|
||||
@@ -43,6 +42,7 @@ class IMICFPS
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
@percentage.text = "#{((@asset_index.to_f / @assets.count) * 100.0).round}%"
|
||||
@act = true if @cycled
|
||||
|
||||
|
||||
@@ -8,21 +8,25 @@ class IMICFPS
|
||||
@base_color = Gosu::Color.rgb(255, 127, 0)
|
||||
@background_alpha = 200
|
||||
window.needs_cursor = true
|
||||
|
||||
@__version_text = CyberarmEngine::Text.new("<b>#{IMICFPS::NAME}</b> v#{IMICFPS::VERSION} (#{IMICFPS::RELEASE_NAME})")
|
||||
@__version_text.x = window.width - (@__version_text.width + 10)
|
||||
@__version_text.y = window.height - (@__version_text.height + 10)
|
||||
super(*args)
|
||||
end
|
||||
|
||||
def title(text, color = @base_color)
|
||||
@elements << Text.new(text, color: color, size: 100, x: 0, y: 15, alignment: :center)
|
||||
@elements << Text.new(text, color: color, size: 100, x: 0, y: 15)
|
||||
@_title = @elements.last
|
||||
end
|
||||
|
||||
def subtitle(text, color = Gosu::Color::WHITE)
|
||||
@elements << Text.new(text, color: color, size: 50, x: 0, y: 100, alignment: :center)
|
||||
@elements << Text.new(text, color: color, size: 50, x: 0, y: 100)
|
||||
@_subtitle = @elements.last
|
||||
end
|
||||
|
||||
def link(text, color = Gosu::Color.rgb(0,127,127), &block)
|
||||
text = Text.new(text, color: color, size: 50, x: 0, y: 100 + (60 * @elements.count), alignment: :center)
|
||||
text = Text.new(text, color: color, size: 50, x: 0, y: 100 + (60 * @elements.count))
|
||||
@elements << Link.new(text, self, block)
|
||||
end
|
||||
|
||||
@@ -30,38 +34,44 @@ class IMICFPS
|
||||
draw_background
|
||||
draw_menu_box
|
||||
draw_menu
|
||||
|
||||
@__version_text.draw
|
||||
|
||||
if window.scene
|
||||
window.gl(-1) do
|
||||
window.renderer.draw(window.scene.camera, window.scene.lights, window.scene.entities)
|
||||
end
|
||||
|
||||
window.scene.draw
|
||||
end
|
||||
end
|
||||
|
||||
def draw_background
|
||||
@background ||= Gosu.record(Gosu.screen_width, Gosu.screen_height) do
|
||||
((Gosu.screen_height+@slope)/@size).times do |i|
|
||||
fill_quad(
|
||||
0, i*@size,
|
||||
0, @slope+(i*@size),
|
||||
window.width/2, (-@slope)+(i*@size),
|
||||
window.width/2, i*@size,
|
||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha)
|
||||
)
|
||||
fill_quad(
|
||||
window.width, i*@size,
|
||||
window.width, @slope+(i*@size),
|
||||
window.width/2, (-@slope)+(i*@size),
|
||||
window.width/2, i*@size,
|
||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha)
|
||||
)
|
||||
end
|
||||
|
||||
((Gosu.screen_height+@slope)/@size).times do |i|
|
||||
fill_quad(
|
||||
0, i*@size,
|
||||
0, @slope+(i*@size),
|
||||
window.width/2, (-@slope)+(i*@size),
|
||||
window.width/2, i*@size,
|
||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha),
|
||||
-2
|
||||
)
|
||||
fill_quad(
|
||||
window.width, i*@size,
|
||||
window.width, @slope+(i*@size),
|
||||
window.width/2, (-@slope)+(i*@size),
|
||||
window.width/2, i*@size,
|
||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha),
|
||||
-2
|
||||
)
|
||||
end
|
||||
|
||||
@background.draw(0, 0, 0)
|
||||
end
|
||||
|
||||
def draw_menu_box
|
||||
draw_rect(
|
||||
window.width/4, 0,
|
||||
window.width/2, window.height,
|
||||
Gosu::Color.rgba(0, 0, 0, 150)
|
||||
# Gosu::Color.rgba(@base_color.red+@color_step, @base_color.green+@color_step, @base_color.blue+@color_step, 200)
|
||||
Gosu::Color.rgba(0, 0, 0, 150),
|
||||
)
|
||||
end
|
||||
|
||||
@@ -73,8 +83,16 @@ class IMICFPS
|
||||
|
||||
def update
|
||||
@elements.each do |e|
|
||||
e.x = window.width / 2 - e.width / 2
|
||||
e.update
|
||||
end
|
||||
|
||||
if window.scene
|
||||
window.scene.update(window.dt)
|
||||
end
|
||||
|
||||
@__version_text.x = window.width - (@__version_text.width + 10)
|
||||
@__version_text.y = window.height - (@__version_text.height + 10)
|
||||
end
|
||||
|
||||
def fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, color = Gosu::Color::WHITE, z = 0, mode = :default)
|
||||
@@ -125,6 +143,7 @@ class IMICFPS
|
||||
end
|
||||
|
||||
def x; text.x; end
|
||||
def x=(n); text.x = n; end
|
||||
def y; text.y; end
|
||||
def width; text.width; end
|
||||
def height; text.height; end
|
||||
|
||||
@@ -37,8 +37,6 @@ as a commandline argument to override reported version."
|
||||
message += linux_mesa_message if RUBY_PLATFORM =~ /linux/ && gl_version.downcase.include?(" mesa ")
|
||||
@old_gl_warning = Gosu::Image.from_markup(message, 24, align: :center)
|
||||
end
|
||||
|
||||
@text = CyberarmEngine::Text.new("<b>#{IMICFPS::NAME}</b> v#{IMICFPS::VERSION} (#{IMICFPS::RELEASE_NAME})")
|
||||
end
|
||||
|
||||
def draw
|
||||
@@ -47,10 +45,6 @@ as a commandline argument to override reported version."
|
||||
if @old_gl_warning
|
||||
@old_gl_warning.draw(window.width / 2 - @old_gl_warning.width / 2, window.height - (@old_gl_warning.height + 10), Float::INFINITY)
|
||||
end
|
||||
|
||||
@text.draw
|
||||
@text.x = window.width - (@text.width + 10)
|
||||
@text.y = window.height - (@text.height + 10)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class IMICFPS
|
||||
class Window < CyberarmEngine::Engine
|
||||
attr_accessor :number_of_vertices, :needs_cursor
|
||||
attr_reader :camera, :config
|
||||
attr_reader :renderer, :scene, :config
|
||||
|
||||
attr_reader :console, :delta_time
|
||||
def initialize(window_width = 1280, window_height = 720, fullscreen = false)
|
||||
@@ -23,6 +23,10 @@ class IMICFPS
|
||||
@console = Console.new
|
||||
Commands::Command.setup
|
||||
|
||||
@renderer = Renderer.new
|
||||
@renderer.preload_default_shaders
|
||||
@scene = TurnTableScene.new
|
||||
|
||||
at_exit do
|
||||
@config.save!
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
in vec3 outPosition;
|
||||
in vec3 outColor;
|
||||
in vec4 outNormal;
|
||||
in vec3 outNormal;
|
||||
in vec3 outUV;
|
||||
in float outTextureID;
|
||||
in float outHasTexture;
|
||||
@@ -12,7 +12,6 @@ in Light outLights[MAX_LIGHTS];
|
||||
in float outTotalLights;
|
||||
in vec3 outFragPos;
|
||||
in vec3 outCameraPos;
|
||||
in vec3 outInverseNormal;
|
||||
in float outDisableLighting;
|
||||
|
||||
uniform sampler2D diffuse_texture;
|
||||
@@ -55,7 +54,7 @@ vec3 calculateBasicLight(Light light) {
|
||||
|
||||
float specularStrength = 0.5;
|
||||
vec3 viewDir = normalize(outCameraPos - outFragPos);
|
||||
vec3 reflectDir = reflect(-lightDir, outInverseNormal);
|
||||
vec3 reflectDir = reflect(-lightDir, outNormal);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
||||
vec3 specular = specularStrength * spec * light.specular;
|
||||
|
||||
@@ -77,7 +76,7 @@ vec3 calculateLighting() {
|
||||
}
|
||||
|
||||
void main() {
|
||||
lokiVar = vec4(outColor, 1.0) + outNormal + vec4(outUV, 1.0) + vec4(outTextureID, 1.0, 1.0, 1.0);
|
||||
lokiVar = vec4(outColor, 1.0) + vec4(outNormal, 1.0) + vec4(outUV, 1.0) + vec4(outTextureID, 1.0, 1.0, 1.0);
|
||||
lokiVar = normalize(lokiVar);
|
||||
|
||||
vec3 result;
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
layout(location = 2) in vec4 inNormal;
|
||||
layout(location = 2) in vec3 inNormal;
|
||||
layout(location = 3) in vec3 inUV;
|
||||
layout(location = 4) in float inTextureID;
|
||||
|
||||
out vec3 outPosition;
|
||||
out vec3 outColor;
|
||||
out vec4 outNormal;
|
||||
out vec3 outNormal;
|
||||
out vec3 outUV;
|
||||
out float outTextureID;
|
||||
out float outHasTexture;
|
||||
@@ -19,7 +19,6 @@ out float outTotalLights;
|
||||
out vec3 outFragPos;
|
||||
out vec3 outViewPos;
|
||||
out vec3 outCameraPos;
|
||||
out vec3 outInverseNormal;
|
||||
out float outDisableLighting;
|
||||
|
||||
uniform mat4 projection;
|
||||
@@ -36,7 +35,7 @@ void main() {
|
||||
// projection * view * model * position
|
||||
outPosition = inPosition;
|
||||
outColor = inColor;
|
||||
outNormal= inNormal;
|
||||
outNormal= normalize(transpose(inverse(mat3(model))) * inNormal);
|
||||
outUV = inUV;
|
||||
outTextureID = inTextureID;
|
||||
outHasTexture = hasTexture;
|
||||
@@ -44,7 +43,6 @@ void main() {
|
||||
outTotalLights = totalLights;
|
||||
outCameraPos = cameraPos;
|
||||
outDisableLighting = disableLighting;
|
||||
outInverseNormal = mat3(transpose(inverse(model))) * vec3(inNormal);
|
||||
|
||||
outFragPos = vec3(model * vec4(inPosition, 1.0));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user