2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/material.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/crc32.h"
|
2019-06-11 22:39:39 +02:00
|
|
|
#include "engine/file_system.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/log.h"
|
2018-06-30 15:18:27 +02:00
|
|
|
#include "engine/lua_wrapper.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/path_utils.h"
|
|
|
|
#include "engine/profiler.h"
|
|
|
|
#include "engine/resource_manager.h"
|
2019-06-11 01:09:14 +02:00
|
|
|
#include "engine/stream.h"
|
2016-02-14 16:49:37 +01:00
|
|
|
#include "renderer/pipeline.h"
|
2015-09-05 13:08:47 +02:00
|
|
|
#include "renderer/renderer.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/shader.h"
|
|
|
|
#include "renderer/texture.h"
|
2018-07-15 17:35:41 +02:00
|
|
|
#include "ffr/ffr.h"
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
namespace Lumix
|
|
|
|
{
|
|
|
|
|
2014-09-07 01:10:24 +02:00
|
|
|
|
2016-02-10 14:32:40 +01:00
|
|
|
static const float DEFAULT_ALPHA_REF_VALUE = 0.3f;
|
2016-05-17 07:10:20 +02:00
|
|
|
|
|
|
|
|
2016-03-14 00:59:28 +01:00
|
|
|
static struct CustomFlags
|
|
|
|
{
|
|
|
|
char flags[32][32];
|
|
|
|
int count;
|
|
|
|
} s_custom_flags = {};
|
2014-09-07 01:10:24 +02:00
|
|
|
|
|
|
|
|
2018-01-11 21:13:59 +01:00
|
|
|
const ResourceType Material::TYPE("material");
|
|
|
|
|
|
|
|
|
2018-08-22 20:53:54 +02:00
|
|
|
Material::Material(const Path& path, ResourceManager& resource_manager, Renderer& renderer, IAllocator& allocator)
|
2015-09-04 14:00:28 +02:00
|
|
|
: Resource(path, resource_manager, allocator)
|
|
|
|
, m_shader(nullptr)
|
|
|
|
, m_uniforms(allocator)
|
|
|
|
, m_allocator(allocator)
|
|
|
|
, m_texture_count(0)
|
2018-07-01 18:13:44 +02:00
|
|
|
, m_renderer(renderer)
|
|
|
|
, m_render_states(u64(ffr::StateFlags::CULL_BACK))
|
2017-11-07 12:03:51 +01:00
|
|
|
, m_color(1, 1, 1, 1)
|
2016-11-29 00:26:01 +01:00
|
|
|
, m_metallic(0)
|
2016-12-02 15:57:32 +01:00
|
|
|
, m_roughness(1.0f)
|
2018-02-21 17:15:47 +01:00
|
|
|
, m_emission(0.0f)
|
2016-02-08 00:18:19 +01:00
|
|
|
, m_define_mask(0)
|
2016-03-14 00:59:28 +01:00
|
|
|
, m_custom_flags(0)
|
2018-09-25 18:33:38 +02:00
|
|
|
, m_render_data(nullptr)
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
2018-10-13 23:24:44 +02:00
|
|
|
static u32 last_sort_key = 0;
|
|
|
|
m_sort_key = ++last_sort_key;
|
2018-10-13 15:08:58 +02:00
|
|
|
m_layer = m_renderer.getLayerIdx("default");
|
2016-02-10 14:32:40 +01:00
|
|
|
setAlphaRef(DEFAULT_ALPHA_REF_VALUE);
|
2015-09-04 14:00:28 +02:00
|
|
|
for (int i = 0; i < MAX_TEXTURE_COUNT; ++i)
|
|
|
|
{
|
|
|
|
m_textures[i] = nullptr;
|
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
|
|
|
setShader(nullptr);
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
Material::~Material()
|
|
|
|
{
|
|
|
|
ASSERT(isEmpty());
|
|
|
|
}
|
|
|
|
|
2015-06-18 01:33:49 +02:00
|
|
|
|
2016-03-14 00:59:28 +01:00
|
|
|
const char* Material::getCustomFlagName(int index)
|
|
|
|
{
|
|
|
|
return s_custom_flags.flags[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-25 16:50:28 +02:00
|
|
|
int Material::getCustomFlagCount()
|
|
|
|
{
|
|
|
|
return s_custom_flags.count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 Material::getCustomFlag(const char* flag_name)
|
2016-03-14 00:59:28 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < s_custom_flags.count; ++i)
|
|
|
|
{
|
2016-05-12 09:56:07 +02:00
|
|
|
if (equalStrings(s_custom_flags.flags[i], flag_name)) return 1 << i;
|
2016-03-14 00:59:28 +01:00
|
|
|
}
|
|
|
|
if (s_custom_flags.count >= lengthOf(s_custom_flags.flags))
|
|
|
|
{
|
|
|
|
ASSERT(false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
copyString(s_custom_flags.flags[s_custom_flags.count], flag_name);
|
|
|
|
++s_custom_flags.count;
|
|
|
|
return 1 << (s_custom_flags.count - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
bool Material::isDefined(u8 define_idx) const
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
2016-02-08 00:18:19 +01:00
|
|
|
return (m_define_mask & (1 << define_idx)) != 0;
|
2015-09-05 13:08:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void Material::setDefine(u8 define_idx, bool enabled)
|
2015-09-05 20:54:26 +02:00
|
|
|
{
|
2019-07-23 00:08:28 +02:00
|
|
|
u32 old_mask = m_define_mask;
|
2018-07-01 18:13:44 +02:00
|
|
|
if (enabled) {
|
2016-02-08 00:18:19 +01:00
|
|
|
m_define_mask |= 1 << define_idx;
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
else {
|
2016-02-08 00:18:19 +01:00
|
|
|
m_define_mask &= ~(1 << define_idx);
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
2019-07-23 00:08:28 +02:00
|
|
|
if(old_mask != m_define_mask) updateRenderData(false);
|
2014-10-06 23:58:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-28 19:37:15 +01:00
|
|
|
void Material::unload()
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2018-06-30 15:18:27 +02:00
|
|
|
// TODO
|
|
|
|
/*
|
2016-02-09 19:21:00 +01:00
|
|
|
m_uniforms.clear();
|
2018-06-30 15:18:27 +02:00
|
|
|
*/
|
2018-07-01 18:13:44 +02:00
|
|
|
for (int i = 0; i < m_texture_count; i++) {
|
2019-07-23 18:24:13 +02:00
|
|
|
if (m_textures[i]) {
|
2015-05-31 15:48:35 +02:00
|
|
|
removeDependency(*m_textures[i]);
|
2019-07-23 18:24:13 +02:00
|
|
|
m_textures[i]->getResourceManager().unload(*m_textures[i]);
|
2015-02-28 13:05:01 +01:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
m_texture_count = 0;
|
2018-07-11 23:35:34 +02:00
|
|
|
for(Texture*& tex : m_textures ) {
|
|
|
|
tex = nullptr;
|
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
|
2018-09-25 18:33:38 +02:00
|
|
|
m_renderer.runInRenderThread(m_render_data, [](Renderer& renderer, void* ptr){
|
|
|
|
LUMIX_DELETE(renderer.getAllocator(), (RenderData*)ptr);
|
|
|
|
});
|
|
|
|
m_render_data = nullptr;
|
|
|
|
|
2018-04-19 20:49:20 +02:00
|
|
|
setShader(nullptr);
|
|
|
|
|
2017-09-05 22:32:28 +02:00
|
|
|
m_alpha_ref = 0.3f;
|
2017-11-07 12:03:51 +01:00
|
|
|
m_color.set(1, 1, 1, 1);
|
2017-09-05 22:32:28 +02:00
|
|
|
m_custom_flags = 0;
|
2016-05-08 11:41:27 +02:00
|
|
|
m_define_mask = 0;
|
2017-09-05 22:32:28 +02:00
|
|
|
m_metallic = 0.0f;
|
|
|
|
m_roughness = 1.0f;
|
2018-02-21 17:15:47 +01:00
|
|
|
m_emission = 0.0f;
|
2018-07-01 18:13:44 +02:00
|
|
|
m_render_states = u64(ffr::StateFlags::CULL_BACK);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-11 01:09:14 +02:00
|
|
|
bool Material::save(IOutputStream& file)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
if(!isReady()) return false;
|
|
|
|
if(!m_shader) return false;
|
2018-08-05 18:00:30 +02:00
|
|
|
|
2018-12-24 16:15:22 +01:00
|
|
|
file << "shader \"" << m_shader->getPath().c_str() << "\"\n";
|
2018-09-09 15:31:09 +02:00
|
|
|
file << "backface_culling(" << (isBackfaceCulling() ? "true" : "false") << ")\n";
|
2018-10-27 21:05:52 +02:00
|
|
|
file << "layer \"" << m_renderer.getLayerName(m_layer) << "\"\n";
|
2016-02-09 19:21:00 +01:00
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
char tmp[64];
|
2019-07-25 18:50:31 +02:00
|
|
|
toCString(m_metallic, Span(tmp), 9);
|
2018-08-05 18:00:30 +02:00
|
|
|
file << "metallic(" << tmp << ")\n";
|
2019-07-25 18:50:31 +02:00
|
|
|
toCString(m_roughness, Span(tmp), 9);
|
2018-08-05 18:00:30 +02:00
|
|
|
file << "roughness(" << tmp << ")\n";
|
2019-07-25 18:50:31 +02:00
|
|
|
toCString(m_alpha_ref, Span(tmp), 9);
|
2019-07-18 18:34:52 +02:00
|
|
|
file << "alpha_ref(" << tmp << ")\n";
|
2016-02-08 00:18:19 +01:00
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
file << "defines {";
|
|
|
|
for (int i = 0; i < sizeof(m_define_mask) * 8; ++i) {
|
|
|
|
if ((m_define_mask & (1 << i)) == 0) continue;
|
2018-10-27 21:05:52 +02:00
|
|
|
const char* def = m_renderer.getShaderDefine(i);
|
2018-12-24 16:15:22 +01:00
|
|
|
if (i > 0) file << ", ";
|
2018-08-05 18:00:30 +02:00
|
|
|
file << "\"" << def << "\"";
|
|
|
|
}
|
|
|
|
file << "}\n";
|
|
|
|
|
2018-09-08 14:41:18 +02:00
|
|
|
StaticString<1024> color_tmp("", m_color.x, ", ", m_color.y, ", ", m_color.z, ", ", m_color.w);
|
|
|
|
file << "color { " << color_tmp << " }\n";
|
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
for (int i = 0; i < m_texture_count; ++i) {
|
2015-07-30 00:33:52 +02:00
|
|
|
char path[MAX_PATH_LENGTH];
|
2018-08-05 18:00:30 +02:00
|
|
|
if (m_textures[i] && m_textures[i] != m_shader->m_texture_slots[i].default_texture) {
|
2019-07-25 18:50:31 +02:00
|
|
|
copyString(Span(path), m_textures[i]->getPath().c_str());
|
2015-05-31 15:48:35 +02:00
|
|
|
}
|
2018-08-05 18:00:30 +02:00
|
|
|
else {
|
2015-05-31 15:48:35 +02:00
|
|
|
path[0] = '\0';
|
2014-09-28 17:29:39 +02:00
|
|
|
}
|
2018-08-05 18:00:30 +02:00
|
|
|
file << "texture \"/" << path << "\"\n";
|
|
|
|
|
|
|
|
/*serializer.beginObject("texture");
|
2015-05-31 15:48:35 +02:00
|
|
|
serializer.serialize("source", path);
|
2015-09-25 23:03:10 +02:00
|
|
|
if (flags & BGFX_TEXTURE_U_CLAMP) serializer.serialize("u_clamp", true);
|
|
|
|
if (flags & BGFX_TEXTURE_V_CLAMP) serializer.serialize("v_clamp", true);
|
|
|
|
if (flags & BGFX_TEXTURE_W_CLAMP) serializer.serialize("w_clamp", true);
|
|
|
|
if (flags & BGFX_TEXTURE_MIN_POINT) serializer.serialize("min_filter", "point");
|
|
|
|
if (flags & BGFX_TEXTURE_MIN_ANISOTROPIC) serializer.serialize("min_filter", "anisotropic");
|
|
|
|
if (flags & BGFX_TEXTURE_MAG_POINT) serializer.serialize("mag_filter", "point");
|
|
|
|
if (flags & BGFX_TEXTURE_MAG_ANISOTROPIC) serializer.serialize("mag_filter", "anisotropic");
|
|
|
|
if (m_textures[i] && m_textures[i]->getData()) serializer.serialize("keep_data", true);
|
2018-08-05 18:00:30 +02:00
|
|
|
serializer.endObject();*/
|
2014-09-28 17:29:39 +02:00
|
|
|
}
|
2016-02-08 00:18:19 +01:00
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
// TODO
|
|
|
|
/*
|
|
|
|
|
|
|
|
serializer.beginObject();
|
|
|
|
serializer.serialize("render_layer", renderer.getLayerName(m_render_layer));
|
|
|
|
serializer.serialize("layers_count", m_layers_count);
|
|
|
|
serializer.serialize("backface_culling", isBackfaceCulling());
|
|
|
|
|
|
|
|
|
2016-03-14 00:59:28 +01:00
|
|
|
if (m_custom_flags != 0)
|
|
|
|
{
|
|
|
|
serializer.beginArray("custom_flags");
|
|
|
|
for (int i = 0; i < 32; ++i)
|
|
|
|
{
|
|
|
|
if (m_custom_flags & (1 << i)) serializer.serializeArrayItem(s_custom_flags.flags[i]);
|
|
|
|
}
|
|
|
|
serializer.endArray();
|
|
|
|
}
|
|
|
|
|
2014-09-28 17:29:39 +02:00
|
|
|
serializer.beginArray("uniforms");
|
2016-05-07 12:59:47 +02:00
|
|
|
for (int i = 0; i < m_shader->m_uniforms.size(); ++i)
|
2014-09-28 17:29:39 +02:00
|
|
|
{
|
|
|
|
serializer.beginObject();
|
2016-05-07 12:59:47 +02:00
|
|
|
const auto& uniform = m_shader->m_uniforms[i];
|
2016-02-09 19:21:00 +01:00
|
|
|
|
|
|
|
serializer.serialize("name", uniform.name);
|
|
|
|
switch (uniform.type)
|
2014-09-28 17:29:39 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::FLOAT:
|
|
|
|
serializer.serialize("float_value", m_uniforms[i].float_value);
|
2014-09-28 17:29:39 +02:00
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::COLOR:
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.beginArray("color");
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[0]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[1]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[2]);
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.endArray();
|
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::VEC3:
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.beginArray("vec3");
|
2016-10-23 15:04:46 +02:00
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[0]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[1]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec3[2]);
|
|
|
|
serializer.endArray();
|
|
|
|
break;
|
2018-06-16 19:16:01 +02:00
|
|
|
case Shader::Uniform::VEC4:
|
|
|
|
serializer.beginArray("vec4");
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec4[0]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec4[1]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec4[2]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec4[3]);
|
|
|
|
serializer.endArray();
|
|
|
|
break;
|
2016-10-23 15:04:46 +02:00
|
|
|
case Shader::Uniform::VEC2:
|
|
|
|
serializer.beginArray("vec2");
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec2[0]);
|
|
|
|
serializer.serializeArrayItem(m_uniforms[i].vec2[1]);
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.endArray();
|
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::TIME:
|
|
|
|
serializer.serialize("time", 0);
|
2014-09-28 17:29:39 +02:00
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::INT:
|
|
|
|
serializer.serialize("int_value", m_uniforms[i].int_value);
|
2014-09-28 17:29:39 +02:00
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::MATRIX4:
|
2014-09-28 17:29:39 +02:00
|
|
|
serializer.beginArray("matrix_value");
|
|
|
|
for (int j = 0; j < 16; ++j)
|
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.serializeArrayItem(m_uniforms[i].matrix[j]);
|
2014-09-28 17:29:39 +02:00
|
|
|
}
|
|
|
|
serializer.endArray();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ASSERT(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
serializer.endObject();
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2014-09-28 17:29:39 +02:00
|
|
|
serializer.endArray();
|
2018-02-21 17:15:47 +01:00
|
|
|
serializer.serialize("emission", m_emission);
|
2016-02-12 12:18:24 +01:00
|
|
|
serializer.beginArray("color");
|
|
|
|
serializer.serializeArrayItem(m_color.x);
|
|
|
|
serializer.serializeArrayItem(m_color.y);
|
|
|
|
serializer.serializeArrayItem(m_color.z);
|
2017-11-07 12:03:51 +01:00
|
|
|
serializer.serializeArrayItem(m_color.w);
|
2015-07-10 08:12:12 +02:00
|
|
|
serializer.endArray();
|
2018-06-30 15:18:27 +02:00
|
|
|
serializer.endObject();*/
|
2015-09-25 23:03:10 +02:00
|
|
|
return true;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
2015-11-16 12:11:10 +01:00
|
|
|
|
2018-06-30 15:18:27 +02:00
|
|
|
void Material::deserializeUniforms(lua_State* L)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2018-06-30 15:18:27 +02:00
|
|
|
// TODO
|
|
|
|
ASSERT(false);
|
|
|
|
/*
|
|
|
|
serializer.deserializeArrayBegin();
|
2016-02-09 19:21:00 +01:00
|
|
|
m_uniforms.clear();
|
2014-06-16 21:18:15 +02:00
|
|
|
while (!serializer.isArrayEnd())
|
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
Uniform& uniform = m_uniforms.emplace();
|
2014-06-16 21:18:15 +02:00
|
|
|
serializer.nextArrayItem();
|
|
|
|
serializer.deserializeObjectBegin();
|
|
|
|
char label[256];
|
|
|
|
while (!serializer.isObjectEnd())
|
|
|
|
{
|
|
|
|
serializer.deserializeLabel(label, 255);
|
2016-05-12 09:56:07 +02:00
|
|
|
if (equalStrings(label, "name"))
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
char name[32];
|
|
|
|
serializer.deserialize(name, lengthOf(name), "");
|
|
|
|
uniform.name_hash = crc32(name);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "int_value"))
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.deserialize(uniform.int_value, 0);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "float_value"))
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.deserialize(uniform.float_value, 0);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "matrix_value"))
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayBegin();
|
|
|
|
for (int i = 0; i < 16; ++i)
|
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.deserializeArrayItem(uniform.matrix[i], 0);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
serializer.deserializeArrayEnd();
|
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "time"))
|
2014-06-21 19:26:27 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.deserialize(uniform.float_value, 0);
|
2014-06-21 19:26:27 +02:00
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "color"))
|
2016-02-08 23:23:07 +01:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayBegin();
|
2016-02-09 19:21:00 +01:00
|
|
|
serializer.deserializeArrayItem(uniform.vec3[0], 0);
|
|
|
|
serializer.deserializeArrayItem(uniform.vec3[1], 0);
|
|
|
|
serializer.deserializeArrayItem(uniform.vec3[2], 0);
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.deserializeArrayEnd();
|
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "vec3"))
|
2016-02-08 23:23:07 +01:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayBegin();
|
2016-10-26 00:49:04 +02:00
|
|
|
serializer.deserializeArrayItem(uniform.vec3[0], 0);
|
|
|
|
serializer.deserializeArrayItem(uniform.vec3[1], 0);
|
|
|
|
serializer.deserializeArrayItem(uniform.vec3[2], 0);
|
|
|
|
serializer.deserializeArrayEnd();
|
|
|
|
}
|
|
|
|
else if (equalStrings(label, "vec2"))
|
|
|
|
{
|
|
|
|
serializer.deserializeArrayBegin();
|
|
|
|
serializer.deserializeArrayItem(uniform.vec2[0], 0);
|
|
|
|
serializer.deserializeArrayItem(uniform.vec2[1], 0);
|
2016-02-08 23:23:07 +01:00
|
|
|
serializer.deserializeArrayEnd();
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
else
|
|
|
|
{
|
2019-06-21 17:14:06 +02:00
|
|
|
logWarning("Renderer") << "Unknown label \"" << label << "\"";
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
serializer.deserializeObjectEnd();
|
|
|
|
}
|
2018-06-30 15:18:27 +02:00
|
|
|
serializer.deserializeArrayEnd();*/
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
2015-05-28 23:30:50 +02:00
|
|
|
|
2015-05-31 15:48:35 +02:00
|
|
|
void Material::setTexturePath(int i, const Path& path)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-05-31 15:48:35 +02:00
|
|
|
if (path.length() == 0)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-05-31 15:48:35 +02:00
|
|
|
setTexture(i, nullptr);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-05-31 15:48:35 +02:00
|
|
|
else
|
2014-09-27 22:15:14 +02:00
|
|
|
{
|
2018-08-22 20:53:54 +02:00
|
|
|
Texture* texture = m_resource_manager.getOwner().load<Texture>(path);
|
2015-05-31 15:48:35 +02:00
|
|
|
setTexture(i, texture);
|
2014-09-27 22:15:14 +02:00
|
|
|
}
|
2014-12-12 00:48:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
void Material::setTexture(int i, Texture* texture)
|
2016-02-10 15:25:28 +01:00
|
|
|
{
|
2015-06-01 23:35:57 +02:00
|
|
|
Texture* old_texture = i < m_texture_count ? m_textures[i] : nullptr;
|
2018-08-19 22:01:20 +02:00
|
|
|
if (!texture && m_shader && m_shader->isReady() && m_shader->m_texture_slots[i].default_texture)
|
2018-04-19 20:49:20 +02:00
|
|
|
{
|
|
|
|
texture = m_shader->m_texture_slots[i].default_texture;
|
2019-07-23 18:24:13 +02:00
|
|
|
texture->getResourceManager().load(*texture);
|
2018-04-19 20:49:20 +02:00
|
|
|
}
|
2019-07-23 18:24:13 +02:00
|
|
|
if (texture) addDependency(*texture);
|
2015-05-31 15:48:35 +02:00
|
|
|
m_textures[i] = texture;
|
2015-10-07 18:40:17 +02:00
|
|
|
if (i >= m_texture_count) m_texture_count = i + 1;
|
|
|
|
|
2019-07-23 18:24:13 +02:00
|
|
|
if (old_texture) {
|
2015-05-28 23:30:50 +02:00
|
|
|
removeDependency(*old_texture);
|
2019-07-23 18:24:13 +02:00
|
|
|
old_texture->getResourceManager().unload(*old_texture);
|
2015-05-28 23:30:50 +02:00
|
|
|
}
|
2015-09-05 20:54:26 +02:00
|
|
|
if (isReady() && m_shader)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-05-07 12:59:47 +02:00
|
|
|
int define_idx = m_shader->m_texture_slots[i].define_idx;
|
2016-02-10 15:25:28 +01:00
|
|
|
if(define_idx >= 0)
|
2015-09-05 20:54:26 +02:00
|
|
|
{
|
2016-02-10 15:25:28 +01:00
|
|
|
if(m_textures[i])
|
|
|
|
{
|
|
|
|
m_define_mask |= 1 << define_idx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_define_mask &= ~(1 << define_idx);
|
|
|
|
}
|
2015-09-05 20:54:26 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2019-06-30 17:40:13 +02:00
|
|
|
|
|
|
|
updateRenderData(false);
|
2014-10-06 23:58:33 +02:00
|
|
|
}
|
|
|
|
|
2014-12-12 00:48:06 +01:00
|
|
|
|
|
|
|
void Material::setShader(const Path& path)
|
|
|
|
{
|
2018-08-22 20:53:54 +02:00
|
|
|
Shader* shader = m_resource_manager.getOwner().load<Shader>(path);
|
2014-12-12 00:48:06 +01:00
|
|
|
setShader(shader);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-03 01:14:38 +02:00
|
|
|
void Material::onBeforeReady()
|
2015-05-31 15:48:35 +02:00
|
|
|
{
|
2015-10-03 01:14:38 +02:00
|
|
|
if (!m_shader) return;
|
2016-02-09 19:21:00 +01:00
|
|
|
|
2019-07-23 18:24:13 +02:00
|
|
|
for(int i = 0; i < m_shader->m_texture_slot_count; ++i) {
|
|
|
|
if (!m_textures[i] && m_shader->m_texture_slots[i].default_texture) {
|
|
|
|
m_textures[i] = m_shader->m_texture_slots[i].default_texture;
|
|
|
|
if (i >= m_texture_count) m_texture_count = i + 1;
|
|
|
|
m_textures[i]->getResourceManager().load(*m_textures[i]);
|
|
|
|
addDependency(*m_textures[i]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-07 12:59:47 +02:00
|
|
|
for(int i = 0; i < m_shader->m_uniforms.size(); ++i)
|
2016-02-09 19:21:00 +01:00
|
|
|
{
|
2016-05-07 12:59:47 +02:00
|
|
|
auto& shader_uniform = m_shader->m_uniforms[i];
|
2016-02-09 19:21:00 +01:00
|
|
|
bool found = false;
|
|
|
|
for(int j = i; j < m_uniforms.size(); ++j)
|
|
|
|
{
|
|
|
|
if(m_uniforms[j].name_hash == shader_uniform.name_hash)
|
|
|
|
{
|
|
|
|
auto tmp = m_uniforms[i];
|
|
|
|
m_uniforms[i] = m_uniforms[j];
|
|
|
|
m_uniforms[j] = tmp;
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(found) continue;
|
|
|
|
if(i < m_uniforms.size())
|
|
|
|
{
|
|
|
|
m_uniforms.emplace(m_uniforms[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_uniforms.emplace();
|
|
|
|
}
|
|
|
|
m_uniforms[i].name_hash = shader_uniform.name_hash;
|
|
|
|
}
|
|
|
|
|
2018-07-01 18:13:44 +02:00
|
|
|
for(int i = 0; i < m_shader->m_texture_slot_count; ++i) {
|
|
|
|
const int define_idx = m_shader->m_texture_slots[i].define_idx;
|
|
|
|
if(define_idx >= 0) {
|
|
|
|
if(m_textures[i]) {
|
2016-02-10 15:25:28 +01:00
|
|
|
m_define_mask |= 1 << define_idx;
|
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
else {
|
2016-02-10 15:25:28 +01:00
|
|
|
m_define_mask &= ~(1 << define_idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 22:01:20 +02:00
|
|
|
|
|
|
|
for (int i = m_shader->m_texture_slot_count; i < m_texture_count; ++i) {
|
|
|
|
setTexture(i, nullptr);
|
|
|
|
}
|
2019-06-13 17:26:52 +02:00
|
|
|
m_texture_count = minimum(m_texture_count, m_shader->m_texture_slot_count);
|
2018-10-28 17:38:15 +01:00
|
|
|
|
2019-06-24 21:17:23 +02:00
|
|
|
updateRenderData(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Material::updateRenderData(bool on_before_ready)
|
|
|
|
{
|
|
|
|
if (!m_shader) return;
|
|
|
|
if (!on_before_ready && !isReady()) return;
|
|
|
|
|
|
|
|
if(m_render_data) {
|
|
|
|
m_renderer.runInRenderThread(m_render_data, [](Renderer& renderer, void* ptr){
|
|
|
|
LUMIX_DELETE(renderer.getAllocator(), (RenderData*)ptr);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-13 00:01:11 +02:00
|
|
|
m_render_data = LUMIX_NEW(m_renderer.getAllocator(), RenderData);
|
|
|
|
m_render_data->color = m_color;
|
|
|
|
m_render_data->emission = m_emission;
|
|
|
|
m_render_data->metallic = m_metallic;
|
2019-07-18 18:34:52 +02:00
|
|
|
m_render_data->define_mask = m_define_mask;
|
2019-06-13 00:01:11 +02:00
|
|
|
m_render_data->render_states = m_render_states;
|
|
|
|
m_render_data->roughness = m_roughness;
|
|
|
|
m_render_data->shader = m_shader->m_render_data;
|
|
|
|
m_render_data->textures_count = m_texture_count;
|
|
|
|
for(int i = 0; i < m_texture_count; ++i) {
|
|
|
|
m_render_data->textures[i] = m_textures[i] ? m_textures[i]->handle : ffr::INVALID_TEXTURE;
|
2018-10-28 17:38:15 +01:00
|
|
|
}
|
2015-05-31 15:48:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
void Material::setShader(Shader* shader)
|
|
|
|
{
|
2018-07-01 18:13:44 +02:00
|
|
|
if (m_shader) {
|
2015-09-11 00:03:05 +02:00
|
|
|
Shader* shader = m_shader;
|
|
|
|
m_shader = nullptr;
|
|
|
|
removeDependency(*shader);
|
2019-07-23 18:24:13 +02:00
|
|
|
shader->getResourceManager().unload(*shader);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
m_shader = shader;
|
2018-07-01 18:13:44 +02:00
|
|
|
if (m_shader) {
|
2014-06-16 21:18:15 +02:00
|
|
|
addDependency(*m_shader);
|
2015-05-31 15:48:35 +02:00
|
|
|
}
|
2019-06-30 17:40:13 +02:00
|
|
|
|
|
|
|
updateRenderData(false);
|
2015-05-31 15:48:35 +02:00
|
|
|
}
|
|
|
|
|
2015-06-18 01:33:49 +02:00
|
|
|
|
2018-11-25 13:47:18 +01:00
|
|
|
Texture* Material::getTextureByName(const char* name) const
|
2015-05-31 15:48:35 +02:00
|
|
|
{
|
2016-08-04 20:53:20 +02:00
|
|
|
if (!m_shader) return nullptr;
|
2015-08-07 02:40:57 +02:00
|
|
|
|
2018-07-01 18:13:44 +02:00
|
|
|
for (int i = 0, c = m_shader->m_texture_slot_count; i < c; ++i) {
|
2018-11-25 13:47:18 +01:00
|
|
|
if (equalStrings(m_shader->m_texture_slots[i].name, name)) {
|
2015-05-31 15:48:35 +02:00
|
|
|
return m_textures[i];
|
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
}
|
2015-05-31 15:48:35 +02:00
|
|
|
return nullptr;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
2016-08-04 20:53:20 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
bool Material::isTextureDefine(u8 define_idx) const
|
2016-08-04 20:53:20 +02:00
|
|
|
{
|
|
|
|
if (!m_shader) return false;
|
|
|
|
|
2018-07-01 18:13:44 +02:00
|
|
|
for (int i = 0, c = m_shader->m_texture_slot_count; i < c; ++i) {
|
|
|
|
if (m_shader->m_texture_slots[i].define_idx == define_idx) {
|
2016-08-04 20:53:20 +02:00
|
|
|
return true;
|
|
|
|
}
|
2014-09-27 22:15:14 +02:00
|
|
|
}
|
2018-07-01 18:13:44 +02:00
|
|
|
return false;
|
2014-09-27 22:15:14 +02:00
|
|
|
}
|
|
|
|
|
2015-06-07 18:17:25 +02:00
|
|
|
|
2016-06-08 17:31:31 +02:00
|
|
|
void Material::enableBackfaceCulling(bool enable)
|
|
|
|
{
|
2018-07-15 17:35:41 +02:00
|
|
|
if (enable) {
|
|
|
|
m_render_states |= (u64)ffr::StateFlags::CULL_BACK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_render_states &= ~(u64)ffr::StateFlags::CULL_BACK;
|
2016-06-08 17:31:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Material::isBackfaceCulling() const
|
|
|
|
{
|
2018-07-15 17:35:41 +02:00
|
|
|
return (m_render_states & (u64)ffr::StateFlags::CULL_BACK) != 0;
|
2018-06-30 15:18:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace LuaAPI
|
|
|
|
{
|
|
|
|
|
|
|
|
|
2018-10-13 15:08:58 +02:00
|
|
|
int layer(lua_State* L)
|
|
|
|
{
|
|
|
|
const char* layer_name = LuaWrapper::checkArg<const char*>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
const int layer = material->getRenderer().getLayerIdx(layer_name);
|
|
|
|
material->setLayer(layer);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
int roughness(lua_State* L)
|
|
|
|
{
|
|
|
|
const float r = LuaWrapper::checkArg<float>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->setRoughness(r);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-22 19:52:08 +02:00
|
|
|
int alpha_ref(lua_State* L)
|
|
|
|
{
|
|
|
|
const float r = LuaWrapper::checkArg<float>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->setAlphaRef(r);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-09 15:31:09 +02:00
|
|
|
int backface_culling(lua_State* L)
|
|
|
|
{
|
|
|
|
const bool enable = LuaWrapper::checkArg<bool>(L, 1);
|
|
|
|
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->enableBackfaceCulling(enable);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-22 19:52:08 +02:00
|
|
|
int color(lua_State* L)
|
|
|
|
{
|
|
|
|
const Vec4 c = LuaWrapper::checkArg<Vec4>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->setColor(c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int custom_flag(lua_State* L)
|
|
|
|
{
|
|
|
|
const float m = LuaWrapper::checkArg<float>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
const char* flag_name = LuaWrapper::checkArg<const char*>(L, 1);
|
|
|
|
|
|
|
|
const u32 flag = material->getCustomFlag(flag_name);
|
|
|
|
material->setCustomFlag(flag);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
int metallic(lua_State* L)
|
|
|
|
{
|
|
|
|
const float m = LuaWrapper::checkArg<float>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->setMetallic(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-22 19:52:08 +02:00
|
|
|
int emission(lua_State* L)
|
|
|
|
{
|
|
|
|
const float m = LuaWrapper::checkArg<float>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
material->setEmission(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-01 18:13:44 +02:00
|
|
|
int defines(lua_State* L)
|
|
|
|
{
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
2018-11-11 13:46:42 +01:00
|
|
|
LuaWrapper::forEachArrayItem<const char*>(L, 1, "array of strings expected", [&](const char* v){
|
|
|
|
material->setDefine(material->getRenderer().getShaderDefineIdx(v), true);
|
|
|
|
});
|
2018-07-01 18:13:44 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-30 15:18:27 +02:00
|
|
|
int shader(lua_State* L)
|
|
|
|
{
|
|
|
|
const char* path = LuaWrapper::checkArg<const char*>(L, 1);
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
material->setShader(Path(path));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int texture(lua_State* L)
|
|
|
|
{
|
|
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
Material* material = (Material*)lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
2018-07-11 23:35:34 +02:00
|
|
|
char material_dir[MAX_PATH_LENGTH];
|
2019-07-25 18:50:31 +02:00
|
|
|
PathUtils::getDir(Span(material_dir), material->getPath().c_str());
|
2018-07-05 15:54:14 +02:00
|
|
|
|
|
|
|
if (lua_istable(L, 1)) {
|
|
|
|
lua_getfield(L, 1, "source");
|
|
|
|
if (lua_isstring(L, -1)) {
|
|
|
|
const char* path = lua_tostring(L, -1);
|
|
|
|
const int idx = material->getTextureCount();
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
char texture_path[MAX_PATH_LENGTH];
|
|
|
|
if (path[0] != '/' && path[0] != '\\' && path[0] != '\0')
|
|
|
|
{
|
|
|
|
copyString(texture_path, material_dir);
|
|
|
|
catString(texture_path, path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
copyString(texture_path, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
material->setTexturePath(idx, Path(texture_path));
|
2018-07-05 15:54:14 +02:00
|
|
|
}
|
|
|
|
else {
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << material->getPath() << " texture's source is not a string.";
|
2018-07-05 15:54:14 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2018-07-22 15:22:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
Texture* texture = material->getTexture(material->getTextureCount() - 1);
|
|
|
|
bool keep_data = false;
|
|
|
|
LuaWrapper::getOptionalField(L, 1, "keep_data", &keep_data);
|
|
|
|
if (keep_data) texture->addDataReference();
|
2018-07-05 15:54:14 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* path = LuaWrapper::checkArg<const char*>(L, 1);
|
2018-06-30 15:18:27 +02:00
|
|
|
const int idx = material->getTextureCount();
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
char texture_path[MAX_PATH_LENGTH];
|
|
|
|
if (path[0] != '/' && path[0] != '\\' && path[0] != '\0')
|
|
|
|
{
|
|
|
|
copyString(texture_path, material_dir);
|
|
|
|
catString(texture_path, path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
copyString(texture_path, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
material->setTexturePath(idx, Path(texture_path));
|
2018-06-30 15:18:27 +02:00
|
|
|
return 0;
|
2016-06-08 17:31:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-30 15:18:27 +02:00
|
|
|
} // namespace LuaAPI
|
|
|
|
|
|
|
|
|
2019-06-11 01:09:14 +02:00
|
|
|
bool Material::load(u64 size, const u8* mem)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2014-07-27 00:27:01 +02:00
|
|
|
PROFILE_FUNCTION();
|
2015-08-15 09:56:37 +02:00
|
|
|
|
2018-08-05 18:00:30 +02:00
|
|
|
// TODO reuse state
|
2018-06-30 15:18:27 +02:00
|
|
|
lua_State* L = luaL_newstate();
|
|
|
|
lua_pushlightuserdata(L, this);
|
|
|
|
lua_setfield(L, LUA_GLOBALSINDEX, "this");
|
|
|
|
|
2018-08-22 19:52:08 +02:00
|
|
|
#define DEFINE_LUA_FUNC(func) \
|
|
|
|
lua_pushcclosure(L, LuaAPI::func, 0); \
|
|
|
|
lua_setfield(L, LUA_GLOBALSINDEX, #func);
|
|
|
|
|
2018-10-13 15:08:58 +02:00
|
|
|
DEFINE_LUA_FUNC(alpha_ref);
|
|
|
|
DEFINE_LUA_FUNC(backface_culling);
|
|
|
|
DEFINE_LUA_FUNC(color);
|
|
|
|
DEFINE_LUA_FUNC(custom_flag);
|
2018-08-22 19:52:08 +02:00
|
|
|
DEFINE_LUA_FUNC(defines);
|
|
|
|
DEFINE_LUA_FUNC(emission);
|
2018-10-13 15:08:58 +02:00
|
|
|
DEFINE_LUA_FUNC(layer);
|
|
|
|
DEFINE_LUA_FUNC(metallic);
|
|
|
|
DEFINE_LUA_FUNC(roughness);
|
|
|
|
DEFINE_LUA_FUNC(shader);
|
|
|
|
DEFINE_LUA_FUNC(texture);
|
2018-08-22 19:52:08 +02:00
|
|
|
|
|
|
|
#undef DEFINE_LUA_FUNC
|
|
|
|
|
2016-02-10 14:32:40 +01:00
|
|
|
setAlphaRef(DEFAULT_ALPHA_REF_VALUE);
|
2018-06-30 15:18:27 +02:00
|
|
|
|
2018-08-22 19:52:08 +02:00
|
|
|
m_custom_flags = 0;
|
|
|
|
|
2019-06-11 01:09:14 +02:00
|
|
|
const StringView content((const char*)mem, (int)size);
|
2018-06-30 15:18:27 +02:00
|
|
|
if (!LuaWrapper::execute(L, content, getPath().c_str(), 0)) {
|
|
|
|
lua_close(L);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
lua_close(L);
|
2018-07-01 18:13:44 +02:00
|
|
|
return m_shader != nullptr;
|
2018-06-30 15:18:27 +02:00
|
|
|
|
|
|
|
// TODO
|
|
|
|
ASSERT(false);
|
|
|
|
/*
|
|
|
|
m_render_states = BGFX_STATE_CULL_CW;
|
|
|
|
|
2015-08-15 09:56:37 +02:00
|
|
|
m_uniforms.clear();
|
2018-06-30 15:18:27 +02:00
|
|
|
|
2018-01-11 19:38:16 +01:00
|
|
|
JsonDeserializer serializer(file, getPath(), m_allocator);
|
2015-08-15 09:56:37 +02:00
|
|
|
serializer.deserializeObjectBegin();
|
|
|
|
char label[256];
|
|
|
|
char material_dir[MAX_PATH_LENGTH];
|
2015-10-03 01:53:04 +02:00
|
|
|
PathUtils::getDir(material_dir, MAX_PATH_LENGTH, getPath().c_str());
|
2015-08-15 09:56:37 +02:00
|
|
|
while (!serializer.isObjectEnd())
|
|
|
|
{
|
|
|
|
serializer.deserializeLabel(label, 255);
|
2016-10-22 18:08:53 +02:00
|
|
|
else if (equalStrings(label, "render_layer"))
|
|
|
|
{
|
|
|
|
}
|
2016-05-12 09:56:07 +02:00
|
|
|
else if (equalStrings(label, "uniforms"))
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-08-15 09:56:37 +02:00
|
|
|
deserializeUniforms(serializer);
|
|
|
|
}
|
2016-05-18 07:09:24 +02:00
|
|
|
else if (equalStrings(label, "backface_culling"))
|
|
|
|
{
|
|
|
|
bool b = true;
|
|
|
|
serializer.deserialize(b, true);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
m_render_states |= BGFX_STATE_CULL_CW;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_render_states &= ~BGFX_STATE_CULL_MASK;
|
2018-07-01 18:13:44 +02:00
|
|
|
}
|
2016-05-18 07:09:24 +02:00
|
|
|
}
|
2015-08-15 09:56:37 +02:00
|
|
|
else
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << "Unknown parameter " << label << " in material " << getPath();
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
}
|
2015-08-15 09:56:37 +02:00
|
|
|
serializer.deserializeObjectEnd();
|
2018-06-30 15:18:27 +02:00
|
|
|
*/
|
2015-08-15 09:56:37 +02:00
|
|
|
if (!m_shader)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << "Material " << getPath() << " without a shader";
|
2015-10-03 01:14:38 +02:00
|
|
|
return false;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-08-15 09:56:37 +02:00
|
|
|
|
2019-06-11 01:09:14 +02:00
|
|
|
m_size = size;
|
2015-10-03 01:14:38 +02:00
|
|
|
return true;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-12 17:02:10 +01:00
|
|
|
} // namespace Lumix
|