blah/src/graphics/material.cpp

357 lines
7.2 KiB
C++
Raw Normal View History

2020-08-26 15:38:01 +08:00
#include <blah/graphics/material.h>
#include <blah/common.h>
#include <cstring>
2020-08-26 15:38:01 +08:00
using namespace Blah;
namespace
{
int calc_uniform_size(const UniformInfo& uniform)
2020-08-26 15:38:01 +08:00
{
int components = 0;
2020-08-26 15:38:01 +08:00
switch (uniform.type)
{
case UniformType::Float: components = 1; break;
case UniformType::Float2: components = 2; break;
case UniformType::Float3: components = 3; break;
case UniformType::Float4: components = 4; break;
case UniformType::Mat3x2: components = 6; break;
case UniformType::Mat4x4: components = 16; break;
default:
BLAH_ASSERT(false, "Unespected Uniform Type");
2020-08-26 15:38:01 +08:00
break;
}
return components * uniform.array_length;
}
}
2020-12-27 06:44:48 +08:00
MaterialRef Material::create(const ShaderRef& shader)
{
BLAH_ASSERT(shader, "The provided shader is invalid");
if (shader)
return MaterialRef(new Material(shader));
return MaterialRef();
}
2020-08-26 15:38:01 +08:00
Material::Material(const ShaderRef& shader)
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(shader, "Material is being created with an invalid shader");
2020-08-26 15:38:01 +08:00
m_shader = shader;
auto& uniforms = shader->uniforms();
2020-12-27 06:44:48 +08:00
int float_size = 0;
2020-08-26 15:38:01 +08:00
for (auto& uniform : uniforms)
{
if (uniform.type == UniformType::None)
continue;
if (uniform.type == UniformType::Texture2D)
2020-08-26 15:38:01 +08:00
{
for (int i = 0; i < uniform.array_length; i ++)
m_textures.push_back(TextureRef());
2020-08-26 15:38:01 +08:00
continue;
}
if (uniform.type == UniformType::Sampler2D)
{
for (int i = 0; i < uniform.array_length; i++)
m_samplers.push_back(TextureSampler());
continue;
}
2020-08-26 15:38:01 +08:00
float_size += calc_uniform_size(uniform);
}
2020-12-24 08:16:09 +08:00
m_data.expand(float_size);
2020-08-26 15:38:01 +08:00
}
2021-05-07 12:48:06 +08:00
ShaderRef Material::shader() const
2020-08-26 15:38:01 +08:00
{
return m_shader;
}
void Material::set_texture(const char* name, const TextureRef& texture, int index)
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(m_shader, "Material Shader is invalid");
2020-08-26 15:38:01 +08:00
2020-12-29 10:31:06 +08:00
int offset = 0;
for (auto& uniform : m_shader->uniforms())
2020-08-26 15:38:01 +08:00
{
if (uniform.type != UniformType::Texture2D)
2020-12-29 10:31:06 +08:00
continue;
if (strcmp(uniform.name, name) == 0)
2020-08-26 15:38:01 +08:00
{
2020-12-29 10:31:06 +08:00
m_textures[offset + index] = texture;
return;
}
2020-08-26 15:38:01 +08:00
2020-12-29 10:31:06 +08:00
offset += uniform.array_length;
if (offset + index >= m_textures.size())
break;
}
Log::warn("No Texture Uniform '%s' at index [%i] exists", name, index);
}
void Material::set_texture(int slot, const TextureRef& texture, int index)
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int s = 0;
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Texture2D)
continue;
2020-12-29 10:31:06 +08:00
if (s == slot)
{
if (index > uniform.array_length)
2020-12-29 10:31:06 +08:00
break;
m_textures[offset + index] = texture;
break;
2020-08-26 15:38:01 +08:00
}
offset += uniform.array_length;
s++;
2020-08-26 15:38:01 +08:00
}
}
TextureRef Material::get_texture(const char* name, int index) const
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(m_shader, "Material Shader is invalid");
2020-08-26 15:38:01 +08:00
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Texture2D)
2020-08-26 15:38:01 +08:00
continue;
if (strcmp(uniform.name, name) == 0)
return m_textures[offset + index];
offset += uniform.array_length;
if (offset + index >= m_textures.size())
2020-08-26 15:38:01 +08:00
break;
}
Log::warn("No Texture Uniform '%s' at index [%i] exists", name, index);
return TextureRef();
}
TextureRef Material::get_texture(int slot, int index) const
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(m_shader, "Material Shader is invalid");
2020-08-26 15:38:01 +08:00
int s = 0;
2020-12-29 10:31:06 +08:00
int offset = 0;
2020-08-26 15:38:01 +08:00
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Texture2D)
continue;
2020-08-26 15:38:01 +08:00
if (s == slot)
{
if (index > uniform.array_length)
2020-08-26 15:38:01 +08:00
break;
return m_textures[offset + index];
2020-08-26 15:38:01 +08:00
}
offset += uniform.array_length;
if (offset + index >= m_textures.size())
break;
2020-08-26 15:38:01 +08:00
s++;
}
Log::warn("No Texture Uniform ['%i'] at index [%i] exists", slot, index);
return TextureRef();
}
void Material::set_sampler(const char* name, const TextureSampler& sampler, int index)
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Sampler2D)
continue;
if (strcmp(uniform.name, name) == 0)
{
m_samplers[offset + index] = sampler;
return;
}
offset += uniform.array_length;
if (offset + index >= m_samplers.size())
break;
}
Log::warn("No Sampler Uniform '%s' at index [%i] exists", name, index);
}
void Material::set_sampler(int slot, const TextureSampler& sampler, int index)
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int s = 0;
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Sampler2D)
continue;
if (s == slot)
{
if (index > uniform.array_length)
break;
m_samplers[offset + index] = sampler;
break;
}
offset += uniform.array_length;
s++;
}
}
TextureSampler Material::get_sampler(const char* name, int index) const
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Sampler2D)
continue;
if (strcmp(uniform.name, name) == 0)
return m_samplers[offset + index];
offset += uniform.array_length;
if (offset + index >= m_samplers.size())
break;
}
Log::warn("No Sampler Uniform '%s' at index [%i] exists", name, index);
return TextureSampler();
}
TextureSampler Material::get_sampler(int slot, int index) const
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int s = 0;
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Sampler2D)
continue;
if (s == slot)
{
if (index > uniform.array_length)
break;
return m_samplers[offset + index];
}
offset += uniform.array_length;
if (offset + index >= m_samplers.size())
break;
s++;
}
Log::warn("No Sampler Uniform ['%i'] at index [%i] exists", slot, index);
return TextureSampler();
}
void Material::set_value(const char* name, const float* value, i64 length)
2020-08-26 15:38:01 +08:00
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(m_shader, "Material Shader is invalid");
2020-08-26 15:38:01 +08:00
BLAH_ASSERT(length >= 0, "Length must be >= 0");
int index = 0;
2020-12-29 10:31:06 +08:00
int offset = 0;
2020-08-26 15:38:01 +08:00
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type == UniformType::Texture2D ||
uniform.type == UniformType::Sampler2D ||
uniform.type == UniformType::None)
2020-08-26 15:38:01 +08:00
continue;
if (strcmp(uniform.name, name) == 0)
{
2020-10-25 06:37:07 +08:00
auto max = calc_uniform_size(uniform);
2020-08-26 15:38:01 +08:00
if (length > max)
{
Log::warn("Exceeding length of Uniform '%s' (%i / %i)", name, length, max);
length = max;
}
2020-12-29 10:31:06 +08:00
memcpy(m_data.begin() + offset, value, sizeof(float) * length);
2020-08-26 15:38:01 +08:00
return;
}
2020-12-29 10:31:06 +08:00
offset += calc_uniform_size(uniform);
2020-08-26 15:38:01 +08:00
index++;
}
Log::warn("No Uniform '%s' exists", name);
}
const float* Material::get_value(const char* name, i64* length) const
2020-08-26 15:38:01 +08:00
{
2020-12-24 08:16:09 +08:00
BLAH_ASSERT(m_shader, "Material Shader is invalid");
2020-08-26 15:38:01 +08:00
int index = 0;
2020-12-29 10:31:06 +08:00
int offset = 0;
2020-08-26 15:38:01 +08:00
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type == UniformType::Texture2D ||
uniform.type == UniformType::Sampler2D ||
uniform.type == UniformType::None)
2020-08-26 15:38:01 +08:00
continue;
if (strcmp(uniform.name, name) == 0)
{
if (length != nullptr)
*length = calc_uniform_size(uniform);
2020-12-29 10:31:06 +08:00
return m_data.begin() + offset;
2020-08-26 15:38:01 +08:00
}
index++;
2020-12-29 10:31:06 +08:00
offset += calc_uniform_size(uniform);
2020-08-26 15:38:01 +08:00
}
Log::warn("No Uniform '%s' exists", name);
2020-08-26 15:38:01 +08:00
*length = 0;
return nullptr;
}
2020-12-29 10:31:06 +08:00
const Vector<TextureRef>& Material::textures() const
2020-08-26 15:38:01 +08:00
{
2020-12-29 10:31:06 +08:00
return m_textures;
}
2020-08-26 15:38:01 +08:00
const Vector<TextureSampler>& Material::samplers() const
{
return m_samplers;
}
2020-12-29 10:31:06 +08:00
const float* Material::data() const
{
return m_data.begin();
}