restructured project to match a more standard cmake setup

This commit is contained in:
Noel Berry
2020-12-31 13:43:23 -08:00
parent c841bd82a1
commit 241d863ac4
97 changed files with 233 additions and 264 deletions

25
src/graphics/blend.cpp Normal file
View File

@ -0,0 +1,25 @@
#include <blah/graphics/blend.h>
using namespace Blah;
const BlendMode BlendMode::Normal = BlendMode(
BlendOp::Add,
BlendFactor::One,
BlendFactor::OneMinusSrcAlpha,
BlendOp::Add,
BlendFactor::One,
BlendFactor::OneMinusSrcAlpha,
BlendMask::RGBA,
0xffffffff
);
const BlendMode BlendMode::Subtract = BlendMode(
BlendOp::ReverseSubtract,
BlendFactor::One,
BlendFactor::One,
BlendOp::Add,
BlendFactor::One,
BlendFactor::One,
BlendMask::RGBA,
0xffffffff
);

View File

@ -0,0 +1,35 @@
#include <blah/graphics/framebuffer.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
FrameBufferRef FrameBuffer::create(int width, int height)
{
static const TextureFormat attachment = TextureFormat::RGBA;
return create(width, height, &attachment, 1);
}
FrameBufferRef FrameBuffer::create(int width, int height, const TextureFormat* attachments, int attachment_count)
{
BLAH_ASSERT(width > 0 && height > 0, "FrameBuffer width and height must be larger than 0");
BLAH_ASSERT(attachment_count <= BLAH_ATTACHMENTS, "Exceeded maximum attachment count");
BLAH_ASSERT(attachment_count > 0, "At least one attachment must be provided");
int color_count = 0;
int depth_count = 0;
for (int i = 0; i < attachment_count; i++)
{
BLAH_ASSERT((int)attachments[i] > (int)TextureFormat::None && (int)attachments[i] < (int)TextureFormat::Count, "Invalid texture format");
if (attachments[i] == TextureFormat::DepthStencil)
depth_count++;
else
color_count++;
}
BLAH_ASSERT(depth_count <= 1, "FrameBuffer can only have 1 Depth/Stencil Texture");
BLAH_ASSERT(color_count <= BLAH_ATTACHMENTS - 1, "Exceeded maximum Color attachment count");
return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count);
}

355
src/graphics/material.cpp Normal file
View File

@ -0,0 +1,355 @@
#include <blah/graphics/material.h>
#include <blah/core/log.h>
using namespace Blah;
namespace
{
int calc_uniform_size(const UniformInfo& uniform)
{
int components = 0;
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_ERROR("Unespected Uniform Type");
break;
}
return components * uniform.array_length;
}
}
MaterialRef Material::create(const ShaderRef& shader)
{
BLAH_ASSERT(shader, "The provided shader is invalid");
if (shader)
return MaterialRef(new Material(shader));
return MaterialRef();
}
Material::Material(const ShaderRef& shader)
{
BLAH_ASSERT(shader, "Material is being created with an invalid shader");
m_shader = shader;
auto& uniforms = shader->uniforms();
int float_size = 0;
for (auto& uniform : uniforms)
{
if (uniform.type == UniformType::None)
continue;
if (uniform.type == UniformType::Texture2D)
{
for (int i = 0; i < uniform.array_length; i ++)
m_textures.push_back(TextureRef());
continue;
}
if (uniform.type == UniformType::Sampler2D)
{
for (int i = 0; i < uniform.array_length; i++)
m_samplers.push_back(TextureSampler());
continue;
}
float_size += calc_uniform_size(uniform);
}
m_data.expand(float_size);
}
const ShaderRef Material::shader() const
{
return m_shader;
}
void Material::set_texture(const char* name, const TextureRef& texture, int index)
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type != UniformType::Texture2D)
continue;
if (strcmp(uniform.name, name) == 0)
{
m_textures[offset + index] = texture;
return;
}
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;
if (s == slot)
{
if (index > uniform.array_length)
break;
m_textures[offset + index] = texture;
break;
}
offset += uniform.array_length;
s++;
}
}
TextureRef Material::get_texture(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::Texture2D)
continue;
if (strcmp(uniform.name, name) == 0)
return m_textures[offset + index];
offset += uniform.array_length;
if (offset + index >= m_textures.size())
break;
}
Log::warn("No Texture Uniform '%s' at index [%i] exists", name, index);
return TextureRef();
}
TextureRef Material::get_texture(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::Texture2D)
continue;
if (s == slot)
{
if (index > uniform.array_length)
break;
return m_textures[offset + index];
}
offset += uniform.array_length;
if (offset + index >= m_textures.size())
break;
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, int64_t length)
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
BLAH_ASSERT(length >= 0, "Length must be >= 0");
int index = 0;
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type == UniformType::Texture2D ||
uniform.type == UniformType::Sampler2D ||
uniform.type == UniformType::None)
continue;
if (strcmp(uniform.name, name) == 0)
{
auto max = calc_uniform_size(uniform);
if (length > max)
{
Log::warn("Exceeding length of Uniform '%s' (%i / %i)", name, length, max);
length = max;
}
memcpy(m_data.begin() + offset, value, sizeof(float) * length);
return;
}
offset += calc_uniform_size(uniform);
index++;
}
Log::warn("No Uniform '%s' exists", name);
}
const float* Material::get_value(const char* name, int64_t* length) const
{
BLAH_ASSERT(m_shader, "Material Shader is invalid");
int index = 0;
int offset = 0;
for (auto& uniform : m_shader->uniforms())
{
if (uniform.type == UniformType::Texture2D ||
uniform.type == UniformType::Sampler2D ||
uniform.type == UniformType::None)
continue;
if (strcmp(uniform.name, name) == 0)
{
if (length != nullptr)
*length = calc_uniform_size(uniform);
return m_data.begin() + offset;
}
index++;
offset += calc_uniform_size(uniform);
}
*length = 0;
return nullptr;
Log::warn("No Uniform '%s' exists", name);
}
const Vector<TextureRef>& Material::textures() const
{
return m_textures;
}
const Vector<TextureSampler>& Material::samplers() const
{
return m_samplers;
}
const float* Material::data() const
{
return m_data.begin();
}

40
src/graphics/mesh.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <blah/graphics/mesh.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
MeshRef Mesh::create()
{
return GraphicsBackend::create_mesh();
}
VertexFormat::VertexFormat(std::initializer_list<VertexAttribute> attributes, int stride)
{
for (auto& it : attributes)
this->attributes.push_back(it);
if (stride <= 0)
{
stride = 0;
for (auto& it : attributes)
{
switch (it.type)
{
case VertexType::Float: stride += 4; break;
case VertexType::Float2: stride += 8; break;
case VertexType::Float3: stride += 12; break;
case VertexType::Float4: stride += 16; break;
case VertexType::Byte4: stride += 4; break;
case VertexType::UByte4: stride += 4; break;
case VertexType::Short2: stride += 4; break;
case VertexType::UShort2: stride += 4; break;
case VertexType::Short4: stride += 8; break;
case VertexType::UShort4: stride += 8; break;
}
}
}
this->stride = stride;
}

View File

@ -0,0 +1,94 @@
#include <blah/graphics/renderpass.h>
#include <blah/core/log.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
RenderPass::RenderPass()
{
blend = BlendMode::Normal;
target = App::backbuffer;
mesh = MeshRef();
material = MaterialRef();
has_viewport = false;
has_scissor = false;
viewport = Rect();
scissor = Rect();
index_start = 0;
index_count = 0;
instance_count = 0;
depth = Compare::None;
cull = Cull::None;
}
void RenderPass::perform()
{
BLAH_ASSERT(material, "Trying to draw with an invalid Material");
BLAH_ASSERT(material->shader(), "Trying to draw with an invalid Shader");
BLAH_ASSERT(mesh, "Trying to draw with an invalid Mesh");
// copy call
RenderPass pass = *this;
// Validate Backbuffer
if (!pass.target)
{
pass.target = App::backbuffer;
Log::warn("Trying to draw with an invalid Target; falling back to Back Buffer");
}
// Validate Index Count
int64_t index_count = pass.mesh->index_count();
if (pass.index_start + pass.index_count > index_count)
{
Log::warn(
"Trying to draw more indices than exist in the index buffer (%i-%i / %i); trimming extra indices",
pass.index_start,
pass.index_start + pass.index_count,
index_count);
if (pass.index_start > pass.index_count)
return;
pass.index_count = pass.index_count - pass.index_start;
}
// Validate Instance Count
int64_t instance_count = pass.mesh->instance_count();
if (pass.instance_count > instance_count)
{
Log::warn(
"Trying to draw more instances than exist in the index buffer (%i / %i); trimming extra instances",
pass.instance_count,
instance_count);
pass.instance_count = instance_count;
}
// get the total drawable size
Vec2 draw_size;
if (!pass.target)
draw_size = Vec2(App::draw_width(), App::draw_height());
else
draw_size = Vec2(pass.target->width(), pass.target->height());
// Validate Viewport
if (!pass.has_viewport)
{
pass.viewport.x = 0;
pass.viewport.y = 0;
pass.viewport.w = draw_size.x;
pass.viewport.h = draw_size.y;
}
else
{
pass.viewport = pass.viewport.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
}
// Validate Scissor
if (pass.has_scissor)
pass.scissor = pass.scissor.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
// perform render
GraphicsBackend::render(pass);
}

39
src/graphics/shader.cpp Normal file
View File

@ -0,0 +1,39 @@
#include <blah/graphics/shader.h>
#include <blah/core/app.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
ShaderRef Shader::create(const ShaderData& data)
{
BLAH_ASSERT(data.vertex.length() > 0, "Must provide a Vertex Shader");
BLAH_ASSERT(data.fragment.length() > 0, "Must provide a Fragment Shader");
BLAH_ASSERT(data.hlsl_attributes.size() > 0 || App::renderer() != Renderer::D3D11, "D3D11 Shaders must have hlsl_attributes assigned");
auto shader = GraphicsBackend::create_shader(&data);
// validate the shader
if (shader)
{
auto& uniforms = shader->uniforms();
// make sure its uniforms are valid
for (auto& it : uniforms)
if (it.type == UniformType::None)
{
BLAH_ERROR_FMT("Uniform '%s' has an invalid type!\n\tOnly Float/Float2/Float3/Float4/Mat3x2/Mat4x4/Texture are allowed!", it.name.cstr());
return ShaderRef();
}
// make sure uniform names don't overlap
for (int i = 0; i < uniforms.size(); i ++)
for (int j = i + 1; j < uniforms.size(); j ++)
if (uniforms[i].name == uniforms[j].name)
{
BLAH_ERROR_FMT("Shader Uniform names '%s' overlap! All Names must be unique.", uniforms[0].name.cstr());
return ShaderRef();
}
}
return shader;
}

61
src/graphics/texture.cpp Normal file
View File

@ -0,0 +1,61 @@
#include <blah/graphics/texture.h>
#include <blah/images/image.h>
#include <blah/streams/stream.h>
#include <blah/core/log.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
TextureRef Texture::create(const Image& image)
{
auto tex = create(image.width, image.height, TextureFormat::RGBA);
if (tex)
tex->set_data((unsigned char*)image.pixels);
return tex;
}
TextureRef Texture::create(int width, int height, unsigned char* rgba)
{
auto tex = create(width, height, TextureFormat::RGBA);
if (tex)
tex->set_data(rgba);
return tex;
}
TextureRef Texture::create(int width, int height, TextureFormat format)
{
BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0");
BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format");
return GraphicsBackend::create_texture(width, height, format);
}
TextureRef Texture::create(Stream& stream)
{
Image img = Image(stream);
if (img.pixels && img.width > 0 && img.height > 0)
{
auto tex = create(img.width, img.height, TextureFormat::RGBA);
if (tex)
tex->set_data((unsigned char*)img.pixels);
return tex;
}
return TextureRef();
}
TextureRef Texture::create(const char* file)
{
Image img = Image(file);
if (img.pixels)
{
auto tex = create(img.width, img.height, TextureFormat::RGBA);
if (tex)
tex->set_data((unsigned char*)img.pixels);
return tex;
}
return TextureRef();
}