mirror of
https://github.com/cyberarm/i-mic-fps.git
synced 2025-12-15 23:52:35 +00:00
Added command to reload shaders at runtime, added support for shared scripts to Manifest, lights are now loadable from MapParser, misc changes.
This commit is contained in:
@@ -21,8 +21,10 @@ collision: "mesh"
|
|||||||
# Path to collision model or null to use `model`
|
# Path to collision model or null to use `model`
|
||||||
collision_mesh: null
|
collision_mesh: null
|
||||||
# Array of scripts to load, relative to package/name/scripts/
|
# Array of scripts to load, relative to package/name/scripts/
|
||||||
|
# Optionally shared scripts can be loaded from package/shared/scripts/ if prefixed with an exclaimation mark "!"
|
||||||
scripts: [
|
scripts: [
|
||||||
"script"
|
"script",
|
||||||
|
"!shared_script"
|
||||||
]
|
]
|
||||||
# Array of assets to preload that this asset uses/requires
|
# Array of assets to preload that this asset uses/requires
|
||||||
uses: [
|
uses: [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: "Alternate Tank"
|
name: "Alternate Tank"
|
||||||
model: "alternate_tank.obj"
|
model: "alternate_tank.obj"
|
||||||
scripts: [
|
scripts: [
|
||||||
"vehicle"
|
"!vehicle"
|
||||||
]
|
]
|
||||||
@@ -6,6 +6,6 @@ on.create do |event|
|
|||||||
map.insert_entity("base", "door", event.entity.position + Vector.new(3.3, 0, 6), Vector.new(0, 0, 0))
|
map.insert_entity("base", "door", event.entity.position + Vector.new(3.3, 0, 6), Vector.new(0, 0, 0))
|
||||||
map.insert_entity("base", "door", event.entity.position + Vector.new(3.3, 0, 6), Vector.new(0, 180, 0))
|
map.insert_entity("base", "door", event.entity.position + Vector.new(3.3, 0, 6), Vector.new(0, 180, 0))
|
||||||
|
|
||||||
map.insert_particle_emitter(Vector.new(3.0, 15.379, 0.029), Texture.new("base", "shared", "particles", "smoke", "smoke.png"))
|
map.insert_particle_emitter(Vector.new(3.0, 15.379, 0.029), Texture.new(path: ["base", "shared", "particles", "smoke", "smoke.png"]))
|
||||||
map.insert_particle_emitter(Vector.new(5.0, 15.379, 0.029), Texture.new("base", "shared", "particles", "smoke", "smoke.png"))
|
map.insert_particle_emitter(Vector.new(5.0, 15.379, 0.029), Texture.new(path: ["base", "shared", "particles", "smoke", "smoke.png"]))
|
||||||
end
|
end
|
||||||
@@ -19,7 +19,7 @@ class IMICFPS
|
|||||||
|
|
||||||
@devisor = 500.0
|
@devisor = 500.0
|
||||||
@name_image = Gosu::Image.from_text("#{Etc.getlogin}", 100, font: "Consolas", align: :center)
|
@name_image = Gosu::Image.from_text("#{Etc.getlogin}", 100, font: "Consolas", align: :center)
|
||||||
@name_texture_id = Texture.new(@name_image).id
|
@name_texture_id = Texture.new(image: @name_image).id
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw_nameplate
|
def draw_nameplate
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ class IMICFPS
|
|||||||
def initialize(
|
def initialize(
|
||||||
id:,
|
id:,
|
||||||
type: Light::POINT,
|
type: Light::POINT,
|
||||||
ambient: Vector.new(0.5, 0.5, 0.5, 1),
|
ambient: Vector.new(0.5, 0.5, 0.5),
|
||||||
diffuse: Vector.new(1, 1, 1, 1),
|
diffuse: Vector.new(1, 1, 1),
|
||||||
specular: Vector.new(0.2, 0.2, 0.2, 1),
|
specular: Vector.new(0.2, 0.2, 0.2),
|
||||||
position: Vector.new(0, 0, 0, 0),
|
position: Vector.new(0, 0, 0),
|
||||||
intensity: 1
|
intensity: 1
|
||||||
)
|
)
|
||||||
@light_id = id
|
@light_id = id
|
||||||
|
|||||||
@@ -35,7 +35,16 @@ class IMICFPS
|
|||||||
def parse_scripts(scripts)
|
def parse_scripts(scripts)
|
||||||
list = []
|
list = []
|
||||||
scripts.each do |script|
|
scripts.each do |script|
|
||||||
list << Script.new(script, File.read("#{file_path}/scripts/#{script}.rb"))
|
path = ""
|
||||||
|
|
||||||
|
if script.start_with?("!")
|
||||||
|
script = script.sub("!", "")
|
||||||
|
path = File.expand_path("../shared/", file_path) + "/scripts/" + script
|
||||||
|
else
|
||||||
|
path = "#{file_path}/scripts/#{script}"
|
||||||
|
end
|
||||||
|
|
||||||
|
list << Script.new(script, File.read("#{path}.rb"))
|
||||||
end
|
end
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|||||||
23
lib/map.rb
23
lib/map.rb
@@ -6,8 +6,8 @@ class IMICFPS
|
|||||||
|
|
||||||
attr_reader :collision_manager
|
attr_reader :collision_manager
|
||||||
attr_reader :gravity
|
attr_reader :gravity
|
||||||
def initialize(map_loader:, gravity: IMICFPS::EARTH_GRAVITY)
|
def initialize(map_parser:, gravity: IMICFPS::EARTH_GRAVITY)
|
||||||
@map_loader = map_loader
|
@map_parser = map_parser
|
||||||
@gravity = gravity
|
@gravity = gravity
|
||||||
|
|
||||||
@entities = []
|
@entities = []
|
||||||
@@ -19,23 +19,26 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
add_entity(Terrain.new(map_entity: @map_loader.terrain, manifest: Manifest.new(package: @map_loader.terrain.package, name: @map_loader.terrain.name)))
|
add_entity(Terrain.new(map_entity: @map_parser.terrain, manifest: Manifest.new(package: @map_parser.terrain.package, name: @map_parser.terrain.name)))
|
||||||
|
|
||||||
add_entity(Skydome.new(map_entity: @map_loader.skydome, manifest: Manifest.new(package: @map_loader.skydome.package, name: @map_loader.skydome.name), backface_culling: false))
|
add_entity(Skydome.new(map_entity: @map_parser.skydome, manifest: Manifest.new(package: @map_parser.skydome.package, name: @map_parser.skydome.name), backface_culling: false))
|
||||||
|
|
||||||
@map_loader.entities.each do |ent|
|
@map_parser.lights.each do |l|
|
||||||
|
add_light(Light.new(id: available_light, position: l.position, diffuse: l.diffuse, ambient: l.ambient, specular: l.specular, intensity: l.intensity))
|
||||||
|
end
|
||||||
|
|
||||||
|
@map_parser.entities.each do |ent|
|
||||||
add_entity(Entity.new(map_entity: ent, manifest: Manifest.new(package: ent.package, name: ent.name)))
|
add_entity(Entity.new(map_entity: ent, manifest: Manifest.new(package: ent.package, name: ent.name)))
|
||||||
end
|
end
|
||||||
|
|
||||||
add_entity(Player.new(spawnpoint: @map_loader.spawnpoints.sample, manifest: Manifest.new(package: "base", name: "character")))
|
add_entity(Player.new(spawnpoint: @map_parser.spawnpoints.sample, manifest: Manifest.new(package: "base", name: "character")))
|
||||||
|
|
||||||
# TODO: Load lights from MapParser
|
# add_light(Light.new(id: available_light, position: Vector.new(30, 10.0, 30)))
|
||||||
add_light(Light.new(id: available_light, position: Vector.new(30, 10.0, 30)))
|
# add_light(Light.new(id: available_light, position: Vector.new(0, 100, 0), diffuse: Color.new(1.0, 0.5, 0.1)))
|
||||||
add_light(Light.new(id: available_light, position: Vector.new(0, 100, 0), diffuse: Color.new(1.0, 0.5, 0.1)))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def data
|
def data
|
||||||
@map_loader
|
@map_parser
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(camera)
|
def render(camera)
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class MapParser
|
class MapParser
|
||||||
attr_reader :metadata, :terrain, :skydome, :entities, :spawnpoints
|
attr_reader :metadata, :terrain, :skydome, :lights, :entities, :spawnpoints
|
||||||
attr_reader :assets, :missing_assets
|
attr_reader :assets, :missing_assets
|
||||||
def initialize(map_file:)
|
def initialize(map_file:)
|
||||||
@metadata = MapParser::MetaData.new
|
@metadata = MapParser::MetaData.new
|
||||||
@terrain = MapParser::Entity.new
|
@terrain = MapParser::Entity.new
|
||||||
@skydome = MapParser::Entity.new
|
@skydome = MapParser::Entity.new
|
||||||
|
@lights = []
|
||||||
@entities = []
|
@entities = []
|
||||||
@spawnpoints = []
|
@spawnpoints = []
|
||||||
|
|
||||||
@@ -76,6 +77,36 @@ class IMICFPS
|
|||||||
raise "Map skydome data is missing!"
|
raise "Map skydome data is missing!"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if section = data["lights"]
|
||||||
|
section.each do |l|
|
||||||
|
light = MapParser::Light.new
|
||||||
|
light.type = IMICFPS::Light::POINT # TODO: fix me
|
||||||
|
light.position = Vector.new(
|
||||||
|
l["position"]["x"],
|
||||||
|
l["position"]["y"],
|
||||||
|
l["position"]["z"]
|
||||||
|
)
|
||||||
|
light.diffuse = Color.new(
|
||||||
|
l["diffuse"]["red"],
|
||||||
|
l["diffuse"]["green"],
|
||||||
|
l["diffuse"]["blue"]
|
||||||
|
)
|
||||||
|
light.ambient = Color.new(
|
||||||
|
l["ambient"]["red"],
|
||||||
|
l["ambient"]["green"],
|
||||||
|
l["ambient"]["blue"]
|
||||||
|
)
|
||||||
|
light.specular = Color.new(
|
||||||
|
l["specular"]["red"],
|
||||||
|
l["specular"]["green"],
|
||||||
|
l["specular"]["blue"]
|
||||||
|
)
|
||||||
|
light.intensity = l["intensity"]
|
||||||
|
|
||||||
|
@lights << light
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if section = data["entities"]
|
if section = data["entities"]
|
||||||
section.each do |ent|
|
section.each do |ent|
|
||||||
entity = MapParser::Entity.new
|
entity = MapParser::Entity.new
|
||||||
@@ -132,6 +163,7 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
MetaData = Struct.new(:name, :gamemode, :authors, :datetime, :thumbnail, :description)
|
MetaData = Struct.new(:name, :gamemode, :authors, :datetime, :thumbnail, :description)
|
||||||
|
Light = Struct.new(:type, :position, :diffuse, :ambient, :specular, :intensity)
|
||||||
Entity = Struct.new(:package, :name, :position, :orientation, :scale, :water_level, :scripts)
|
Entity = Struct.new(:package, :name, :position, :orientation, :scale, :water_level, :scripts)
|
||||||
SpawnPoint = Struct.new(:team, :position, :orientation)
|
SpawnPoint = Struct.new(:team, :position, :orientation)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_texture(texture_path)
|
def set_texture(texture_path)
|
||||||
@texture_id = Texture.new(texture_path).id
|
@texture_id = Texture.new(path: texture_path).id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class IMICFPS
|
|||||||
if id
|
if id
|
||||||
_model = @model.objects.find { |o| o.id == id }
|
_model = @model.objects.find { |o| o.id == id }
|
||||||
elsif name
|
elsif name
|
||||||
_model = @model.objects.find { |o| o.id == id }
|
_model = @model.objects.find { |o| o.name == name }
|
||||||
else
|
else
|
||||||
raise "Must provide either an id: or name:"
|
raise "Must provide either an id: or name:"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ class IMICFPS
|
|||||||
[:obj]
|
[:obj]
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(model)
|
|
||||||
@model = model
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse
|
def parse
|
||||||
lines = 0
|
lines = 0
|
||||||
list = File.read(@model.file_path).split("\n")
|
list = File.read(@model.file_path).split("\n")
|
||||||
|
|||||||
@@ -124,12 +124,14 @@ class IMICFPS
|
|||||||
glEnableClientState(GL_VERTEX_ARRAY)
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
glEnableClientState(GL_COLOR_ARRAY)
|
glEnableClientState(GL_COLOR_ARRAY)
|
||||||
glEnableClientState(GL_NORMAL_ARRAY)
|
glEnableClientState(GL_NORMAL_ARRAY)
|
||||||
|
|
||||||
if model.has_texture?
|
if model.has_texture?
|
||||||
glEnable(GL_TEXTURE_2D)
|
glEnable(GL_TEXTURE_2D)
|
||||||
glBindTexture(GL_TEXTURE_2D, model.materials[model.textured_material].texture_id)
|
glBindTexture(GL_TEXTURE_2D, model.materials[model.textured_material].texture_id)
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
glTexCoordPointer(3, GL_FLOAT, 0, o.flattened_textures)
|
glTexCoordPointer(3, GL_FLOAT, 0, o.flattened_textures)
|
||||||
end
|
end
|
||||||
|
|
||||||
glVertexPointer(4, GL_FLOAT, 0, o.flattened_vertices)
|
glVertexPointer(4, GL_FLOAT, 0, o.flattened_vertices)
|
||||||
glColorPointer(3, GL_FLOAT, 0, o.flattened_materials)
|
glColorPointer(3, GL_FLOAT, 0, o.flattened_materials)
|
||||||
glNormalPointer(GL_FLOAT, 0, o.flattened_normals)
|
glNormalPointer(GL_FLOAT, 0, o.flattened_normals)
|
||||||
@@ -160,10 +162,12 @@ class IMICFPS
|
|||||||
glDisableClientState(GL_VERTEX_ARRAY)
|
glDisableClientState(GL_VERTEX_ARRAY)
|
||||||
glDisableClientState(GL_COLOR_ARRAY)
|
glDisableClientState(GL_COLOR_ARRAY)
|
||||||
glDisableClientState(GL_NORMAL_ARRAY)
|
glDisableClientState(GL_NORMAL_ARRAY)
|
||||||
|
|
||||||
if model.has_texture?
|
if model.has_texture?
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
glDisable(GL_TEXTURE_2D)
|
glDisable(GL_TEXTURE_2D)
|
||||||
end
|
end
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE) if model.entity.backface_culling
|
glDisable(GL_CULL_FACE) if model.entity.backface_culling
|
||||||
glDisable(GL_COLOR_MATERIAL)
|
glDisable(GL_COLOR_MATERIAL)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class IMICFPS
|
|||||||
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)))
|
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 = {
|
options = {
|
||||||
|
# entity: scale
|
||||||
"character": 0.25,
|
"character": 0.25,
|
||||||
"information_panel": 0.25,
|
"information_panel": 0.25,
|
||||||
"purchase_terminal": 0.35,
|
"purchase_terminal": 0.35,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ class IMICFPS
|
|||||||
|
|
||||||
attr_reader :map
|
attr_reader :map
|
||||||
def setup
|
def setup
|
||||||
@map = Map.new(map_loader: @options[:map_parser])
|
@map = Map.new(map_parser: @options[:map_parser])
|
||||||
@map.setup
|
@map.setup
|
||||||
|
|
||||||
@player = @map.find_entity_by(name: "character")
|
@player = @map.find_entity_by(name: "character")
|
||||||
|
|||||||
@@ -11,18 +11,19 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :id
|
attr_reader :id
|
||||||
def initialize(*path)
|
def initialize(path: nil, image: nil, retro: false)
|
||||||
if path.size > 1
|
raise "keyword :path or :image must be provided!" if path.nil? && image.nil?
|
||||||
path = "#{GAME_ROOT_PATH}/assets/#{path.join("/")}"
|
@retro = retro
|
||||||
else
|
|
||||||
path = path.first
|
if path.is_a?(Array)
|
||||||
|
if path.size > 1
|
||||||
|
path = "#{GAME_ROOT_PATH}/assets/#{path.join("/")}"
|
||||||
|
else
|
||||||
|
path = path.first
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless path.is_a?(String)
|
@id = create_from_image(path ? path : image)
|
||||||
@id = create_from_image(path)
|
|
||||||
else
|
|
||||||
@id = from_cache(path)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def from_cache(path)
|
def from_cache(path)
|
||||||
@@ -51,7 +52,8 @@ class IMICFPS
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) if @retro
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) unless @retro
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||||
glGenerateMipmap(GL_TEXTURE_2D)
|
glGenerateMipmap(GL_TEXTURE_2D)
|
||||||
gl_error?
|
gl_error?
|
||||||
|
|||||||
62
lib/ui/commands/reload_shader_command.rb
Normal file
62
lib/ui/commands/reload_shader_command.rb
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class Commands
|
||||||
|
class ReloadShaderCommand < Command
|
||||||
|
def group
|
||||||
|
:reload_shader
|
||||||
|
end
|
||||||
|
|
||||||
|
def command
|
||||||
|
:reload_shader
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle(arguments, console)
|
||||||
|
if arguments.size > 2
|
||||||
|
console.stdin("to many arguments for #{Style.highlight("#{command}")}, got #{Style.error(arguments.size)} expected #{Style.notice(1)}.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
shader = nil
|
||||||
|
stdout = $stdout
|
||||||
|
$stdout = StringIO.new
|
||||||
|
|
||||||
|
case arguments.size
|
||||||
|
when 0
|
||||||
|
console.stdin( usage )
|
||||||
|
return
|
||||||
|
when 1
|
||||||
|
name = arguments.first
|
||||||
|
shader = Shader.new(
|
||||||
|
name: name,
|
||||||
|
includes_dir: "shaders/include",
|
||||||
|
vertex: "shaders/vertex/#{name}.glsl",
|
||||||
|
fragment: "shaders/fragment/#{name}.glsl"
|
||||||
|
)
|
||||||
|
when 2
|
||||||
|
vertex = arguments.first
|
||||||
|
fragment = arguments.last
|
||||||
|
shader = Shader.new(
|
||||||
|
name: vertex,
|
||||||
|
includes_dir: "shaders/include",
|
||||||
|
vertex: "shaders/vertex/#{vertex}.glsl",
|
||||||
|
fragment: "shaders/fragment/#{fragment}.glsl"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
string = $stdout.string
|
||||||
|
|
||||||
|
if shader.compiled?
|
||||||
|
console.stdin("#{Style.notice("Successfully reloaded shader")}: #{shader.name}")
|
||||||
|
else
|
||||||
|
console.stdin("#{Style.error("Failed to reload #{shader.name}")}")
|
||||||
|
console.stdin(string)
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
$stdout = stdout
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage
|
||||||
|
"#{Style.highlight(command)} #{Style.notice("vertex_name [fragment_name]")}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -20,6 +20,57 @@
|
|||||||
"scale":0.08
|
"scale":0.08
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"lights":[
|
||||||
|
{
|
||||||
|
"type":"directional",
|
||||||
|
"intensity": 1,
|
||||||
|
"position": {
|
||||||
|
"x":30,
|
||||||
|
"y":10,
|
||||||
|
"z":30
|
||||||
|
},
|
||||||
|
"diffuse": {
|
||||||
|
"red":1,
|
||||||
|
"green":1,
|
||||||
|
"blue":1
|
||||||
|
},
|
||||||
|
"ambient": {
|
||||||
|
"red":0.5,
|
||||||
|
"green":0.5,
|
||||||
|
"blue":0.5
|
||||||
|
},
|
||||||
|
"specular": {
|
||||||
|
"red":0.2,
|
||||||
|
"green":0.2,
|
||||||
|
"blue":0.2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type":"directional",
|
||||||
|
"intensity": 1,
|
||||||
|
"position": {
|
||||||
|
"x":0,
|
||||||
|
"y":100,
|
||||||
|
"z":0
|
||||||
|
},
|
||||||
|
"diffuse": {
|
||||||
|
"red":1,
|
||||||
|
"green":0.5,
|
||||||
|
"blue":0.1
|
||||||
|
},
|
||||||
|
"ambient": {
|
||||||
|
"red":0.5,
|
||||||
|
"green":0.5,
|
||||||
|
"blue":0.5
|
||||||
|
},
|
||||||
|
"specular": {
|
||||||
|
"red":0.2,
|
||||||
|
"green":0.2,
|
||||||
|
"blue":0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
"entities":[
|
"entities":[
|
||||||
{
|
{
|
||||||
"package":"base",
|
"package":"base",
|
||||||
|
|||||||
Reference in New Issue
Block a user