Class: Engine::Material
- Inherits:
-
Object
- Object
- Engine::Material
- Includes:
- Serializable
- Defined in:
- lib/engine/material.rb
Constant Summary collapse
- TEXTURE_SLOTS =
Cache texture slot constants to avoid const_get every frame
Array.new(32) { |i| Object.const_get("Engine::GL::TEXTURE#{i}") }
Instance Attribute Summary collapse
-
#shader ⇒ Object
readonly
Returns the value of attribute shader.
Class Method Summary collapse
- .bind_texture(slot, target, texture_id) ⇒ Object
- .create_1x1_texture(r, g, b, a) ⇒ Object
- .default_black_texture ⇒ Object
- .default_normal_texture ⇒ Object
- .default_white_texture ⇒ Object
Instance Method Summary collapse
- #set_cubemap(name, value) ⇒ Object
- #set_cubemap_array(name, value) ⇒ Object
- #set_float(name, value) ⇒ Object
- #set_int(name, value) ⇒ Object
- #set_mat4(name, value) ⇒ Object
-
#set_runtime_texture(name, gl_id) ⇒ Object
TODO: Runtime textures are not serializable.
- #set_texture(name, texture) ⇒ Object
- #set_texture_array(name, value) ⇒ Object
- #set_vec2(name, value) ⇒ Object
- #set_vec3(name, value) ⇒ Object
- #set_vec4(name, value) ⇒ Object
- #update_shader ⇒ Object
Methods included from Serializable
allowed_class?, #awake, get_class, included, register_class, #uuid
Instance Attribute Details
#shader ⇒ Object (readonly)
Returns the value of attribute shader.
17 18 19 |
# File 'lib/engine/material.rb', line 17 def shader @shader end |
Class Method Details
.bind_texture(slot, target, texture_id) ⇒ Object
12 13 14 15 |
# File 'lib/engine/material.rb', line 12 def self.bind_texture(slot, target, texture_id) Engine::GL.ActiveTexture(TEXTURE_SLOTS[slot]) Engine::GL.BindTexture(target, texture_id) end |
.create_1x1_texture(r, g, b, a) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/engine/material.rb', line 31 def self.create_1x1_texture(r, g, b, a) tex = ' ' * 4 Engine::GL.GenTextures(1, tex) texture_id = tex.unpack('L')[0] Engine::GL.BindTexture(Engine::GL::TEXTURE_2D, texture_id) pixel = [r, g, b, a].pack('C*') Engine::GL.TexImage2D(Engine::GL::TEXTURE_2D, 0, Engine::GL::RGBA, 1, 1, 0, Engine::GL::RGBA, Engine::GL::UNSIGNED_BYTE, pixel) Engine::GL.TexParameteri(Engine::GL::TEXTURE_2D, Engine::GL::TEXTURE_MIN_FILTER, Engine::GL::NEAREST) Engine::GL.TexParameteri(Engine::GL::TEXTURE_2D, Engine::GL::TEXTURE_MAG_FILTER, Engine::GL::NEAREST) texture_id end |
.default_black_texture ⇒ Object
27 28 29 |
# File 'lib/engine/material.rb', line 27 def self.default_black_texture @default_black_texture ||= create_1x1_texture(0, 0, 0, 255) end |
.default_normal_texture ⇒ Object
23 24 25 |
# File 'lib/engine/material.rb', line 23 def self.default_normal_texture @default_normal_texture ||= create_1x1_texture(128, 128, 255, 255) end |
.default_white_texture ⇒ Object
19 20 21 |
# File 'lib/engine/material.rb', line 19 def self.default_white_texture @default_white_texture ||= create_1x1_texture(255, 255, 255, 255) end |
Instance Method Details
#set_cubemap(name, value) ⇒ Object
77 78 79 |
# File 'lib/engine/material.rb', line 77 def set_cubemap(name, value) cubemaps[name] = value end |
#set_cubemap_array(name, value) ⇒ Object
85 86 87 |
# File 'lib/engine/material.rb', line 85 def set_cubemap_array(name, value) cubemap_arrays[name] = value end |
#set_float(name, value) ⇒ Object
59 60 61 |
# File 'lib/engine/material.rb', line 59 def set_float(name, value) floats[name] = value end |
#set_int(name, value) ⇒ Object
63 64 65 |
# File 'lib/engine/material.rb', line 63 def set_int(name, value) ints[name] = value end |
#set_mat4(name, value) ⇒ Object
43 44 45 |
# File 'lib/engine/material.rb', line 43 def set_mat4(name, value) mat4s[name] = value end |
#set_runtime_texture(name, gl_id) ⇒ Object
TODO: Runtime textures are not serializable. We need to revisit this to make render targets serializable or find another approach.
73 74 75 |
# File 'lib/engine/material.rb', line 73 def set_runtime_texture(name, gl_id) runtime_textures[name] = gl_id end |
#set_texture(name, texture) ⇒ Object
67 68 69 |
# File 'lib/engine/material.rb', line 67 def set_texture(name, texture) textures[name] = texture end |
#set_texture_array(name, value) ⇒ Object
81 82 83 |
# File 'lib/engine/material.rb', line 81 def set_texture_array(name, value) texture_arrays[name] = value end |
#set_vec2(name, value) ⇒ Object
47 48 49 |
# File 'lib/engine/material.rb', line 47 def set_vec2(name, value) vec2s[name] = value end |
#set_vec3(name, value) ⇒ Object
51 52 53 |
# File 'lib/engine/material.rb', line 51 def set_vec3(name, value) vec3s[name] = value end |
#set_vec4(name, value) ⇒ Object
55 56 57 |
# File 'lib/engine/material.rb', line 55 def set_vec4(name, value) vec4s[name] = value end |
#update_shader ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/engine/material.rb', line 89 def update_shader shader.use mat4s.each do |name, value| shader.set_mat4(name, value) end vec2s.each do |name, value| shader.set_vec2(name, value) end vec3s.each do |name, value| shader.set_vec3(name, value) end vec4s.each do |name, value| shader.set_vec4(name, value) end floats.each do |name, value| shader.set_float(name, value) end ints.each do |name, value| shader.set_int(name, value) end # Start with shader's expected textures (defaulting to nil for fallbacks) expected = shader.expected_textures.each_with_object({}) { |name, h| h[name] = nil } all_textures = expected.merge(textures).merge(runtime_textures) all_textures.each.with_index do |(name, value), slot| texture_id = if value.is_a?(Texture) value.texture elsif value value else fallback_texture_for(name) end Material.bind_texture(slot, Engine::GL::TEXTURE_2D, texture_id) shader.set_int(name, slot) end # Cubemaps start after regular textures cubemap_start_slot = all_textures.size cubemaps.each.with_index do |(name, value), i| slot = cubemap_start_slot + i texture_id = value || fallback_cubemap_for(name) Material.bind_texture(slot, Engine::GL::TEXTURE_CUBE_MAP, texture_id) shader.set_int(name, slot) end # Texture arrays start after cubemaps texture_array_start_slot = cubemap_start_slot + cubemaps.size texture_arrays.each.with_index do |(name, value), i| slot = texture_array_start_slot + i Material.bind_texture(slot, Engine::GL::TEXTURE_2D_ARRAY, value || 0) shader.set_int(name, slot) end # Cubemap arrays start after texture arrays cubemap_array_start_slot = texture_array_start_slot + texture_arrays.size cubemap_arrays.each.with_index do |(name, value), i| slot = cubemap_array_start_slot + i Material.bind_texture(slot, Engine::GL::TEXTURE_CUBE_MAP_ARRAY, value || 0) shader.set_int(name, slot) end end |