Kaynağa Gözat

Add basic material resource

Daniele Bartolini 11 yıl önce
ebeveyn
işleme
ddfa4d9c7a

+ 5 - 0
engine/compilers/bundle_compiler.cpp

@@ -51,6 +51,7 @@ namespace sprite_resource { extern void compile(Filesystem&, const char*, File*)
 namespace material_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace material_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace font_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace font_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace level_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace level_resource { extern void compile(Filesystem&, const char*, File*); }
+namespace shader_resource { extern void compile(Filesystem&, const char*, File*); }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 BundleCompiler::BundleCompiler()
 BundleCompiler::BundleCompiler()
@@ -179,6 +180,10 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir, con
 			{
 			{
 				level_resource::compile(root_fs, filename, out_file);
 				level_resource::compile(root_fs, filename, out_file);
 			}
 			}
+			else if (name.type == SHADER_TYPE)
+			{
+				shader_resource::compile(root_fs, filename, out_file);
+			}
 			else
 			else
 			{
 			{
 				CE_LOGE("Oops, unknown resource type!");
 				CE_LOGE("Oops, unknown resource type!");

+ 7 - 0
engine/device.cpp

@@ -56,6 +56,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "network_filesystem.h"
 #include "network_filesystem.h"
 #include "lua_system.h"
 #include "lua_system.h"
 #include "debug_line.h"
 #include "debug_line.h"
+#include "material_manager.h"
 
 
 #if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
 #if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
 	#include "bundle_compiler.h"
 	#include "bundle_compiler.h"
@@ -164,6 +165,9 @@ void Device::init()
 	graphics_system::init();
 	graphics_system::init();
 	debug_line::init();
 	debug_line::init();
 
 
+	CE_LOGD("Creating material manager...");
+	material_manager::init();
+
 	CE_LOGD("Creating lua system...");
 	CE_LOGD("Creating lua system...");
 	lua_system::init();
 	lua_system::init();
 	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)(lua_system::state());
 	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)(lua_system::state());
@@ -213,6 +217,9 @@ void Device::shutdown()
 	CE_DELETE(m_allocator, m_mouse);
 	CE_DELETE(m_allocator, m_mouse);
 	CE_DELETE(m_allocator, m_keyboard);
 	CE_DELETE(m_allocator, m_keyboard);
 
 
+	CE_LOGD("Releasing material manager...");
+	material_manager::shutdown();
+
 	CE_LOGD("Releasing renderer...");
 	CE_LOGD("Releasing renderer...");
 	debug_line::shutdown();
 	debug_line::shutdown();
 	graphics_system::shutdown();
 	graphics_system::shutdown();

+ 167 - 25
engine/renderers/material.cpp

@@ -26,51 +26,193 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include "material.h"
 #include "material.h"
 #include "material_resource.h"
 #include "material_resource.h"
+#include "memory.h"
+#include "random.h"
 #include "device.h"
 #include "device.h"
 #include "resource_manager.h"
 #include "resource_manager.h"
 #include "texture_resource.h"
 #include "texture_resource.h"
+#include <bgfx.h>
 
 
-namespace crown
+static const uint8_t vs_h[358] =
 {
 {
+	0x56, 0x53, 0x48, 0x02, 0x8c, 0xd4, 0x10, 0xbd, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod
+	0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, // elViewProj......
+	0x41, 0x01, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x65, // A...attribute me
+	0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, // diump vec2 a_pos
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, // ition;.attribute
+	0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, //  mediump vec2 a_
+	0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, // texcoord0;.varyi
+	0x6e, 0x67, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, // ng mediump vec2 
+	0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, // v_texcoord0;.uni
+	0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x6d, 0x61, 0x74, // form mediump mat
+	0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, // 4 u_modelViewPro
+	0x6a, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, // j;.void main ().
+	0x7b, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, // {.  mediump vec4
+	0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, //  tmpvar_1;.  tmp
+	0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x7a, 0x77, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, // var_1.zw = vec2(
+	0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, // 0.0, 1.0);.  tmp
+	0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, // var_1.xy = a_pos
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, // ition;.  gl_Posi
+	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, // tion = (u_modelV
+	0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, // iewProj * tmpvar
+	0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, // _1);.  v_texcoor
+	0x64, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, // d0 = a_texcoord0
+	0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00,                                                             // ;.}...
+};
 
 
-//-----------------------------------------------------------------------------
-Material::Material(const MaterialResource* mr)
-	: m_resource(mr)
+static const uint8_t fs_h[207] =
 {
 {
-	Blob vs_code = mr->get_vertex_shader();
-	Blob fs_code = mr->get_fragment_shader();
+	0x46, 0x53, 0x48, 0x02, 0x8c, 0xd4, 0x10, 0xbd, 0x01, 0x00, 0x08, 0x75, 0x5f, 0x61, 0x6c, 0x62, // FSH........u_alb
+	0x65, 0x64, 0x6f, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x76, 0x61, 0x72, // edo..........var
+	0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, // ying mediump vec
+	0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, // 2 v_texcoord0;.u
+	0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, // niform sampler2D
+	0x20, 0x75, 0x5f, 0x61, 0x6c, 0x62, 0x65, 0x64, 0x6f, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, //  u_albedo;.void 
+	0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, // main ().{.  lowp
+	0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, //  vec4 tmpvar_1;.
+	0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, //   tmpvar_1 = tex
+	0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x20, 0x28, 0x75, 0x5f, 0x61, 0x6c, 0x62, 0x65, 0x64, 0x6f, // ture2D (u_albedo
+	0x2c, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x29, 0x3b, 0x0a, // , v_texcoord0);.
+	0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, //   gl_FragColor =
+	0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00,       //  tmpvar_1;.}...
+};
 
 
-	printf("vs: %d, %p\n", vs_code.m_size, (void*) vs_code.m_data);
-	printf("fs: %d, %p\n", fs_code.m_size, (void*) fs_code.m_data);
+static const uint8_t vsc_h[358] =
+{
+	0x56, 0x53, 0x48, 0x02, 0x8c, 0xd4, 0x10, 0xbd, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod
+	0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, // elViewProj......
+	0x41, 0x01, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x65, // A...attribute me
+	0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, // diump vec2 a_pos
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, // ition;.attribute
+	0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, //  mediump vec2 a_
+	0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, // texcoord0;.varyi
+	0x6e, 0x67, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, // ng mediump vec2 
+	0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, // v_texcoord0;.uni
+	0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x6d, 0x61, 0x74, // form mediump mat
+	0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, // 4 u_modelViewPro
+	0x6a, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, // j;.void main ().
+	0x7b, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, // {.  mediump vec4
+	0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, //  tmpvar_1;.  tmp
+	0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x7a, 0x77, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, // var_1.zw = vec2(
+	0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, // 0.0, 1.0);.  tmp
+	0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, // var_1.xy = a_pos
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, // ition;.  gl_Posi
+	0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, // tion = (u_modelV
+	0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, // iewProj * tmpvar
+	0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, // _1);.  v_texcoor
+	0x64, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, // d0 = a_texcoord0
+	0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00,                                                             // ;.}...
+};
 
 
-	bgfx::ShaderHandle vs = bgfx::createShader(bgfx::makeRef((const void*) vs_code.m_data, vs_code.m_size));
-	bgfx::ShaderHandle fs = bgfx::createShader(bgfx::makeRef((const void*) fs_code.m_data, fs_code.m_size));
+static const uint8_t fsc_h[103] =
+{
+	0x46, 0x53, 0x48, 0x02, 0x8c, 0xd4, 0x10, 0xbd, 0x01, 0x00, 0x07, 0x75, 0x5f, 0x63, 0x6f, 0x6c, // FSH........u_col
+	0x6f, 0x72, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x69, 0x66, // or......J...unif
+	0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, // orm mediump vec4
+	0x20, 0x75, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, //  u_color;.void m
+	0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, // ain ().{.  gl_Fr
+	0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x75, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // agColor = u_colo
+	0x72, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00,                                                       // r;.}...
+};
 
 
-	m_program = bgfx::createProgram(vs, fs);
-	m_uniform = bgfx::createUniform("u_albedo", bgfx::UniformType::Uniform1iv);
-}
 
 
-//-----------------------------------------------------------------------------
-Material::~Material()
+namespace crown
+{
+
+void Material::create(const MaterialResource* mr)
 {
 {
+	uint32_t size = mr->dynamic_data_size();
+	uint32_t offt = mr->dynamic_data_offset();
+	char* base = (char*) mr + offt;
+
+	data = (char*) default_allocator().allocate(size);
+	memcpy(data, base, size);
+
+	bgfx::ShaderHandle vs = bgfx::createShader(bgfx::makeRef(vs_h, sizeof(vs_h)));
+	bgfx::ShaderHandle fs = bgfx::createShader(bgfx::makeRef(fs_h, sizeof(fs_h)));
+	program = bgfx::createProgram(vs, fs, true);
+
+	for (uint32_t i = 0; i < mr->num_textures(); i++)
+	{
+		TextureData* ud = mr->get_texture_data(i);
+
+		TextureHandle* th = mr->get_texture_handle(i, data);
+		th->sampler_handle = bgfx::createUniform(ud->sampler_name, bgfx::UniformType::Uniform1iv).idx;
+
+		ResourceId texid;
+		texid.type = TEXTURE_TYPE;
+		texid.name = ud->id;
+		TextureResource* tex = (TextureResource*) device()->resource_manager()->get(texid);
+
+		th->texture_handle = bgfx::createTexture(bgfx::copy(tex->data(), tex->size())).idx;
+	}
+
+	for (uint32_t i = 0; i < mr->num_uniforms(); i++)
+	{
+		UniformData* ud = mr->get_uniform_data(i);
+
+		UniformHandle* uh = mr->get_uniform_handle(i, data);
+		uh->uniform_handle = bgfx::createUniform(ud->name, bgfx::UniformType::Uniform4fv).idx;
+	}
+
+	resource = mr;
 }
 }
 
 
-//-----------------------------------------------------------------------------
-const MaterialResource* Material::resource()
+void Material::destroy() const
 {
 {
-	return m_resource;
+	bgfx::destroyProgram(program);
+
+	for (uint32_t i = 0; i < resource->num_textures(); i++)
+	{
+		TextureHandle* th = resource->get_texture_handle(i, data);
+
+		bgfx::UniformHandle sh;
+		sh.idx = th->sampler_handle;
+		bgfx::destroyUniform(sh);
+
+		bgfx::TextureHandle bgfx_th;
+		bgfx_th.idx = th->texture_handle;
+		bgfx::destroyTexture(bgfx_th);
+	}
+
+	for (uint32_t i = 0; i < resource->num_uniforms(); i++)
+	{
+		UniformHandle* uh = resource->get_uniform_handle(i, data);
+
+		bgfx::UniformHandle bgfx_uh;
+		bgfx_uh.idx = uh->uniform_handle;
+		bgfx::destroyUniform(bgfx_uh);
+	}
+
+	default_allocator().deallocate(data);
 }
 }
 
 
-//-----------------------------------------------------------------------------
-void Material::bind()
+void Material::bind() const
 {
 {
-	const void* tr = device()->resource_manager()->get("texture", "spaceship");
+	bgfx::setProgram(program);
+
+	// Set samplers
+	for (uint32_t i = 0; i < resource->num_textures(); i++)
+	{
+		TextureHandle* th = resource->get_texture_handle(i, data);
+
+		bgfx::UniformHandle sampler;
+		bgfx::TextureHandle texture;
+		sampler.idx = th->sampler_handle;
+		texture.idx = th->texture_handle;
+
+		bgfx::setTexture(i, sampler, texture);
+	}
 
 
-	bgfx::TextureHandle th;
-	th.idx = (uintptr_t) tr;
+	// Set uniforms
+	for (uint32_t i = 0; i < resource->num_uniforms(); i++)
+	{
+		UniformHandle* uh = resource->get_uniform_handle(i, data);
 
 
-	bgfx::setTexture(0, m_uniform, th);
-	bgfx::setProgram(m_program);
+		bgfx::UniformHandle buh;
+		buh.idx = uh->uniform_handle;
+		bgfx::setUniform(buh, (char*) uh + sizeof(uh->uniform_handle));
+	}
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 6 - 10
engine/renderers/material.h

@@ -35,18 +35,14 @@ struct MaterialResource;
 
 
 struct Material
 struct Material
 {
 {
-	Material(const MaterialResource* mr);
-	~Material();
+	void create(const MaterialResource* mr);
+	void destroy() const;
+	void bind() const;
 
 
-	const MaterialResource* resource();
+	const MaterialResource* resource;
+	char* data;
 
 
-	void bind();
-
-private:
-
-	const MaterialResource* m_resource;
-	bgfx::ProgramHandle m_program;
-	bgfx::UniformHandle m_uniform;
+	bgfx::ProgramHandle program;
 };
 };
 
 
 } // namespace crown
 } // namespace crown

+ 9 - 25
engine/renderers/render_world.cpp

@@ -38,6 +38,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "gui.h"
 #include "gui.h"
 #include <bgfx.h>
 #include <bgfx.h>
 
 
+#include "material_manager.h"
+
 namespace crown
 namespace crown
 {
 {
 
 
@@ -58,7 +60,6 @@ namespace graphics_system
 RenderWorld::RenderWorld()
 RenderWorld::RenderWorld()
 	: m_mesh_pool(default_allocator(), MAX_MESHES, sizeof(Mesh), CE_ALIGNOF(Mesh))
 	: m_mesh_pool(default_allocator(), MAX_MESHES, sizeof(Mesh), CE_ALIGNOF(Mesh))
 	, m_sprite_pool(default_allocator(), MAX_SPRITES, sizeof(Sprite), CE_ALIGNOF(Sprite))
 	, m_sprite_pool(default_allocator(), MAX_SPRITES, sizeof(Sprite), CE_ALIGNOF(Sprite))
-	, m_material_pool(default_allocator(), MAX_MATERIALS, sizeof(Material), CE_ALIGNOF(Material))
 	, m_gui_pool(default_allocator(), MAX_GUIS, sizeof(Gui), CE_ALIGNOF(Gui))
 	, m_gui_pool(default_allocator(), MAX_GUIS, sizeof(Gui), CE_ALIGNOF(Gui))
 {
 {
 }
 }
@@ -109,26 +110,6 @@ Sprite*	RenderWorld::get_sprite(SpriteId id)
 	return id_array::get(m_sprite, id);
 	return id_array::get(m_sprite, id);
 }
 }
 
 
-//-----------------------------------------------------------------------------
-MaterialId RenderWorld::create_material(MaterialResource* mr)
-{
-	Material* mat = CE_NEW(m_material_pool, Material)(mr);
-	return id_array::create(m_materials, mat);
-}
-
-//-----------------------------------------------------------------------------
-void RenderWorld::destroy_material(MaterialId id)
-{
-	CE_DELETE(m_material_pool, id_array::get(m_materials, id));
-	id_array::destroy(m_materials, id);
-}
-
-//-----------------------------------------------------------------------------
-Material* RenderWorld::get_material(MaterialId id)
-{
-	return id_array::get(m_materials, id);
-}
-
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 GuiId RenderWorld::create_gui(uint16_t width, uint16_t height)
 GuiId RenderWorld::create_gui(uint16_t width, uint16_t height)
 {
 {
@@ -180,14 +161,17 @@ void RenderWorld::update(const Matrix4x4& view, const Matrix4x4& projection, uin
 
 
 	// Use debug font to print information about this example.
 	// Use debug font to print information about this example.
 	bgfx::dbgTextClear();
 	bgfx::dbgTextClear();
-	bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/00-helloworld");
-	bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Initialization and debug text.");
+	bgfx::dbgTextPrintf(0, 2, 0x6f, "dt = %4.7f", dt);
 
 
-	// Draw all sprites
+	// Update all sprites
 	for (uint32_t s = 0; s < id_array::size(m_sprite); s++)
 	for (uint32_t s = 0; s < id_array::size(m_sprite); s++)
 	{
 	{
-		//r->set_program(render_world_globals::default_texture_program());
 		m_sprite[s]->update(dt);
 		m_sprite[s]->update(dt);
+	}	
+
+	// Draw all sprites
+	for (uint32_t s = 0; s < id_array::size(m_sprite); s++)
+	{
 		m_sprite[s]->render();
 		m_sprite[s]->render();
 	}
 	}
 
 

+ 1 - 11
engine/renderers/render_world.h

@@ -32,10 +32,10 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "resource.h"
 #include "resource.h"
 #include "matrix4x4.h"
 #include "matrix4x4.h"
 #include "render_world_types.h"
 #include "render_world_types.h"
+#include "material_manager.h"
 
 
 #define MAX_MESHES 100
 #define MAX_MESHES 100
 #define MAX_SPRITES 512
 #define MAX_SPRITES 512
-#define MAX_MATERIALS 512
 #define MAX_GUIS 8
 #define MAX_GUIS 8
 
 
 namespace crown
 namespace crown
@@ -94,14 +94,6 @@ public:
 	/// Creates the sprite @a id.
 	/// Creates the sprite @a id.
 	Sprite* get_sprite(SpriteId id);
 	Sprite* get_sprite(SpriteId id);
 
 
-	MaterialId create_material(MaterialResource* mr);
-
-	/// Destroys the material @a id.
-	void destroy_material(MaterialId id);
-
-	/// Returns the material @a id.
-	Material* get_material(MaterialId id);
-
 	GuiId create_gui(uint16_t width, uint16_t height);
 	GuiId create_gui(uint16_t width, uint16_t height);
 	void destroy_gui(GuiId id);
 	void destroy_gui(GuiId id);
 	Gui* get_gui(GuiId id);
 	Gui* get_gui(GuiId id);
@@ -112,12 +104,10 @@ private:
 
 
 	PoolAllocator m_mesh_pool;
 	PoolAllocator m_mesh_pool;
 	PoolAllocator m_sprite_pool;
 	PoolAllocator m_sprite_pool;
-	PoolAllocator m_material_pool;
 	PoolAllocator m_gui_pool;
 	PoolAllocator m_gui_pool;
 
 
 	IdArray<MAX_MESHES, Mesh*> m_mesh;
 	IdArray<MAX_MESHES, Mesh*> m_mesh;
 	IdArray<MAX_SPRITES, Sprite*> m_sprite;
 	IdArray<MAX_SPRITES, Sprite*> m_sprite;
-	IdArray<MAX_MATERIALS, Material*> m_materials;
 	IdArray<MAX_GUIS, Gui*> m_guis;
 	IdArray<MAX_GUIS, Gui*> m_guis;
 };
 };
 
 

+ 0 - 1
engine/renderers/render_world_types.h

@@ -33,7 +33,6 @@ namespace crown
 
 
 typedef Id MeshId;
 typedef Id MeshId;
 typedef Id SpriteId;
 typedef Id SpriteId;
-typedef Id MaterialId;
 typedef Id GuiId;
 typedef Id GuiId;
 
 
 } // namespace crown
 } // namespace crown

+ 8 - 28
engine/renderers/sprite.cpp

@@ -33,6 +33,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "unit.h"
 #include "unit.h"
 #include "material.h"
 #include "material.h"
 #include "render_world.h"
 #include "render_world.h"
+#include "device.h"
+#include "material_manager.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -43,6 +45,7 @@ Sprite::Sprite(RenderWorld& render_world, SceneGraph& sg, int32_t node, const Sp
 	, m_scene_graph(sg)
 	, m_scene_graph(sg)
 	, m_node(node)
 	, m_node(node)
 	, m_resource(sr)
 	, m_resource(sr)
+	, m_material(0)
 	, m_frame(0)
 	, m_frame(0)
 	, m_animation(NULL)
 	, m_animation(NULL)
 	, m_time(0)
 	, m_time(0)
@@ -120,10 +123,9 @@ void Sprite::set_local_pose(Unit* unit, const Matrix4x4& pose)
 	unit->set_local_pose(m_node, pose);
 	unit->set_local_pose(m_node, pose);
 }
 }
 
 
-//-----------------------------------------------------------------------------
-void Sprite::set_material(MaterialId mat)
+void Sprite::set_material(StringId64 id)
 {
 {
-	m_material = mat;
+	m_material = id;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -180,32 +182,10 @@ void Sprite::update(float dt)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void Sprite::render()
 void Sprite::render()
 {
 {
-	///
-	/// @param _state State flags. Default state for primitive type is
-	///   triangles. See: BGFX_STATE_DEFAULT.
-	///
-	///   BGFX_STATE_ALPHA_WRITE - Enable alpha write.
-	///   BGFX_STATE_DEPTH_WRITE - Enable depth write.
-	///   BGFX_STATE_DEPTH_TEST_* - Depth test function.
-	///   BGFX_STATE_BLEND_* - See NOTE 1: BGFX_STATE_BLEND_FUNC.
-	///   BGFX_STATE_BLEND_EQUATION_* - See NOTE 2.
-	///   BGFX_STATE_CULL_* - Backface culling mode.
-	///   BGFX_STATE_RGB_WRITE - Enable RGB write.
-	///   BGFX_STATE_MSAA - Enable MSAA.
-	///   BGFX_STATE_PT_[LINES/POINTS] - Primitive type.
-	///
-	/// @param _rgba Sets blend factor used by BGFX_STATE_BLEND_FACTOR and
-	///   BGFX_STATE_BLEND_INV_FACTOR blend modes.
-	///
-	/// NOTE:
-	///   1. Use BGFX_STATE_ALPHA_REF, BGFX_STATE_POINT_SIZE and
-	///      BGFX_STATE_BLEND_FUNC macros to setup more complex states.
-	///   2. BGFX_STATE_BLEND_EQUATION_ADD is set when no other blend
-	///      equation is specified.
-	///
-	bgfx::setState(BGFX_STATE_DEFAULT
-		| BGFX_STATE_BLEND_ALPHA);
+	if (m_material)
+		material_manager::get()->get(m_material).bind();
 
 
+	bgfx::setState(BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA);
 	bgfx::setVertexBuffer(m_vb);
 	bgfx::setVertexBuffer(m_vb);
 	bgfx::setIndexBuffer(m_ib, m_frame * 6, 6);
 	bgfx::setIndexBuffer(m_ib, m_frame * 6, 6);
 	bgfx::setTransform(matrix4x4::to_float_ptr(world_pose()));
 	bgfx::setTransform(matrix4x4::to_float_ptr(world_pose()));

+ 7 - 6
engine/renderers/sprite.h

@@ -59,7 +59,8 @@ struct Sprite
 	void set_local_rotation(Unit* unit, const Quaternion& rot);
 	void set_local_rotation(Unit* unit, const Quaternion& rot);
 	void set_local_pose(Unit* unit, const Matrix4x4& pose);
 	void set_local_pose(Unit* unit, const Matrix4x4& pose);
 
 
-	void set_material(MaterialId mat);
+	void set_material(StringId64 id);
+
 	void render();
 	void render();
 	void set_frame(uint32_t i);
 	void set_frame(uint32_t i);
 
 
@@ -70,12 +71,12 @@ struct Sprite
 
 
 public:
 public:
 
 
-	RenderWorld&			m_render_world;
-	SceneGraph&				m_scene_graph;
-	int32_t					m_node;
-	const SpriteResource*	m_resource;
+	RenderWorld& m_render_world;
+	SceneGraph& m_scene_graph;
+	int32_t m_node;
+	const SpriteResource* m_resource;
+	StringId64 m_material;
 
 
-	MaterialId m_material;
 	bgfx::VertexBufferHandle m_vb;
 	bgfx::VertexBufferHandle m_vb;
 	bgfx::IndexBufferHandle m_ib;
 	bgfx::IndexBufferHandle m_ib;
 
 

+ 4 - 8
engine/resource/font_resource.h

@@ -109,23 +109,19 @@ public:
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* resource)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		(void)resource;
-		// TODO
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
-		// TODO
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------

+ 4 - 6
engine/resource/level_resource.h

@@ -79,20 +79,18 @@ struct LevelResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------

+ 4 - 6
engine/resource/lua_resource.h

@@ -61,20 +61,18 @@ struct LuaResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	/// Returns the size in bytes of the lua program.
 	/// Returns the size in bytes of the lua program.

+ 146 - 68
engine/resource/material_resource.cpp

@@ -38,90 +38,168 @@ namespace crown
 namespace material_resource
 namespace material_resource
 {
 {
 
 
-//-----------------------------------------------------------------------------
-void compile(Filesystem& fs, const char* resource_path, File* out_file)
+struct Data
 {
 {
-	File* file = fs.open(resource_path, FOM_READ);
-	JSONParser json(*file);
-	fs.close(file);
-
-	JSONElement root = json.root();
+	Array<TextureData> textures;
+	Array<UniformData> uniforms;
+	Array<char> dynamic;
+
+	Data()
+		: textures(default_allocator())
+		, uniforms(default_allocator())
+		, dynamic(default_allocator())
+	{}
+};
+
+// Returns offset to start of data
+template <typename T>
+static uint32_t reserve_dynamic_data(T data, Array<char>& dynamic)
+{
+	uint32_t offt = array::size(dynamic);
+	array::push(dynamic, (char*) &data, sizeof(data));
+	return offt;
+}
 
 
-	DynamicString vs_src;
-	DynamicString fs_src;
-	DynamicString varying_src;
+static void parse_textures(JSONElement root, Array<TextureData>& textures, Array<char>& dynamic)
+{
+	using namespace vector;
 
 
-	root.key("vs_source").to_string(vs_src);
-	root.key("fs_source").to_string(fs_src);
-	root.key("varying_source").to_string(varying_src);
+	Vector<DynamicString> keys(default_allocator());
+	root.key("textures").to_keys(keys);
 
 
-	vs_src += ".sc";
-	fs_src += ".sc";
-	varying_src += ".def.sc";
+	for (uint32_t i = 0; i < size(keys); i++)
+	{
+		TextureHandle th;
+		th.sampler_handle = 0;
+		th.texture_handle = 0;
 
 
-	DynamicString vs_src_abs;
-	DynamicString fs_src_abs;
-	DynamicString varying_src_abs;
-	DynamicString vs_bin_abs;
-	DynamicString fs_bin_abs;
+		ResourceId texid = root.key("textures").key(keys[i].c_str()).to_resource_id("texture");
 
 
-	fs.get_absolute_path(vs_src.c_str(), vs_src_abs);
-	fs.get_absolute_path(fs_src.c_str(), fs_src_abs);
-	fs.get_absolute_path(varying_src.c_str(), varying_src_abs);
-	fs.get_absolute_path("vs_bin.tmp", vs_bin_abs);
-	fs.get_absolute_path("fs_bin.tmp", fs_bin_abs);
+		TextureData td;
+		td.id = texid.name;
+		td.data_offset = reserve_dynamic_data(th, dynamic);
+		strncpy(td.sampler_name, keys[i].c_str(), 256);
 
 
-	const char* shaderc_vs[] =
-	{
-		"./shaderc",
-		"-f", vs_src_abs.c_str(),
-		"-o", vs_bin_abs.c_str(),
-		"--platform", "linux",
-		"--varyingdef", varying_src_abs.c_str(),
-		"--type", "vertex",
-		NULL
-	};
-
-	const char* shaderc_fs[] =
-	{
-		"shaderc",
-		"-f", fs_src_abs.c_str(),
-		"-o", fs_bin_abs.c_str(),
-		"--platform", "linux",
-		"--varyingdef", varying_src_abs.c_str(),
-		"--type", "fragment",
-		NULL
-	};
+		array::push_back(textures, td);
+	}
+}
 
 
-	os::execute_process(shaderc_vs);
-	os::execute_process(shaderc_fs);
+struct UniformTypeInfo
+{
+	const char* name;
+	UniformType::Enum type;
+	uint8_t size;
+};
 
 
-	File* vs_code = fs.open(vs_bin_abs.c_str(), FOM_READ);
-	File* fs_code = fs.open(fs_bin_abs.c_str(), FOM_READ);
+static const UniformTypeInfo s_uniform_type_info[UniformType::COUNT] =
+{
+	{ "integer", UniformType::INTEGER,  4 },
+	{ "float",   UniformType::FLOAT,    4 },
+	{ "vector2", UniformType::VECTOR3,  8 },
+	{ "vector3", UniformType::VECTOR3, 12 },
+	{ "vector4", UniformType::VECTOR4, 16 }
+};
+
+static UniformType::Enum string_to_uniform_type(const char* str)
+{
+	for (uint32_t i = 0; i < UniformType::COUNT; i++)
+	{
+		if (string::strcmp(str, s_uniform_type_info[i].name) == 0)
+			return s_uniform_type_info[i].type;
+	}
 
 
-	const uint32_t vs_code_size = vs_code->size();
-	const uint32_t fs_code_size = fs_code->size();
+	CE_FATAL("Unknown uniform type");
+}
 
 
-	// Write material
-	BinaryWriter bw(*out_file);
+static void parse_uniforms(JSONElement root, Array<UniformData>& uniforms, Array<char>& dynamic)
+{
+	using namespace vector;
 
 
-	bw.write(vs_code_size);
-	bw.write(uint32_t(16 + 0));
-	bw.write(fs_code_size);
-	bw.write(uint32_t(16 + vs_code_size));
+	Vector<DynamicString> keys(default_allocator());
+	root.key("uniforms").to_keys(keys);
 
 
-	char* shaders = (char*) default_allocator().allocate(vs_code_size + fs_code_size);
-	vs_code->read(shaders + 0, vs_code_size);
-	fs_code->read(shaders + vs_code_size, fs_code_size);
+	for (uint32_t i = 0; i < size(keys); i++)
+	{
+		UniformHandle uh;
+		uh.uniform_handle = 0;
+
+		DynamicString type;
+		root.key("uniforms").key(keys[i].c_str()).key("type").to_string(type);
+
+		UniformData ud;
+		ud.type = string_to_uniform_type(type.c_str());
+		ud.data_offset = reserve_dynamic_data(uh, dynamic);
+
+		strncpy(ud.name, keys[i].c_str(), 256);
+
+		switch (ud.type)
+		{
+			case UniformType::INTEGER:
+			{
+				int32_t data = root.key("uniforms").key(keys[i].c_str()).key("value").to_int();
+				reserve_dynamic_data(data, dynamic);
+				break;
+			}
+			case UniformType::FLOAT:
+			{
+				float data = root.key("uniforms").key(keys[i].c_str()).key("value").to_int();
+				reserve_dynamic_data(data, dynamic);
+				break;
+			}
+			case UniformType::VECTOR2:
+			{
+				Vector2 data = root.key("uniforms").key(keys[i].c_str()).key("value").to_vector2();
+				reserve_dynamic_data(data, dynamic);
+				break;
+			}
+			case UniformType::VECTOR3:
+			{
+				Vector3 data = root.key("uniforms").key(keys[i].c_str()).key("value").to_vector3();
+				reserve_dynamic_data(data, dynamic);
+				break;
+			}
+			case UniformType::VECTOR4:
+			{
+				Vector4 data = root.key("uniforms").key(keys[i].c_str()).key("value").to_vector4();
+				reserve_dynamic_data(data, dynamic);
+				break;
+			}
+			default: CE_FATAL("Oops"); break;
+		}
+
+		array::push_back(uniforms, ud);
+	}
+}
 
 
-	bw.write(shaders, vs_code_size + fs_code_size);
+//-----------------------------------------------------------------------------
+void compile(Filesystem& fs, const char* resource_path, File* out_file)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+	JSONParser json(*file);
+	fs.close(file);
 
 
-	default_allocator().deallocate(shaders);
+	JSONElement root = json.root();
 
 
-	fs.close(vs_code);
-	fs.close(fs_code);
-	fs.delete_file(vs_bin_abs.c_str());
-	fs.delete_file(fs_bin_abs.c_str());
+	Array<TextureData> texdata(default_allocator());
+	Array<UniformData> unidata(default_allocator());
+	Array<char> dynblob(default_allocator());
+
+	parse_textures(root, texdata, dynblob);
+	parse_uniforms(root, unidata, dynblob);
+
+	MaterialHeader mh;
+	mh.version = MATERIAL_VERSION;
+	mh.num_textures = array::size(texdata);
+	mh.texture_data_offset = sizeof(mh);
+	mh.num_uniforms = array::size(unidata);
+	mh.uniform_data_offset = sizeof(mh) + sizeof(TextureData) * array::size(texdata);
+	mh.dynamic_data_size = array::size(dynblob);
+	mh.dynamic_data_offset = sizeof(mh) + sizeof(TextureData) * array::size(texdata) + sizeof(UniformData) * array::size(unidata);
+
+	out_file->write((char*) &mh, sizeof(mh));
+	out_file->write((char*) array::begin(texdata), sizeof(TextureData) * array::size(texdata));
+	out_file->write((char*) array::begin(unidata), sizeof(UniformData) * array::size(unidata));
+	out_file->write((char*) array::begin(dynblob), sizeof(char) * array::size(dynblob));
 }
 }
 
 
 } // namespace material_resource
 } // namespace material_resource

+ 87 - 39
engine/resource/material_resource.h

@@ -27,57 +27,73 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include "types.h"
 #include "types.h"
-#include "texture_resource.h"
 #include "resource.h"
 #include "resource.h"
 #include "vector3.h"
 #include "vector3.h"
 #include "color4.h"
 #include "color4.h"
 #include "bundle.h"
 #include "bundle.h"
 #include "allocator.h"
 #include "allocator.h"
 #include "blob.h"
 #include "blob.h"
+#include "device.h"
+#include "file.h"
+#include "resource_manager.h"
+#include "material_manager.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
+const uint32_t MATERIAL_VERSION = 1;
+
+
 struct MaterialHeader
 struct MaterialHeader
 {
 {
-	uint32_t vs_size;
-	uint32_t vs_offset;
-	uint32_t fs_size;
-	uint32_t fs_offset;
+	uint32_t version;
+	uint32_t num_textures;
+	uint32_t texture_data_offset;
+	uint32_t num_uniforms;
+	uint32_t uniform_data_offset;
+	uint32_t dynamic_data_size;
+	uint32_t dynamic_data_offset;
 };
 };
 
 
-struct SamplerArray
+struct TextureData
 {
 {
-	uint32_t num;
+	char sampler_name[256];	// Sampler uniform name
+	StringId64 id;			// Resource name
+	uint32_t data_offset;	// Offset into dynamic blob
 };
 };
 
 
-struct Sampler
+struct TextureHandle
 {
 {
-	char name[32];
-	ResourceId texture;
+	uint32_t sampler_handle;
+	uint32_t texture_handle;
 };
 };
 
 
-struct UniformArray
+struct UniformType
 {
 {
-	uint32_t num;
+	enum Enum
+	{
+		INTEGER,
+		FLOAT,
+		VECTOR2,
+		VECTOR3,
+		VECTOR4,
+		COUNT
+	};
 };
 };
 
 
-union UniformValue
+struct UniformData
 {
 {
-	float float_value;
-	//Vector3 vector3_value;
+	char name[256];			// Uniform name
+	uint32_t type;			// UniformType::Enum
+	uint32_t data_offset;	// Offset into dynamic blob
 };
 };
 
 
-struct Uniform
+struct UniformHandle
 {
 {
-	char name[32];
-	uint32_t type;
-	UniformValue value;
+	uint32_t uniform_handle;
+	// data
 };
 };
 
 
-/// A material describes the visual properties of a surface.
-/// It is primarly intended for rendering purposes but can
-/// also be used to drive other types of systems such as sounds or physics.
 struct MaterialResource
 struct MaterialResource
 {
 {
 public:
 public:
@@ -97,38 +113,71 @@ public:
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 id, ResourceManager& rm)
+	{
+		material_manager::get()->load(id, rm);
+	}
+
+	//-----------------------------------------------------------------------------
+	static void offline(StringId64 id, ResourceManager& rm)
 	{
 	{
+		material_manager::get()->unload(id, rm);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	static void unload(Allocator& a, void* res)
 	static void unload(Allocator& a, void* res)
 	{
 	{
-		CE_ASSERT_NOT_NULL(res);
 		a.deallocate(res);
 		a.deallocate(res);
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	uint32_t dynamic_data_size() const
+	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		return mh->dynamic_data_size;		
+	}
+
+	uint32_t dynamic_data_offset() const
+	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		return mh->dynamic_data_offset;
+	}
+
+	uint32_t num_textures() const
+	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		return mh->num_textures;
+	}
+
+	uint32_t num_uniforms() const
+	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		return mh->num_uniforms;		
+	}
+
+	UniformData* get_uniform_data(uint32_t i) const
+	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		UniformData* base = (UniformData*) ((char*) mh + mh->uniform_data_offset);
+		return &base[i];
+	}
+
+	TextureData* get_texture_data(uint32_t i) const
 	{
 	{
+		MaterialHeader* mh = (MaterialHeader*) this;
+		TextureData* base = (TextureData*) ((char*) mh + mh->texture_data_offset);
+		return &base[i];
 	}
 	}
 
 
-	Blob get_vertex_shader() const
+	UniformHandle* get_uniform_handle(uint32_t i, char* dynamic) const
 	{
 	{
-		MaterialHeader* h = (MaterialHeader*) this;
-		Blob b;
-		b.m_size = h->vs_size;
-		b.m_data = (uintptr_t) h->vs_offset + (uintptr_t) this;
-		return b;
+		UniformData* ud = get_uniform_data(i);
+		return (UniformHandle*) (dynamic + ud->data_offset);
 	}
 	}
 
 
-	Blob get_fragment_shader() const
+	TextureHandle* get_texture_handle(uint32_t i, char* dynamic) const
 	{
 	{
-		MaterialHeader* h = (MaterialHeader*) this;
-		Blob b;
-		b.m_size = h->fs_size;
-		b.m_data = (uintptr_t) h->fs_offset + (uintptr_t) this;
-		return b;
+		TextureData* td = get_texture_data(i);
+		return (TextureHandle*) (dynamic + td->data_offset);
 	}
 	}
 
 
 private:
 private:
@@ -138,4 +187,3 @@ private:
 };
 };
 
 
 } // namespace crown
 } // namespace crown
-

+ 4 - 15
engine/resource/mesh_resource.h

@@ -86,13 +86,12 @@ public:
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* resource)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		MeshResource* m = (MeshResource*) resource;
-		MeshHeader* h = (MeshHeader*) m;
+	}
 
 
-		// h->vbuffer = device()->renderer()->create_vertex_buffer(m->num_vertices() * Vertex::bytes_per_vertex(m->vertex_format()), m->vertices(), m->vertex_format());
-		// h->ibuffer = device()->renderer()->create_index_buffer(m->num_indices() * sizeof(uint16_t), m->indices());
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
+	{
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
@@ -102,16 +101,6 @@ public:
 		a.deallocate(res);
 		a.deallocate(res);
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void offline(void* resource)
-	{
-		MeshResource* m = (MeshResource*) resource;
-		MeshHeader* h = (MeshHeader*) m;
-
-		// device()->renderer()->destroy_index_buffer(h->ibuffer);
-		// device()->renderer()->destroy_vertex_buffer(h->vbuffer);
-	}
-
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	uint32_t num_vertices() const
 	uint32_t num_vertices() const
 	{
 	{

+ 4 - 6
engine/resource/package_resource.h

@@ -79,20 +79,18 @@ struct PackageResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------

+ 8 - 12
engine/resource/physics_resource.h

@@ -170,20 +170,18 @@ struct PhysicsResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
@@ -335,20 +333,18 @@ struct PhysicsConfigResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------

+ 5 - 2
engine/resource/resource.h

@@ -47,6 +47,7 @@ namespace crown
 #define SPRITE_EXTENSION			"sprite"
 #define SPRITE_EXTENSION			"sprite"
 #define TEXTURE_EXTENSION			"texture"
 #define TEXTURE_EXTENSION			"texture"
 #define UNIT_EXTENSION				"unit"
 #define UNIT_EXTENSION				"unit"
+#define SHADER_EXTENSION			"shader"
 
 
 #define CONFIG_TYPE					uint64_t(0x82645835e6b73232)
 #define CONFIG_TYPE					uint64_t(0x82645835e6b73232)
 #define FONT_TYPE					uint64_t(0x9efe0a916aae7880)
 #define FONT_TYPE					uint64_t(0x9efe0a916aae7880)
@@ -61,6 +62,7 @@ namespace crown
 #define SPRITE_TYPE					uint64_t(0x8d5871f9ebdb651c)
 #define SPRITE_TYPE					uint64_t(0x8d5871f9ebdb651c)
 #define TEXTURE_TYPE				uint64_t(0xcd4238c6a0c69e32)
 #define TEXTURE_TYPE				uint64_t(0xcd4238c6a0c69e32)
 #define UNIT_TYPE					uint64_t(0xe0a48d0be9a7453f)
 #define UNIT_TYPE					uint64_t(0xe0a48d0be9a7453f)
+#define SHADER_TYPE					uint64_t(0xcce8d5b5f5ae333f)
 
 
 struct ResourceId
 struct ResourceId
 {
 {
@@ -75,11 +77,12 @@ struct ResourceId
 
 
 class Allocator;
 class Allocator;
 class Bundle;
 class Bundle;
+class ResourceManager;
 
 
 typedef void*	(*ResourceLoadCallback)(Allocator& a, Bundle& b, ResourceId id);
 typedef void*	(*ResourceLoadCallback)(Allocator& a, Bundle& b, ResourceId id);
+typedef void	(*ResourceOnlineCallback)(StringId64 id, ResourceManager& rm);
+typedef void	(*ResourceOfflineCallback)(StringId64 id, ResourceManager& rm);
 typedef void	(*ResourceUnloadCallback)(Allocator& a, void* resource);
 typedef void	(*ResourceUnloadCallback)(Allocator& a, void* resource);
-typedef void	(*ResourceOnlineCallback)(void* resource);
-typedef void	(*ResourceOfflineCallback)(void* resource);
 
 
 struct ResourceCallback
 struct ResourceCallback
 {
 {

+ 3 - 2
engine/resource/resource_manager.cpp

@@ -81,7 +81,7 @@ void ResourceManager::unload(ResourceId id, bool force)
 
 
 	if (entry->references == 0 || force)
 	if (entry->references == 0 || force)
 	{
 	{
-		resource_on_offline(id.type, entry->resource);
+		resource_on_offline(id.type, id.name, *this);
 		resource_on_unload(id.type, m_resource_heap, entry->resource);
 		resource_on_unload(id.type, m_resource_heap, entry->resource);
 
 
 		// Swap with last
 		// Swap with last
@@ -147,12 +147,13 @@ void ResourceManager::complete_requests()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void ResourceManager::complete_request(ResourceId id, void* data)
 void ResourceManager::complete_request(ResourceId id, void* data)
 {
 {
-	resource_on_online(id.type, data);
 	ResourceEntry entry;
 	ResourceEntry entry;
 	entry.id = id;
 	entry.id = id;
 	entry.references = 1;
 	entry.references = 1;
 	entry.resource = data;
 	entry.resource = data;
 	array::push_back(m_resources, entry);
 	array::push_back(m_resources, entry);
+
+	resource_on_online(id.type, id.name, *this);
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 4 - 4
engine/resource/resource_registry.cpp

@@ -96,23 +96,23 @@ void resource_on_unload(uint64_t type, Allocator& allocator, void* resource)
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void resource_on_online(uint64_t type, void* resource)
+void resource_on_online(uint64_t type, StringId64 id, ResourceManager& rm)
 {
 {
 	const ResourceCallback* c = find_callback(type);
 	const ResourceCallback* c = find_callback(type);
 
 
 	CE_ASSERT_NOT_NULL(c);
 	CE_ASSERT_NOT_NULL(c);
 
 
-	return c->on_online(resource);
+	return c->on_online(id, rm);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void resource_on_offline(uint64_t type, void* resource)
+void resource_on_offline(uint64_t type, StringId64 id, ResourceManager& rm)
 {
 {
 	const ResourceCallback* c = find_callback(type);
 	const ResourceCallback* c = find_callback(type);
 
 
 	CE_ASSERT_NOT_NULL(c);
 	CE_ASSERT_NOT_NULL(c);
 
 
-	return c->on_offline(resource);
+	return c->on_offline(id, rm);
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 2 - 2
engine/resource/resource_registry.h

@@ -32,8 +32,8 @@ namespace crown
 {
 {
 
 
 void* resource_on_load(uint64_t type, Allocator& allocator, Bundle& bundle, ResourceId id);
 void* resource_on_load(uint64_t type, Allocator& allocator, Bundle& bundle, ResourceId id);
-void resource_on_online(uint64_t type, void* resource);
-void resource_on_offline(uint64_t type, void* resource);
+void resource_on_online(uint64_t type, StringId64 id, ResourceManager& rm);
+void resource_on_offline(uint64_t type, StringId64 id, ResourceManager& rm);
 void resource_on_unload(uint64_t type, Allocator& allocator, void* resource);
 void resource_on_unload(uint64_t type, Allocator& allocator, void* resource);
 
 
 } // namespace crown
 } // namespace crown

+ 4 - 6
engine/resource/sound_resource.h

@@ -80,20 +80,18 @@ public:
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 public:
 public:

+ 4 - 6
engine/resource/sprite_resource.h

@@ -83,20 +83,18 @@ struct SpriteResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------

+ 2 - 0
engine/resource/texture_resource.cpp

@@ -540,6 +540,8 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 
 	BinaryWriter bw(*out_file);
 	BinaryWriter bw(*out_file);
 	// Write DDS
 	// Write DDS
+	bw.write(uint32_t(1)); // Version
+	bw.write(uint32_t(0)); // Size
 	write_dds(bw, image);
 	write_dds(bw, image);
 
 
 	default_allocator().deallocate(image.data);
 	default_allocator().deallocate(image.data);

+ 17 - 24
engine/resource/texture_resource.h

@@ -124,7 +124,8 @@ struct DdsHeader
 
 
 struct TextureHeader
 struct TextureHeader
 {
 {
-	uint32_t id;
+	uint32_t version;
+	uint32_t size;
 };
 };
 
 
 #define DDS_HEADER_OFFSET	uint32_t(sizeof(TextureHeader))
 #define DDS_HEADER_OFFSET	uint32_t(sizeof(TextureHeader))
@@ -143,34 +144,26 @@ struct TextureResource
 
 
 		bundle.close(file);
 		bundle.close(file);
 
 
-		bgfx::TextureHandle tex = bgfx::createTexture(bgfx::copy(res, file_size));
+		// HACK HACK HACK
+		TextureHeader* th = (TextureHeader*) res;
+		th->size = file_size;
 
 
-		return (void*) (uintptr_t) tex.idx;
+		return res;
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* resource)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		// TextureResource* t = (TextureResource*) resource;
-		// TextureHeader* h = (TextureHeader*) t;
-
-		// h->id = device()->renderer()->create_texture(t->width(), t->height(), t->num_mipmaps(), t->format(), t->data());
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT(resource != NULL, "Resource not loaded");
-
-		allocator.deallocate(resource);
 	}
 	}
-
+	
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* resource)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
-		// TextureResource* t = (TextureResource*) resource;
-
-		// device()->renderer()->destroy_texture(t->texture());
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	uint32_t width() const
 	uint32_t width() const
@@ -188,15 +181,15 @@ struct TextureResource
 		return (uint8_t) ((DdsHeader*) (((char*) this) + DDS_HEADER_OFFSET))->num_mips;
 		return (uint8_t) ((DdsHeader*) (((char*) this) + DDS_HEADER_OFFSET))->num_mips;
 	}
 	}
 
 
-	const char* data() const
+	uint32_t size() const
 	{
 	{
-		return (char*) this + DDS_DATA_OFFSET;
+		return ((TextureHeader*) this)->size;
 	}
 	}
 
 
-	// TextureId texture() const
-	// {
-	// 	return ((TextureHeader*) this)->id;
-	// }
+	const char* data() const
+	{
+		return (char*) this + DDS_HEADER_OFFSET;
+	}
 
 
 private:
 private:
 
 

+ 19 - 15
engine/resource/unit_resource.cpp

@@ -305,6 +305,17 @@ void parse_keys(JSONElement e, Array<Key>& generic_keys, Array<char>& values)
 	}
 	}
 }
 }
 
 
+void parse_materials(JSONElement e, Array<UnitMaterial>& materials)
+{
+	for (uint32_t i = 0; i < e.size(); i++)
+	{
+		ResourceId mat_id = e[i].to_resource_id("material");
+		UnitMaterial um;
+		um.id = mat_id.name;
+		array::push_back(materials, um);
+	}
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void compile(Filesystem& fs, const char* resource_path, File* out_file)
 void compile(Filesystem& fs, const char* resource_path, File* out_file)
 {
 {
@@ -315,13 +326,13 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	JSONElement root = json.root();
 	JSONElement root = json.root();
 
 
 	ResourceId				m_physics_resource;
 	ResourceId				m_physics_resource;
-	ResourceId				m_material_resource;
 	Array<GraphNode>		m_nodes(default_allocator());
 	Array<GraphNode>		m_nodes(default_allocator());
 	Array<GraphNodeDepth>	m_node_depths(default_allocator());
 	Array<GraphNodeDepth>	m_node_depths(default_allocator());
 	Array<UnitCamera>		m_cameras(default_allocator());
 	Array<UnitCamera>		m_cameras(default_allocator());
 	Array<UnitRenderable>	m_renderables(default_allocator());
 	Array<UnitRenderable>	m_renderables(default_allocator());
 	Array<Key>				m_keys(default_allocator());
 	Array<Key>				m_keys(default_allocator());
 	Array<char>				m_values(default_allocator());
 	Array<char>				m_values(default_allocator());
+	Array<UnitMaterial>		m_materials(default_allocator());
 
 
 	// Check for nodes
 	// Check for nodes
 	if (root.has_key("nodes")) parse_nodes(root.key("nodes"), m_nodes, m_node_depths);
 	if (root.has_key("nodes")) parse_nodes(root.key("nodes"), m_nodes, m_node_depths);
@@ -336,6 +347,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	if (root.has_key("renderables")) parse_renderables(root.key("renderables"), m_renderables, m_node_depths);
 	if (root.has_key("renderables")) parse_renderables(root.key("renderables"), m_renderables, m_node_depths);
 	if (root.has_key("cameras")) parse_cameras(root.key("cameras"), m_cameras, m_node_depths);
 	if (root.has_key("cameras")) parse_cameras(root.key("cameras"), m_cameras, m_node_depths);
 	if (root.has_key("keys")) parse_keys(root.key("keys"), m_keys, m_values);
 	if (root.has_key("keys")) parse_keys(root.key("keys"), m_keys, m_values);
+	if (root.has_key("materials")) parse_materials(root.key("materials"), m_materials);
 
 
 	// Check if the unit has a .physics resource
 	// Check if the unit has a .physics resource
 	DynamicString unit_name(resource_path);
 	DynamicString unit_name(resource_path);
@@ -351,23 +363,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		m_physics_resource = ResourceId();
 		m_physics_resource = ResourceId();
 	}
 	}
 
 
-	// Check if the unit has a .material resource
-	DynamicString material_name = unit_name;
-	material_name += ".material";
-	if (fs.exists(material_name.c_str()))
-	{
-		m_material_resource = ResourceId("material", unit_name.c_str());
-	}
-	else
-	{
-		m_material_resource = ResourceId();
-	}
-
-
 	UnitHeader h;
 	UnitHeader h;
 	h.physics_resource = m_physics_resource;
 	h.physics_resource = m_physics_resource;
-	h.material_resource = m_material_resource;
 	h.num_renderables = array::size(m_renderables);
 	h.num_renderables = array::size(m_renderables);
+	h.num_materials = array::size(m_materials);
 	h.num_cameras = array::size(m_cameras);
 	h.num_cameras = array::size(m_cameras);
 	h.num_scene_graph_nodes = array::size(m_nodes);
 	h.num_scene_graph_nodes = array::size(m_nodes);
 	h.num_keys = array::size(m_keys);
 	h.num_keys = array::size(m_keys);
@@ -375,6 +374,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 
 	uint32_t offt = sizeof(UnitHeader);
 	uint32_t offt = sizeof(UnitHeader);
 	h.renderables_offset         = offt; offt += sizeof(UnitRenderable) * h.num_renderables;
 	h.renderables_offset         = offt; offt += sizeof(UnitRenderable) * h.num_renderables;
+	h.materials_offset           = offt; offt += sizeof(UnitMaterial) * h.num_materials;
 	h.cameras_offset             = offt; offt += sizeof(UnitCamera) * h.num_cameras;
 	h.cameras_offset             = offt; offt += sizeof(UnitCamera) * h.num_cameras;
 	h.scene_graph_nodes_offset   = offt; offt += sizeof(UnitNode) * h.num_scene_graph_nodes;
 	h.scene_graph_nodes_offset   = offt; offt += sizeof(UnitNode) * h.num_scene_graph_nodes;
 	h.keys_offset                = offt; offt += sizeof(Key) * h.num_keys;
 	h.keys_offset                = offt; offt += sizeof(Key) * h.num_keys;
@@ -387,6 +387,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	if (array::size(m_renderables))
 	if (array::size(m_renderables))
 		out_file->write((char*) array::begin(m_renderables), sizeof(UnitRenderable) * h.num_renderables);
 		out_file->write((char*) array::begin(m_renderables), sizeof(UnitRenderable) * h.num_renderables);
 
 
+	// Write materials
+	if (array::size(m_materials))
+		out_file->write((char*) array::begin(m_materials), sizeof(UnitMaterial) * h.num_materials);
+
 	// Write cameras
 	// Write cameras
 	if (array::size(m_cameras))
 	if (array::size(m_cameras))
 		out_file->write((char*) array::begin(m_cameras), sizeof(UnitCamera) * h.num_cameras);
 		out_file->write((char*) array::begin(m_cameras), sizeof(UnitCamera) * h.num_cameras);

+ 27 - 13
engine/resource/unit_resource.h

@@ -42,9 +42,10 @@ namespace crown
 struct UnitHeader
 struct UnitHeader
 {
 {
 	ResourceId physics_resource;
 	ResourceId physics_resource;
-	ResourceId material_resource;
 	uint32_t num_renderables;
 	uint32_t num_renderables;
 	uint32_t renderables_offset;
 	uint32_t renderables_offset;
+	uint32_t num_materials;
+	uint32_t materials_offset;
 	uint32_t num_cameras;
 	uint32_t num_cameras;
 	uint32_t cameras_offset;
 	uint32_t cameras_offset;
 	uint32_t num_scene_graph_nodes;
 	uint32_t num_scene_graph_nodes;
@@ -64,6 +65,11 @@ struct UnitRenderable
 	bool visible;
 	bool visible;
 };
 };
 
 
+struct UnitMaterial
+{
+	StringId64 id;
+};
+
 struct UnitCamera
 struct UnitCamera
 {
 {
 	uint32_t name;
 	uint32_t name;
@@ -117,20 +123,18 @@ struct UnitResource
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void online(void* /*resource*/)
+	static void online(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	static void unload(Allocator& allocator, void* resource)
+	static void offline(StringId64 /*id*/, ResourceManager& /*rm*/)
 	{
 	{
-		CE_ASSERT_NOT_NULL(resource);
-		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	static void offline(void* /*resource*/)
+	static void unload(Allocator& allocator, void* resource)
 	{
 	{
+		allocator.deallocate(resource);
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
@@ -139,12 +143,6 @@ struct UnitResource
 		return ((UnitHeader*) this)->physics_resource;
 		return ((UnitHeader*) this)->physics_resource;
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	ResourceId material_resource() const
-	{
-		return ((UnitHeader*) this)->material_resource;
-	}
-
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	uint32_t num_renderables() const
 	uint32_t num_renderables() const
 	{
 	{
@@ -161,6 +159,22 @@ struct UnitResource
 		return begin[i];
 		return begin[i];
 	}
 	}
 
 
+	//-----------------------------------------------------------------------------
+	uint32_t num_materials() const
+	{
+		return ((UnitHeader*) this)->num_materials;
+	}
+
+	//-----------------------------------------------------------------------------
+	UnitMaterial get_material(uint32_t i) const
+	{
+		CE_ASSERT(i < num_materials(), "Index out of bounds");
+
+		UnitHeader* h = (UnitHeader*) this;
+		UnitMaterial* begin = (UnitMaterial*) (((char*) this) + h->materials_offset);
+		return begin[i];
+	}	
+
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	uint32_t num_cameras() const
 	uint32_t num_cameras() const
 	{
 	{

+ 8 - 29
engine/world/unit.cpp

@@ -51,7 +51,6 @@ Unit::Unit(World& w, UnitId unit_id, const ResourceId id, const UnitResource* ur
 	, m_num_meshes(0)
 	, m_num_meshes(0)
 	, m_num_sprites(0)
 	, m_num_sprites(0)
 	, m_num_actors(0)
 	, m_num_actors(0)
-	, m_num_materials(0)
 	, m_values(NULL)
 	, m_values(NULL)
 {
 {
 	m_controller.component.id = INVALID_ID;
 	m_controller.component.id = INVALID_ID;
@@ -139,13 +138,6 @@ void Unit::destroy_objects()
 		m_controller.component.id = INVALID_ID;
 		m_controller.component.id = INVALID_ID;
 	}
 	}
 
 
-	// Destroy materials
-	for (uint32_t i = 0; i < m_num_materials; i++)
-	{
-		m_world.render_world()->destroy_material(m_materials[i].component);
-	}
-	m_num_materials = 0;
-
 	// Destroy scene graph
 	// Destroy scene graph
 	m_scene_graph.destroy();
 	m_scene_graph.destroy();
 }
 }
@@ -186,13 +178,6 @@ void Unit::create_renderable_objects()
 			CE_FATAL("Oops, bad renderable type");
 			CE_FATAL("Oops, bad renderable type");
 		}
 		}
 	}
 	}
-
-	// Create materials
-	if (m_resource->material_resource().type != 0)
-	{
-		MaterialResource* mr = (MaterialResource*) device()->resource_manager()->get(m_resource->material_resource());
-		add_material(string::murmur2_32("default", string::strlen("default"), 0), m_world.render_world()->create_material(mr));
-	}
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -233,12 +218,12 @@ void Unit::create_physics_objects()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void Unit::set_default_material()
 void Unit::set_default_material()
 {
 {
-	if (m_num_materials == 0) return;
+	if (m_resource->num_materials() == 0) return;
 
 
 	for (uint32_t i = 0; i < m_num_sprites; i++)
 	for (uint32_t i = 0; i < m_num_sprites; i++)
 	{
 	{
 		Sprite* s = m_world.render_world()->get_sprite(m_sprites[i].component);
 		Sprite* s = m_world.render_world()->get_sprite(m_sprites[i].component);
-		s->set_material(m_materials[0].component);
+		s->set_material(m_resource->get_material(0).id);
 	}
 	}
 }
 }
 
 
@@ -421,14 +406,6 @@ void Unit::add_actor(StringId32 name, ActorId actor)
 	add_component(name, actor, m_num_actors, m_actors);
 	add_component(name, actor, m_num_actors, m_actors);
 }
 }
 
 
-//-----------------------------------------------------------------------------
-void Unit::add_material(StringId32 name, MaterialId material)
-{
-	CE_ASSERT(m_num_materials < CE_MAX_MATERIAL_COMPONENTS, "Max material number reached");
-
-	add_component(name, material, m_num_materials, m_materials);
-}
-
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void Unit::set_controller(StringId32 name, ControllerId controller)
 void Unit::set_controller(StringId32 name, ControllerId controller)
 {
 {
@@ -540,21 +517,23 @@ Controller* Unit::controller()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 Material* Unit::material(const char* name)
 Material* Unit::material(const char* name)
 {
 {
-	MaterialId material = find_component(name, m_num_materials, m_materials);
+/*	MaterialId material = find_component(name, m_num_materials, m_materials);
 
 
 	CE_ASSERT(material.id != INVALID_ID, "Unit does not have material with name '%s'", name);
 	CE_ASSERT(material.id != INVALID_ID, "Unit does not have material with name '%s'", name);
 
 
-	return m_world.render_world()->get_material(material);
+	return m_world.render_world()->get_material(material);*/
+	return NULL;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 Material* Unit::material(uint32_t i)
 Material* Unit::material(uint32_t i)
 {
 {
-	MaterialId material = find_component_by_index(i, m_num_materials, m_materials);
+/*	MaterialId material = find_component_by_index(i, m_num_materials, m_materials);
 
 
 	CE_ASSERT(material.id != INVALID_ID, "Unit does not have material with name '%d'", i);
 	CE_ASSERT(material.id != INVALID_ID, "Unit does not have material with name '%d'", i);
 
 
-	return m_world.render_world()->get_material(material);
+	return m_world.render_world()->get_material(material);*/
+	return NULL;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 0 - 5
engine/world/unit.h

@@ -116,7 +116,6 @@ struct Unit
 	void add_sprite(StringId32 name, SpriteId sprite);
 	void add_sprite(StringId32 name, SpriteId sprite);
 	void add_actor(StringId32 name, ActorId actor);
 	void add_actor(StringId32 name, ActorId actor);
 	void set_controller(StringId32 name, ControllerId controller);
 	void set_controller(StringId32 name, ControllerId controller);
-	void add_material(StringId32 name, MaterialId material);
 
 
 	Camera* camera(const char* name);
 	Camera* camera(const char* name);
 	Camera* camera(uint32_t i);
 	Camera* camera(uint32_t i);
@@ -181,11 +180,7 @@ public:
 	uint32_t m_num_actors;
 	uint32_t m_num_actors;
 	Component m_actors[CE_MAX_ACTOR_COMPONENTS];
 	Component m_actors[CE_MAX_ACTOR_COMPONENTS];
 
 
-	uint32_t m_num_materials;
-	Component m_materials[CE_MAX_MATERIAL_COMPONENTS];
-
 	Component m_controller;
 	Component m_controller;
-
 	char* m_values;
 	char* m_values;
 };
 };