mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
graphics refactor & new organization
This commit is contained in:
parent
2c96f0813e
commit
15608d8309
|
@ -17,17 +17,21 @@ add_library(blah
|
||||||
public/blah/time.cpp
|
public/blah/time.cpp
|
||||||
public/blah/time.h
|
public/blah/time.h
|
||||||
|
|
||||||
public/blah/graphics/graphics.h
|
public/blah/graphics/blend.h
|
||||||
public/blah/graphics/graphics.cpp
|
public/blah/graphics/blend.cpp
|
||||||
public/blah/graphics/texture.h
|
|
||||||
public/blah/graphics/framebuffer.h
|
public/blah/graphics/framebuffer.h
|
||||||
public/blah/graphics/shader.h
|
public/blah/graphics/framebuffer.cpp
|
||||||
public/blah/graphics/mesh.h
|
|
||||||
public/blah/graphics/mesh.cpp
|
|
||||||
public/blah/graphics/material.h
|
public/blah/graphics/material.h
|
||||||
public/blah/graphics/material.cpp
|
public/blah/graphics/material.cpp
|
||||||
|
public/blah/graphics/mesh.h
|
||||||
|
public/blah/graphics/mesh.cpp
|
||||||
|
public/blah/graphics/renderpass.h
|
||||||
|
public/blah/graphics/renderpass.cpp
|
||||||
|
public/blah/graphics/shader.h
|
||||||
|
public/blah/graphics/shader.cpp
|
||||||
|
public/blah/graphics/texture.h
|
||||||
|
public/blah/graphics/texture.cpp
|
||||||
|
|
||||||
public/blah/input/input.h
|
|
||||||
public/blah/input/input.cpp
|
public/blah/input/input.cpp
|
||||||
public/blah/input/virtual_stick.cpp
|
public/blah/input/virtual_stick.cpp
|
||||||
public/blah/input/virtual_stick.h
|
public/blah/input/virtual_stick.h
|
||||||
|
@ -94,15 +98,15 @@ add_library(blah
|
||||||
public/blah/streams/stream.cpp
|
public/blah/streams/stream.cpp
|
||||||
public/blah/streams/stream.h
|
public/blah/streams/stream.h
|
||||||
|
|
||||||
|
private/blah/third_party/stb_image.h
|
||||||
|
private/blah/third_party/stb_image_write.h
|
||||||
|
private/blah/third_party/stb_truetype.h
|
||||||
private/blah/internal/graphics_backend.h
|
private/blah/internal/graphics_backend.h
|
||||||
private/blah/internal/graphics_backend_gl.cpp
|
private/blah/internal/graphics_backend_gl.cpp
|
||||||
private/blah/internal/input_backend.h
|
private/blah/internal/input_backend.h
|
||||||
private/blah/internal/platform_backend.h
|
private/blah/internal/platform_backend.h
|
||||||
private/blah/internal/platform_backend_sdl2.cpp
|
private/blah/internal/platform_backend_sdl2.cpp
|
||||||
|
)
|
||||||
private/blah/third_party/stb_image.h
|
|
||||||
private/blah/third_party/stb_image_write.h
|
|
||||||
private/blah/third_party/stb_truetype.h)
|
|
||||||
|
|
||||||
target_include_directories(blah
|
target_include_directories(blah
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|
16
README.md
16
README.md
|
@ -6,8 +6,8 @@ this will likely see breaking changes.
|
||||||
|
|
||||||
#### building
|
#### building
|
||||||
- Requires C++17 and CMake
|
- Requires C++17 and CMake
|
||||||
- The [SDL2 platform backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/platform_backend_sdl2.cpp) can be enabled in CMake with `BLAH_USE_SDL2`, and setting `SDL2_INCLUDE_DIRS` and `SDL2_LIBRARIES`
|
- The [SDL2 platform backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/platform_backend_sdl2.cpp) can be enabled in CMake with `SDL2_ENABLED`, and setting `SDL2_INCLUDE_DIRS` and `SDL2_LIBRARIES`
|
||||||
- The [OpenGL graphics backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/graphics_backend_gl.cpp) can be enabled in CMake with `BLAH_USE_OPENGL`.
|
- The [OpenGL graphics backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/graphics_backend_gl.cpp) can be enabled in CMake with `OPENGL_ENABLED`.
|
||||||
- Other backends can be added by implementing the [Platform Backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/platform_backend.h) or [Graphics Backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/graphics_backend.h).
|
- Other backends can be added by implementing the [Platform Backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/platform_backend.h) or [Graphics Backend](https://github.com/NoelFB/blah/blob/master/private/blah/internal/graphics_backend.h).
|
||||||
|
|
||||||
#### notes
|
#### notes
|
||||||
|
@ -26,17 +26,17 @@ Batch batch;
|
||||||
|
|
||||||
void render()
|
void render()
|
||||||
{
|
{
|
||||||
Graphics::clear(Graphics::backbuffer, 0x00000000);
|
App::backbuffer->clear(Color::black);
|
||||||
|
|
||||||
Vec2 center = Vec2(App::draw_width(), App::draw_height()) / 2;
|
auto center = Vec2(App::backbuffer->width(), App::backbuffer->height()) / 2;
|
||||||
float rotation = Time::elapsed * Calc::TAU;
|
auto rotation = Time::elapsed * Calc::TAU;
|
||||||
Mat3x2 transform = Mat3x2::create_transform(center, Vec2::zero, Vec2::one, rotation);
|
auto transform = Mat3x2::create_transform(center, Vec2::zero, Vec2::one, rotation);
|
||||||
|
|
||||||
batch.push_matrix(transform);
|
batch.push_matrix(transform);
|
||||||
batch.rect(Rect(-32, -32, 64, 64), 0xff0000);
|
batch.rect(Rect(-32, -32, 64, 64), Color::red);
|
||||||
batch.pop_matrix();
|
batch.pop_matrix();
|
||||||
|
|
||||||
batch.render(Graphics::backbuffer);
|
batch.render();
|
||||||
batch.clear();
|
batch.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <blah/graphics/graphics.h>
|
#include <blah/app.h>
|
||||||
|
#include <blah/graphics/renderpass.h>
|
||||||
|
#include <blah/graphics/texture.h>
|
||||||
|
#include <blah/graphics/framebuffer.h>
|
||||||
|
#include <blah/graphics/shader.h>
|
||||||
|
#include <blah/graphics/mesh.h>
|
||||||
|
#include <blah/graphics/material.h>
|
||||||
|
#include <blah/math/color.h>
|
||||||
|
|
||||||
namespace Blah
|
namespace Blah
|
||||||
{
|
{
|
||||||
|
@ -14,10 +21,10 @@ namespace Blah
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
// Returns info about the renderer
|
// Returns info about the renderer
|
||||||
const GraphicsInfo* info();
|
const RendererFeatures& features();
|
||||||
|
|
||||||
// Returns the renderer type
|
// Returns the renderer type
|
||||||
GraphicsRenderer renderer();
|
Renderer renderer();
|
||||||
|
|
||||||
// Called once per frame
|
// Called once per frame
|
||||||
void frame();
|
void frame();
|
||||||
|
@ -29,10 +36,10 @@ namespace Blah
|
||||||
void after_render();
|
void after_render();
|
||||||
|
|
||||||
// Performs a draw call
|
// Performs a draw call
|
||||||
void render(const RenderCall& call);
|
void render(const RenderPass& pass);
|
||||||
|
|
||||||
// Clears a buffer
|
// Clears the backbuffer
|
||||||
void clear(const FrameBufferRef& target, uint32_t rgba);
|
void clear_backbuffer(Color color);
|
||||||
|
|
||||||
// Creates a new Texture.
|
// Creates a new Texture.
|
||||||
// if the Texture is invalid, this should return an empty reference.
|
// if the Texture is invalid, this should return an empty reference.
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#ifdef BLAH_USE_OPENGL
|
#ifdef BLAH_USE_OPENGL
|
||||||
|
|
||||||
#include <blah/graphics/graphics.h>
|
|
||||||
#include <blah/internal/graphics_backend.h>
|
#include <blah/internal/graphics_backend.h>
|
||||||
#include <blah/internal/platform_backend.h>
|
#include <blah/internal/platform_backend.h>
|
||||||
#include <blah/log.h>
|
#include <blah/log.h>
|
||||||
|
@ -360,7 +359,7 @@ namespace Blah
|
||||||
int max_samples;
|
int max_samples;
|
||||||
int max_texture_image_units;
|
int max_texture_image_units;
|
||||||
int max_texture_size;
|
int max_texture_size;
|
||||||
GraphicsInfo info;
|
RendererFeatures features;
|
||||||
};
|
};
|
||||||
|
|
||||||
// static state
|
// static state
|
||||||
|
@ -691,7 +690,7 @@ namespace Blah
|
||||||
|
|
||||||
for (int i = 0; i < attachmentCount; i++)
|
for (int i = 0; i < attachmentCount; i++)
|
||||||
{
|
{
|
||||||
auto tex = Graphics::create_texture(width, height, attachments[i]);
|
auto tex = Texture::create(width, height, attachments[i]);
|
||||||
auto gltex = ((OpenGL_Texture*)tex.get());
|
auto gltex = ((OpenGL_Texture*)tex.get());
|
||||||
|
|
||||||
gltex->framebuffer_parent = true;
|
gltex->framebuffer_parent = true;
|
||||||
|
@ -751,6 +750,20 @@ namespace Blah
|
||||||
{
|
{
|
||||||
return m_height;
|
return m_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void clear(Color color) override
|
||||||
|
{
|
||||||
|
auto rgba = color.to_rgba();
|
||||||
|
unsigned char r = rgba >> 24;
|
||||||
|
unsigned char g = rgba >> 16;
|
||||||
|
unsigned char b = rgba >> 8;
|
||||||
|
unsigned char a = rgba;
|
||||||
|
|
||||||
|
gl.BindFramebuffer(GL_FRAMEBUFFER, m_id);
|
||||||
|
gl.Disable(GL_SCISSOR_TEST);
|
||||||
|
gl.ClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||||
|
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class OpenGL_Shader : public Shader
|
class OpenGL_Shader : public Shader
|
||||||
|
@ -1106,16 +1119,16 @@ namespace Blah
|
||||||
gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
// assign info
|
// assign info
|
||||||
gl.info.instancing = true;
|
gl.features.instancing = true;
|
||||||
gl.info.origin_bottom_left = true;
|
gl.features.origin_bottom_left = true;
|
||||||
gl.info.max_texture_size = gl.max_texture_size;
|
gl.features.max_texture_size = gl.max_texture_size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsRenderer GraphicsBackend::renderer()
|
Renderer GraphicsBackend::renderer()
|
||||||
{
|
{
|
||||||
return GraphicsRenderer::OpenGL;
|
return Renderer::OpenGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsBackend::shutdown()
|
void GraphicsBackend::shutdown()
|
||||||
|
@ -1124,9 +1137,9 @@ namespace Blah
|
||||||
gl.context = nullptr;
|
gl.context = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GraphicsInfo* GraphicsBackend::info()
|
const RendererFeatures& GraphicsBackend::features()
|
||||||
{
|
{
|
||||||
return &gl.info;
|
return gl.features;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsBackend::frame() {}
|
void GraphicsBackend::frame() {}
|
||||||
|
@ -1185,27 +1198,27 @@ namespace Blah
|
||||||
return MeshRef(resource);
|
return MeshRef(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsBackend::render(const RenderCall& call)
|
void GraphicsBackend::render(const RenderPass& pass)
|
||||||
{
|
{
|
||||||
// Bind the Target
|
// Bind the Target
|
||||||
Point size;
|
Point size;
|
||||||
if (!call.target)
|
if (pass.target == App::backbuffer)
|
||||||
{
|
{
|
||||||
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
|
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
size.x = App::draw_width();
|
size.x = App::draw_width();
|
||||||
size.y = App::draw_height();
|
size.y = App::draw_height();
|
||||||
}
|
}
|
||||||
else
|
else if (pass.target)
|
||||||
{
|
{
|
||||||
auto framebuffer = (OpenGL_FrameBuffer*)call.target.get();
|
auto framebuffer = (OpenGL_FrameBuffer*)pass.target.get();
|
||||||
gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id());
|
gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id());
|
||||||
size.x = call.target->width();
|
size.x = pass.target->width();
|
||||||
size.y = call.target->height();
|
size.y = pass.target->height();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shader_ref = call.material->shader();
|
auto shader_ref = pass.material->shader();
|
||||||
auto shader = (OpenGL_Shader*)shader_ref.get();
|
auto shader = (OpenGL_Shader*)shader_ref.get();
|
||||||
auto mesh = (OpenGL_Mesh*)call.mesh.get();
|
auto mesh = (OpenGL_Mesh*)pass.mesh.get();
|
||||||
|
|
||||||
// Use the Shader
|
// Use the Shader
|
||||||
// TODO: I don't love how material values are assigned or set here
|
// TODO: I don't love how material values are assigned or set here
|
||||||
|
@ -1227,7 +1240,7 @@ namespace Blah
|
||||||
{
|
{
|
||||||
for (int n = 0; n < uniform.array_length; n++)
|
for (int n = 0; n < uniform.array_length; n++)
|
||||||
{
|
{
|
||||||
auto tex = call.material->get_texture(i, n);
|
auto tex = pass.material->get_texture(i, n);
|
||||||
|
|
||||||
gl.ActiveTexture(GL_TEXTURE0 + texture_slot);
|
gl.ActiveTexture(GL_TEXTURE0 + texture_slot);
|
||||||
|
|
||||||
|
@ -1249,59 +1262,59 @@ namespace Blah
|
||||||
// Float
|
// Float
|
||||||
else if (uniform.type == UniformType::Float)
|
else if (uniform.type == UniformType::Float)
|
||||||
{
|
{
|
||||||
gl.Uniform1fv(location, (GLint)uniform.array_length, (const GLfloat*)call.material->get_value(i));
|
gl.Uniform1fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
// Float2
|
// Float2
|
||||||
else if (uniform.type == UniformType::Float2)
|
else if (uniform.type == UniformType::Float2)
|
||||||
{
|
{
|
||||||
gl.Uniform2fv(location, (GLint)uniform.array_length, (const GLfloat*)call.material->get_value(i));
|
gl.Uniform2fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
// Float3
|
// Float3
|
||||||
else if (uniform.type == UniformType::Float3)
|
else if (uniform.type == UniformType::Float3)
|
||||||
{
|
{
|
||||||
gl.Uniform3fv(location, (GLint)uniform.array_length, (const GLfloat*)call.material->get_value(i));
|
gl.Uniform3fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
// Float4
|
// Float4
|
||||||
else if (uniform.type == UniformType::Float4)
|
else if (uniform.type == UniformType::Float4)
|
||||||
{
|
{
|
||||||
gl.Uniform4fv(location, (GLint)uniform.array_length, (const GLfloat*)call.material->get_value(i));
|
gl.Uniform4fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
// Matrix3x2
|
// Matrix3x2
|
||||||
else if (uniform.type == UniformType::Mat3x2)
|
else if (uniform.type == UniformType::Mat3x2)
|
||||||
{
|
{
|
||||||
gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call.material->get_value(i));
|
gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
// Matrix4x4
|
// Matrix4x4
|
||||||
else if (uniform.type == UniformType::Mat4x4)
|
else if (uniform.type == UniformType::Mat4x4)
|
||||||
{
|
{
|
||||||
gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)call.material->get_value(i));
|
gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)pass.material->get_value(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blend Mode
|
// Blend Mode
|
||||||
{
|
{
|
||||||
GLenum colorOp = gl_get_blend_func(call.blend.colorOp);
|
GLenum colorOp = gl_get_blend_func(pass.blend.colorOp);
|
||||||
GLenum alphaOp = gl_get_blend_func(call.blend.alphaOp);
|
GLenum alphaOp = gl_get_blend_func(pass.blend.alphaOp);
|
||||||
GLenum colorSrc = gl_get_blend_factor(call.blend.colorSrc);
|
GLenum colorSrc = gl_get_blend_factor(pass.blend.colorSrc);
|
||||||
GLenum colorDst = gl_get_blend_factor(call.blend.colorDst);
|
GLenum colorDst = gl_get_blend_factor(pass.blend.colorDst);
|
||||||
GLenum alphaSrc = gl_get_blend_factor(call.blend.alphaSrc);
|
GLenum alphaSrc = gl_get_blend_factor(pass.blend.alphaSrc);
|
||||||
GLenum alphaDst = gl_get_blend_factor(call.blend.alphaDst);
|
GLenum alphaDst = gl_get_blend_factor(pass.blend.alphaDst);
|
||||||
|
|
||||||
gl.Enable(GL_BLEND);
|
gl.Enable(GL_BLEND);
|
||||||
gl.BlendEquationSeparate(colorOp, alphaOp);
|
gl.BlendEquationSeparate(colorOp, alphaOp);
|
||||||
gl.BlendFuncSeparate(colorSrc, colorDst, alphaSrc, alphaDst);
|
gl.BlendFuncSeparate(colorSrc, colorDst, alphaSrc, alphaDst);
|
||||||
|
|
||||||
gl.ColorMask(
|
gl.ColorMask(
|
||||||
((int)call.blend.mask & (int)BlendMask::Red),
|
((int)pass.blend.mask & (int)BlendMask::Red),
|
||||||
((int)call.blend.mask & (int)BlendMask::Green),
|
((int)pass.blend.mask & (int)BlendMask::Green),
|
||||||
((int)call.blend.mask & (int)BlendMask::Blue),
|
((int)pass.blend.mask & (int)BlendMask::Blue),
|
||||||
((int)call.blend.mask & (int)BlendMask::Alpha));
|
((int)pass.blend.mask & (int)BlendMask::Alpha));
|
||||||
|
|
||||||
unsigned char r = call.blend.rgba >> 24;
|
unsigned char r = pass.blend.rgba >> 24;
|
||||||
unsigned char g = call.blend.rgba >> 16;
|
unsigned char g = pass.blend.rgba >> 16;
|
||||||
unsigned char b = call.blend.rgba >> 8;
|
unsigned char b = pass.blend.rgba >> 8;
|
||||||
unsigned char a = call.blend.rgba;
|
unsigned char a = pass.blend.rgba;
|
||||||
|
|
||||||
gl.BlendColor(
|
gl.BlendColor(
|
||||||
r / 255.0f,
|
r / 255.0f,
|
||||||
|
@ -1312,7 +1325,7 @@ namespace Blah
|
||||||
|
|
||||||
// Depth Function
|
// Depth Function
|
||||||
{
|
{
|
||||||
if (call.depth == Compare::None)
|
if (pass.depth == Compare::None)
|
||||||
{
|
{
|
||||||
gl.Disable(GL_DEPTH_TEST);
|
gl.Disable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
@ -1320,7 +1333,7 @@ namespace Blah
|
||||||
{
|
{
|
||||||
gl.Enable(GL_DEPTH_TEST);
|
gl.Enable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
switch (call.depth)
|
switch (pass.depth)
|
||||||
{
|
{
|
||||||
case Compare::None: break;
|
case Compare::None: break;
|
||||||
case Compare::Always:
|
case Compare::Always:
|
||||||
|
@ -1353,7 +1366,7 @@ namespace Blah
|
||||||
|
|
||||||
// Cull Mode
|
// Cull Mode
|
||||||
{
|
{
|
||||||
if (call.cull == Cull::None)
|
if (pass.cull == Cull::None)
|
||||||
{
|
{
|
||||||
gl.Disable(GL_CULL_FACE);
|
gl.Disable(GL_CULL_FACE);
|
||||||
}
|
}
|
||||||
|
@ -1361,9 +1374,9 @@ namespace Blah
|
||||||
{
|
{
|
||||||
gl.Enable(GL_CULL_FACE);
|
gl.Enable(GL_CULL_FACE);
|
||||||
|
|
||||||
if (call.cull == Cull::Back)
|
if (pass.cull == Cull::Back)
|
||||||
gl.CullFace(GL_BACK);
|
gl.CullFace(GL_BACK);
|
||||||
else if (call.cull == Cull::Front)
|
else if (pass.cull == Cull::Front)
|
||||||
gl.CullFace(GL_FRONT);
|
gl.CullFace(GL_FRONT);
|
||||||
else
|
else
|
||||||
gl.CullFace(GL_FRONT_AND_BACK);
|
gl.CullFace(GL_FRONT_AND_BACK);
|
||||||
|
@ -1372,7 +1385,7 @@ namespace Blah
|
||||||
|
|
||||||
// Viewport
|
// Viewport
|
||||||
{
|
{
|
||||||
Rect viewport = call.viewport;
|
Rect viewport = pass.viewport;
|
||||||
viewport.y = size.y - viewport.y - viewport.h;
|
viewport.y = size.y - viewport.y - viewport.h;
|
||||||
|
|
||||||
gl.Viewport((GLint)viewport.x, (GLint)viewport.y, (GLint)viewport.w, (GLint)viewport.h);
|
gl.Viewport((GLint)viewport.x, (GLint)viewport.y, (GLint)viewport.w, (GLint)viewport.h);
|
||||||
|
@ -1380,13 +1393,13 @@ namespace Blah
|
||||||
|
|
||||||
// Scissor
|
// Scissor
|
||||||
{
|
{
|
||||||
if (!call.has_scissor)
|
if (!pass.has_scissor)
|
||||||
{
|
{
|
||||||
gl.Disable(GL_SCISSOR_TEST);
|
gl.Disable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Rect scissor = call.scissor;
|
Rect scissor = pass.scissor;
|
||||||
scissor.y = size.y - scissor.y - scissor.h;
|
scissor.y = size.y - scissor.y - scissor.h;
|
||||||
|
|
||||||
if (scissor.w < 0)
|
if (scissor.w < 0)
|
||||||
|
@ -1403,46 +1416,37 @@ namespace Blah
|
||||||
{
|
{
|
||||||
gl.BindVertexArray(mesh->gl_id());
|
gl.BindVertexArray(mesh->gl_id());
|
||||||
|
|
||||||
if (call.instance_count > 0)
|
if (pass.instance_count > 0)
|
||||||
{
|
{
|
||||||
gl.DrawElementsInstanced(
|
gl.DrawElementsInstanced(
|
||||||
GL_TRIANGLES,
|
GL_TRIANGLES,
|
||||||
(GLint)(call.index_count),
|
(GLint)(pass.index_count),
|
||||||
GL_UNSIGNED_INT,
|
GL_UNSIGNED_INT,
|
||||||
(void*)(sizeof(int) * call.index_start),
|
(void*)(sizeof(int) * pass.index_start),
|
||||||
(GLint)call.instance_count);
|
(GLint)pass.instance_count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gl.DrawElements(
|
gl.DrawElements(
|
||||||
GL_TRIANGLES,
|
GL_TRIANGLES,
|
||||||
(GLint)(call.index_count),
|
(GLint)(pass.index_count),
|
||||||
GL_UNSIGNED_INT,
|
GL_UNSIGNED_INT,
|
||||||
(void*)(sizeof(int) * call.index_start));
|
(void*)(sizeof(int) * pass.index_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BindVertexArray(0);
|
gl.BindVertexArray(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsBackend::clear(const FrameBufferRef& target, uint32_t rgba)
|
void GraphicsBackend::clear_backbuffer(Color color)
|
||||||
{
|
{
|
||||||
if (!target)
|
auto rgba = color.to_rgba();
|
||||||
{
|
|
||||||
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto framebuffer = (OpenGL_FrameBuffer*)target.get();
|
|
||||||
if (framebuffer != nullptr)
|
|
||||||
gl.BindFramebuffer(GL_FRAMEBUFFER, framebuffer->gl_id());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char r = rgba >> 24;
|
unsigned char r = rgba >> 24;
|
||||||
unsigned char g = rgba >> 16;
|
unsigned char g = rgba >> 16;
|
||||||
unsigned char b = rgba >> 8;
|
unsigned char b = rgba >> 8;
|
||||||
unsigned char a = rgba;
|
unsigned char a = rgba;
|
||||||
|
|
||||||
|
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
gl.Disable(GL_SCISSOR_TEST);
|
gl.Disable(GL_SCISSOR_TEST);
|
||||||
gl.ClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
gl.ClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||||
gl.Clear(GL_COLOR_BUFFER_BIT);
|
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
|
@ -76,7 +76,7 @@ bool PlatformBackend::init(const Config* config)
|
||||||
int flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
int flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||||
|
|
||||||
// GL Attributes
|
// GL Attributes
|
||||||
if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL)
|
if (App::renderer() == Renderer::OpenGL)
|
||||||
{
|
{
|
||||||
flags |= SDL_WINDOW_OPENGL;
|
flags |= SDL_WINDOW_OPENGL;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ bool PlatformBackend::init(const Config* config)
|
||||||
void PlatformBackend::ready()
|
void PlatformBackend::ready()
|
||||||
{
|
{
|
||||||
// enable V-Sync
|
// enable V-Sync
|
||||||
if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL)
|
if (App::renderer() == Renderer::OpenGL)
|
||||||
SDL_GL_SetSwapInterval(1);
|
SDL_GL_SetSwapInterval(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ void PlatformBackend::sleep(int milliseconds)
|
||||||
|
|
||||||
void PlatformBackend::present()
|
void PlatformBackend::present()
|
||||||
{
|
{
|
||||||
if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL)
|
if (App::renderer() == Renderer::OpenGL)
|
||||||
{
|
{
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ void PlatformBackend::set_size(int width, int height)
|
||||||
|
|
||||||
void PlatformBackend::get_draw_size(int* width, int* height)
|
void PlatformBackend::get_draw_size(int* width, int* height)
|
||||||
{
|
{
|
||||||
if (GraphicsBackend::renderer() == GraphicsRenderer::OpenGL)
|
if (App::renderer() == Renderer::OpenGL)
|
||||||
{
|
{
|
||||||
SDL_GL_GetDrawableSize(window, width, height);
|
SDL_GL_GetDrawableSize(window, width, height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
#include <blah/drawing/spritefont.h>
|
#include <blah/drawing/spritefont.h>
|
||||||
#include <blah/drawing/subtexture.h>
|
#include <blah/drawing/subtexture.h>
|
||||||
|
|
||||||
|
#include <blah/graphics/blend.h>
|
||||||
#include <blah/graphics/framebuffer.h>
|
#include <blah/graphics/framebuffer.h>
|
||||||
#include <blah/graphics/graphics.h>
|
|
||||||
#include <blah/graphics/material.h>
|
#include <blah/graphics/material.h>
|
||||||
#include <blah/graphics/mesh.h>
|
#include <blah/graphics/mesh.h>
|
||||||
|
#include <blah/graphics/renderpass.h>
|
||||||
#include <blah/graphics/shader.h>
|
#include <blah/graphics/shader.h>
|
||||||
#include <blah/graphics/texture.h>
|
#include <blah/graphics/texture.h>
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ using namespace Blah;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static Config app_config;
|
Config app_config;
|
||||||
static bool app_is_running = false;
|
bool app_is_running = false;
|
||||||
static bool app_is_exiting = false;
|
bool app_is_exiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
|
@ -231,3 +231,64 @@ void App::fullscreen(bool enabled)
|
||||||
{
|
{
|
||||||
PlatformBackend::set_fullscreen(enabled);
|
PlatformBackend::set_fullscreen(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer App::renderer()
|
||||||
|
{
|
||||||
|
return GraphicsBackend::renderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const RendererFeatures& Blah::App::renderer_features()
|
||||||
|
{
|
||||||
|
return GraphicsBackend::features();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class BackBuffer final : public FrameBuffer
|
||||||
|
{
|
||||||
|
Attachments empty_attachments;
|
||||||
|
TextureRef empty_texture;
|
||||||
|
|
||||||
|
virtual Attachments& attachments() override
|
||||||
|
{
|
||||||
|
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
|
||||||
|
return empty_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const Attachments& attachments() const override
|
||||||
|
{
|
||||||
|
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
|
||||||
|
return empty_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual TextureRef& attachment(int index) override
|
||||||
|
{
|
||||||
|
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
|
||||||
|
return empty_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const TextureRef& attachment(int index) const override
|
||||||
|
{
|
||||||
|
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
|
||||||
|
return empty_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int width() const override
|
||||||
|
{
|
||||||
|
return App::draw_width();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int height() const override
|
||||||
|
{
|
||||||
|
return App::draw_height();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void clear(Color color) override
|
||||||
|
{
|
||||||
|
GraphicsBackend::clear_backbuffer(color);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const FrameBufferRef App::backbuffer = FrameBufferRef(new BackBuffer());
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <blah/graphics/framebuffer.h>
|
||||||
|
|
||||||
namespace Blah
|
namespace Blah
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,22 @@ namespace Blah
|
||||||
Config();
|
Config();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Renderer
|
||||||
|
{
|
||||||
|
None = -1,
|
||||||
|
OpenGL,
|
||||||
|
D3D11,
|
||||||
|
Metal,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RendererFeatures
|
||||||
|
{
|
||||||
|
bool instancing = false;
|
||||||
|
bool origin_bottom_left = false;
|
||||||
|
int max_texture_size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
namespace App
|
namespace App
|
||||||
{
|
{
|
||||||
// Runs the application
|
// Runs the application
|
||||||
|
@ -60,5 +77,14 @@ namespace Blah
|
||||||
|
|
||||||
// Toggles fullscreen
|
// Toggles fullscreen
|
||||||
void fullscreen(bool enabled);
|
void fullscreen(bool enabled);
|
||||||
|
|
||||||
|
// Returns the Rendering API in use
|
||||||
|
Renderer renderer();
|
||||||
|
|
||||||
|
// Retrieves the Renderer Features
|
||||||
|
const RendererFeatures& renderer_features();
|
||||||
|
|
||||||
|
// Reference to the window's back buffer
|
||||||
|
extern const FrameBufferRef backbuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -268,7 +268,7 @@ void Batch::set_texture(const TextureRef& texture)
|
||||||
if (m_batch.texture != texture)
|
if (m_batch.texture != texture)
|
||||||
{
|
{
|
||||||
m_batch.texture = texture;
|
m_batch.texture = texture;
|
||||||
m_batch.flip_vertically = Graphics::info()->origin_bottom_left && texture && texture->is_framebuffer();
|
m_batch.flip_vertically = App::renderer_features().origin_bottom_left && texture && texture->is_framebuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,53 +293,53 @@ void Batch::render(const FrameBufferRef& target, const Mat4x4& matrix)
|
||||||
{
|
{
|
||||||
if (!m_mesh)
|
if (!m_mesh)
|
||||||
{
|
{
|
||||||
m_mesh = Graphics::create_mesh();
|
m_mesh = Mesh::create();
|
||||||
m_mesh->vertex_format(attributes, 4, sizeof(Vertex));
|
m_mesh->vertex_format(attributes, 4, sizeof(Vertex));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_default_shader)
|
if (!m_default_shader)
|
||||||
m_default_shader = Graphics::create_shader(&data);
|
m_default_shader = Shader::create(&data);
|
||||||
|
|
||||||
if (!m_default_material)
|
if (!m_default_material)
|
||||||
m_default_material = Graphics::create_material(m_default_shader);
|
m_default_material = Material::create(m_default_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
// upload data
|
// upload data
|
||||||
m_mesh->index_data(m_indices.data(), m_indices.size());
|
m_mesh->index_data(m_indices.data(), m_indices.size());
|
||||||
m_mesh->vertex_data(m_vertices.data(), m_vertices.size());
|
m_mesh->vertex_data(m_vertices.data(), m_vertices.size());
|
||||||
|
|
||||||
RenderCall call;
|
RenderPass pass;
|
||||||
call.target = target;
|
pass.target = target;
|
||||||
call.mesh = m_mesh;
|
pass.mesh = m_mesh;
|
||||||
call.has_viewport = false;
|
pass.has_viewport = false;
|
||||||
call.viewport = Rect();
|
pass.viewport = Rect();
|
||||||
call.instance_count = 0;
|
pass.instance_count = 0;
|
||||||
call.depth = Compare::None;
|
pass.depth = Compare::None;
|
||||||
call.cull = Cull::None;
|
pass.cull = Cull::None;
|
||||||
|
|
||||||
for (auto& b : m_batches)
|
for (auto& b : m_batches)
|
||||||
render_single_batch(call, b, matrix);
|
render_single_batch(pass, b, matrix);
|
||||||
|
|
||||||
if (m_batch.elements > 0)
|
if (m_batch.elements > 0)
|
||||||
render_single_batch(call, m_batch, matrix);
|
render_single_batch(pass, m_batch, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::render_single_batch(RenderCall& call, const DrawBatch& b, const Mat4x4& matrix)
|
void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4& matrix)
|
||||||
{
|
{
|
||||||
call.material = b.material;
|
pass.material = b.material;
|
||||||
if (!call.material)
|
if (!pass.material)
|
||||||
call.material = m_default_material;
|
pass.material = m_default_material;
|
||||||
|
|
||||||
call.material->set_texture(texture_uniform, b.texture, 0);
|
pass.material->set_texture(texture_uniform, b.texture, 0);
|
||||||
call.material->set_value(matrix_uniform, &matrix.m11, 16);
|
pass.material->set_value(matrix_uniform, &matrix.m11, 16);
|
||||||
|
|
||||||
call.blend = b.blend;
|
pass.blend = b.blend;
|
||||||
call.has_scissor = b.scissor.w >= 0 && b.scissor.h >= 0;
|
pass.has_scissor = b.scissor.w >= 0 && b.scissor.h >= 0;
|
||||||
call.scissor = b.scissor;
|
pass.scissor = b.scissor;
|
||||||
call.index_start = (int64_t)b.offset * 3;
|
pass.index_start = (int64_t)b.offset * 3;
|
||||||
call.index_count = (int64_t)b.elements * 3;
|
pass.index_count = (int64_t)b.elements * 3;
|
||||||
|
|
||||||
Graphics::render(call);
|
pass.perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::clear()
|
void Batch::clear()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <blah/graphics/graphics.h>
|
|
||||||
#include <blah/containers/str.h>
|
#include <blah/containers/str.h>
|
||||||
#include <blah/math/vec2.h>
|
#include <blah/math/vec2.h>
|
||||||
#include <blah/math/rect.h>
|
#include <blah/math/rect.h>
|
||||||
|
@ -9,6 +8,9 @@
|
||||||
#include <blah/drawing/subtexture.h>
|
#include <blah/drawing/subtexture.h>
|
||||||
#include <blah/drawing/spritefont.h>
|
#include <blah/drawing/spritefont.h>
|
||||||
#include <blah/containers/vector.h>
|
#include <blah/containers/vector.h>
|
||||||
|
#include <blah/graphics/blend.h>
|
||||||
|
#include <blah/graphics/renderpass.h>
|
||||||
|
#include <blah/app.h>
|
||||||
|
|
||||||
namespace Blah
|
namespace Blah
|
||||||
{
|
{
|
||||||
|
@ -114,7 +116,7 @@ namespace Blah
|
||||||
void set_texture(const TextureRef& texture);
|
void set_texture(const TextureRef& texture);
|
||||||
|
|
||||||
// Draws the batch to the given target
|
// Draws the batch to the given target
|
||||||
void render(const FrameBufferRef& target);
|
void render(const FrameBufferRef& target = App::backbuffer);
|
||||||
|
|
||||||
// Draws the batch to the given target, with the provided matrix
|
// Draws the batch to the given target, with the provided matrix
|
||||||
void render(const FrameBufferRef& target, const Mat4x4& matrix);
|
void render(const FrameBufferRef& target, const Mat4x4& matrix);
|
||||||
|
@ -224,6 +226,6 @@ namespace Blah
|
||||||
Vector<int> m_layer_stack;
|
Vector<int> m_layer_stack;
|
||||||
Vector<DrawBatch> m_batches;
|
Vector<DrawBatch> m_batches;
|
||||||
|
|
||||||
void render_single_batch(RenderCall& call, const DrawBatch& b, const Mat4x4& matrix);
|
void render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4& matrix);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
#include <blah/drawing/spritefont.h>
|
#include <blah/drawing/spritefont.h>
|
||||||
#include <blah/images/font.h>
|
#include <blah/images/font.h>
|
||||||
#include <blah/images/packer.h>
|
#include <blah/images/packer.h>
|
||||||
#include <blah/graphics/graphics.h>
|
|
||||||
#include <blah/log.h>
|
#include <blah/log.h>
|
||||||
|
|
||||||
using namespace Blah;
|
using namespace Blah;
|
||||||
|
@ -199,7 +198,7 @@ void SpriteFont::build(const Font& font, float size, const uint32_t* charset)
|
||||||
packer.pack();
|
packer.pack();
|
||||||
|
|
||||||
for (auto& it : packer.pages)
|
for (auto& it : packer.pages)
|
||||||
m_atlas.push_back(Graphics::create_texture(it));
|
m_atlas.push_back(Texture::create(it));
|
||||||
|
|
||||||
// add character subtextures
|
// add character subtextures
|
||||||
for (auto& it : packer.entries)
|
for (auto& it : packer.entries)
|
||||||
|
|
|
@ -6,7 +6,7 @@ using namespace Blah;
|
||||||
Subtexture::Subtexture() {}
|
Subtexture::Subtexture() {}
|
||||||
|
|
||||||
Subtexture::Subtexture(const TextureRef& texture)
|
Subtexture::Subtexture(const TextureRef& texture)
|
||||||
: Subtexture(texture, Rect(0, 0, texture->width(), texture->height())) {}
|
: Subtexture(texture, Rect(0, 0, (float)texture->width(), (float)texture->height())) {}
|
||||||
|
|
||||||
Subtexture::Subtexture(const TextureRef& texture, Rect source)
|
Subtexture::Subtexture(const TextureRef& texture, Rect source)
|
||||||
: Subtexture(texture, source, Rect(0, 0, source.w, source.h)) {}
|
: Subtexture(texture, source, Rect(0, 0, source.w, source.h)) {}
|
||||||
|
@ -48,8 +48,8 @@ void Subtexture::crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame
|
||||||
{
|
{
|
||||||
*dest_source = (clip + source.top_left() + frame.top_left()).overlap_rect(source);
|
*dest_source = (clip + source.top_left() + frame.top_left()).overlap_rect(source);
|
||||||
|
|
||||||
dest_frame->x = Calc::min(0, frame.x + clip.x);
|
dest_frame->x = Calc::min(0.0f, frame.x + clip.x);
|
||||||
dest_frame->y = Calc::min(0, frame.y + clip.y);
|
dest_frame->y = Calc::min(0.0f, frame.y + clip.y);
|
||||||
dest_frame->w = clip.w;
|
dest_frame->w = clip.w;
|
||||||
dest_frame->h = clip.h;
|
dest_frame->h = clip.h;
|
||||||
}
|
}
|
||||||
|
|
25
public/blah/graphics/blend.cpp
Normal file
25
public/blah/graphics/blend.cpp
Normal 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
|
||||||
|
);
|
96
public/blah/graphics/blend.h
Normal file
96
public/blah/graphics/blend.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#pragma once
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
namespace Blah
|
||||||
|
{
|
||||||
|
enum class BlendOp
|
||||||
|
{
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
|
ReverseSubtract,
|
||||||
|
Min,
|
||||||
|
Max
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendFactor
|
||||||
|
{
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
SrcColor,
|
||||||
|
OneMinusSrcColor,
|
||||||
|
DstColor,
|
||||||
|
OneMinusDstColor,
|
||||||
|
SrcAlpha,
|
||||||
|
OneMinusSrcAlpha,
|
||||||
|
DstAlpha,
|
||||||
|
OneMinusDstAlpha,
|
||||||
|
ConstantColor,
|
||||||
|
OneMinusConstantColor,
|
||||||
|
ConstantAlpha,
|
||||||
|
OneMinusConstantAlpha,
|
||||||
|
SrcAlphaSaturate,
|
||||||
|
Src1Color,
|
||||||
|
OneMinusSrc1Color,
|
||||||
|
Src1Alpha,
|
||||||
|
OneMinusSrc1Alpha
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendMask
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Red = 1,
|
||||||
|
Green = 2,
|
||||||
|
Blue = 4,
|
||||||
|
Alpha = 8,
|
||||||
|
RGB = Red | Green | Blue,
|
||||||
|
RGBA = Red | Green | Blue | Alpha,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlendMode
|
||||||
|
{
|
||||||
|
BlendOp colorOp;
|
||||||
|
BlendFactor colorSrc;
|
||||||
|
BlendFactor colorDst;
|
||||||
|
BlendOp alphaOp;
|
||||||
|
BlendFactor alphaSrc;
|
||||||
|
BlendFactor alphaDst;
|
||||||
|
BlendMask mask;
|
||||||
|
uint32_t rgba;
|
||||||
|
|
||||||
|
BlendMode() = default;
|
||||||
|
|
||||||
|
BlendMode(BlendOp op, BlendFactor src, BlendFactor dst)
|
||||||
|
{
|
||||||
|
colorOp = op;
|
||||||
|
colorSrc = src;
|
||||||
|
colorDst = dst;
|
||||||
|
alphaOp = op;
|
||||||
|
alphaSrc = src;
|
||||||
|
alphaDst = dst;
|
||||||
|
mask = BlendMask::RGBA;
|
||||||
|
rgba = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlendMode(BlendOp rgbOp, BlendFactor rgbSrc, BlendFactor rgbDst, BlendOp aOp, BlendFactor aSrc, BlendFactor aDst, BlendMask blendMask, uint32_t blendColor)
|
||||||
|
{
|
||||||
|
colorOp = rgbOp;
|
||||||
|
colorSrc = rgbSrc;
|
||||||
|
colorDst = rgbDst;
|
||||||
|
alphaOp = aOp;
|
||||||
|
alphaSrc = aSrc;
|
||||||
|
alphaDst = aDst;
|
||||||
|
mask = blendMask;
|
||||||
|
rgba = blendColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const BlendMode& rhs) const {
|
||||||
|
return colorOp == rhs.colorOp && colorSrc == rhs.colorSrc && colorDst == rhs.colorDst &&
|
||||||
|
alphaOp == rhs.alphaOp && alphaSrc == rhs.alphaSrc && alphaDst == rhs.alphaDst &&
|
||||||
|
mask == rhs.mask && rgba == rhs.rgba;
|
||||||
|
}
|
||||||
|
inline bool operator!=(const BlendMode& rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
static const BlendMode Normal;
|
||||||
|
static const BlendMode Subtract;
|
||||||
|
};
|
||||||
|
}
|
38
public/blah/graphics/framebuffer.cpp
Normal file
38
public/blah/graphics/framebuffer.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <blah/graphics/framebuffer.h>
|
||||||
|
#include <blah/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");
|
||||||
|
|
||||||
|
if (color_count <= BLAH_ATTACHMENTS - 1 && depth_count <= 1 && width > 0 && height > 0)
|
||||||
|
return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count);
|
||||||
|
|
||||||
|
return FrameBufferRef();
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <blah/graphics/texture.h>
|
#include <blah/graphics/texture.h>
|
||||||
#include <blah/containers/stackvector.h>
|
#include <blah/containers/stackvector.h>
|
||||||
|
#include <blah/math/color.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// 4 color attachments + 1 depth/stencil
|
// 4 color attachments + 1 depth/stencil
|
||||||
|
@ -10,9 +11,21 @@ namespace Blah
|
||||||
{
|
{
|
||||||
typedef StackVector<TextureRef, BLAH_ATTACHMENTS> Attachments;
|
typedef StackVector<TextureRef, BLAH_ATTACHMENTS> Attachments;
|
||||||
|
|
||||||
|
class FrameBuffer;
|
||||||
|
typedef std::shared_ptr<FrameBuffer> FrameBufferRef;
|
||||||
|
|
||||||
class FrameBuffer
|
class FrameBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Creates a new FrameBuffer with a single Color attachment
|
||||||
|
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
||||||
|
static FrameBufferRef create(int width, int height);
|
||||||
|
|
||||||
|
// Creates a new FrameBuffer with the given Texture Attachments. You must provide at least one Attachment.
|
||||||
|
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
||||||
|
static FrameBufferRef create(int width, int height, const TextureFormat* attachments, int attachmentCount);
|
||||||
|
|
||||||
virtual ~FrameBuffer() = default;
|
virtual ~FrameBuffer() = default;
|
||||||
|
|
||||||
// Gets the list of Attachments from the FrameBuffer
|
// Gets the list of Attachments from the FrameBuffer
|
||||||
|
@ -32,7 +45,9 @@ namespace Blah
|
||||||
|
|
||||||
// Gets the height of the FrameBuffer
|
// Gets the height of the FrameBuffer
|
||||||
virtual int height() const = 0;
|
virtual int height() const = 0;
|
||||||
|
|
||||||
|
// Clears the FrameBuffer
|
||||||
|
virtual void clear(Color color) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<FrameBuffer> FrameBufferRef;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
#include <blah/graphics/graphics.h>
|
|
||||||
#include <blah/graphics/texture.h>
|
|
||||||
#include <blah/graphics/framebuffer.h>
|
|
||||||
#include <blah/graphics/mesh.h>
|
|
||||||
#include <blah/graphics/material.h>
|
|
||||||
#include <blah/graphics/shader.h>
|
|
||||||
#include <blah/log.h>
|
|
||||||
#include <blah/app.h>
|
|
||||||
#include <blah/internal/graphics_backend.h>
|
|
||||||
#include <blah/images/image.h>
|
|
||||||
#include <string.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
|
|
||||||
);
|
|
||||||
|
|
||||||
const GraphicsInfo* Graphics::info()
|
|
||||||
{
|
|
||||||
return GraphicsBackend::info();
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsRenderer Graphics::renderer()
|
|
||||||
{
|
|
||||||
return GraphicsBackend::renderer();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(const Image& image)
|
|
||||||
{
|
|
||||||
auto tex = create_texture(image.width, image.height, TextureFormat::RGBA);
|
|
||||||
tex->set_data((unsigned char*)image.pixels);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(int width, int height, unsigned char* rgba)
|
|
||||||
{
|
|
||||||
auto tex = create_texture(width, height, TextureFormat::RGBA);
|
|
||||||
tex->set_data(rgba);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(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");
|
|
||||||
|
|
||||||
if (width > 0 && height > 0)
|
|
||||||
return GraphicsBackend::create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format);
|
|
||||||
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(Stream& stream)
|
|
||||||
{
|
|
||||||
Image img = Image(stream);
|
|
||||||
|
|
||||||
if (img.pixels != nullptr && img.width > 0 && img.height > 0)
|
|
||||||
{
|
|
||||||
auto tex = create_texture(img.width, img.height, TextureFormat::RGBA);
|
|
||||||
tex->set_data((unsigned char*)img.pixels);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(const char* file)
|
|
||||||
{
|
|
||||||
Image img = Image(file);
|
|
||||||
|
|
||||||
if (img.pixels != nullptr)
|
|
||||||
{
|
|
||||||
auto tex = create_texture(img.width, img.height, TextureFormat::RGBA);
|
|
||||||
tex->set_data((unsigned char*)img.pixels);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TextureRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameBufferRef Graphics::create_framebuffer(int width, int height)
|
|
||||||
{
|
|
||||||
static const TextureFormat attachment = TextureFormat::RGBA;
|
|
||||||
return create_framebuffer(width, height, &attachment, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameBufferRef Graphics::create_framebuffer(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");
|
|
||||||
|
|
||||||
if (color_count <= BLAH_ATTACHMENTS - 1 && depth_count <= 1 && width > 0 && height > 0)
|
|
||||||
return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count);
|
|
||||||
|
|
||||||
return FrameBufferRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderRef Graphics::create_shader(const ShaderData* data)
|
|
||||||
{
|
|
||||||
return GraphicsBackend::create_shader(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialRef Graphics::create_material(const ShaderRef& shader)
|
|
||||||
{
|
|
||||||
BLAH_ASSERT(shader, "The provided shader is invalid");
|
|
||||||
|
|
||||||
if (shader)
|
|
||||||
return MaterialRef(new Material(shader));
|
|
||||||
|
|
||||||
return MaterialRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshRef Graphics::create_mesh()
|
|
||||||
{
|
|
||||||
return GraphicsBackend::create_mesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderCall::RenderCall()
|
|
||||||
{
|
|
||||||
blend = BlendMode::Normal;
|
|
||||||
target = Graphics::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 Graphics::render(const RenderCall& render_call)
|
|
||||||
{
|
|
||||||
// Validate Material
|
|
||||||
if (!render_call.material)
|
|
||||||
{
|
|
||||||
Log::warn("Trying to draw with an invalid Material");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Shader
|
|
||||||
if (!render_call.material->shader())
|
|
||||||
{
|
|
||||||
Log::warn("Trying to draw with an invalid Shader");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Mesh
|
|
||||||
if (!render_call.mesh)
|
|
||||||
{
|
|
||||||
Log::warn("Trying to draw with an invalid Mesh");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy call
|
|
||||||
RenderCall call = render_call;
|
|
||||||
|
|
||||||
// Validate Index Count
|
|
||||||
int64_t index_count = call.mesh->index_count();
|
|
||||||
if (call.index_start + call.index_count > index_count)
|
|
||||||
{
|
|
||||||
Log::warn(
|
|
||||||
"Trying to draw more indices than exist in the index buffer (%i-%i / %i)",
|
|
||||||
call.index_start,
|
|
||||||
call.index_start + call.index_count,
|
|
||||||
index_count);
|
|
||||||
|
|
||||||
if (call.index_start > call.index_count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
call.index_count = call.index_count - call.index_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Instance Count
|
|
||||||
int64_t instance_count = call.mesh->instance_count();
|
|
||||||
if (call.instance_count > instance_count)
|
|
||||||
{
|
|
||||||
Log::warn(
|
|
||||||
"Trying to draw more instances than exist in the index buffer (%i / %i)",
|
|
||||||
call.instance_count,
|
|
||||||
instance_count);
|
|
||||||
|
|
||||||
call.instance_count = instance_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the total drawable size
|
|
||||||
Point draw_size;
|
|
||||||
if (!call.target)
|
|
||||||
draw_size = Point(App::draw_width(), App::draw_height());
|
|
||||||
else
|
|
||||||
draw_size = Point(call.target->width(), call.target->height());
|
|
||||||
|
|
||||||
// Validate Viewport
|
|
||||||
if (!call.has_viewport)
|
|
||||||
{
|
|
||||||
call.viewport.x = 0;
|
|
||||||
call.viewport.y = 0;
|
|
||||||
call.viewport.w = (float)draw_size.x;
|
|
||||||
call.viewport.h = (float)draw_size.y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
call.viewport = call.viewport.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Scissor
|
|
||||||
if (call.has_scissor)
|
|
||||||
call.scissor = call.scissor.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
|
|
||||||
|
|
||||||
GraphicsBackend::render(call);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::clear(const FrameBufferRef& target, uint32_t rgba)
|
|
||||||
{
|
|
||||||
GraphicsBackend::clear(target, rgba);
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <blah/math/rect.h>
|
|
||||||
#include <blah/containers/str.h>
|
|
||||||
#include <blah/graphics/texture.h>
|
|
||||||
#include <blah/graphics/framebuffer.h>
|
|
||||||
#include <blah/graphics/mesh.h>
|
|
||||||
#include <blah/graphics/shader.h>
|
|
||||||
#include <blah/graphics/material.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace Blah
|
|
||||||
{
|
|
||||||
class Stream;
|
|
||||||
class Image;
|
|
||||||
|
|
||||||
enum class Compare
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Always,
|
|
||||||
Never,
|
|
||||||
Less,
|
|
||||||
Equal,
|
|
||||||
LessOrEqual,
|
|
||||||
Greater,
|
|
||||||
NotEqual,
|
|
||||||
GreatorOrEqual
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Cull
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Front = 1,
|
|
||||||
Back = 2,
|
|
||||||
Both = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BlendOp
|
|
||||||
{
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
ReverseSubtract,
|
|
||||||
Min,
|
|
||||||
Max
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BlendFactor
|
|
||||||
{
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
SrcColor,
|
|
||||||
OneMinusSrcColor,
|
|
||||||
DstColor,
|
|
||||||
OneMinusDstColor,
|
|
||||||
SrcAlpha,
|
|
||||||
OneMinusSrcAlpha,
|
|
||||||
DstAlpha,
|
|
||||||
OneMinusDstAlpha,
|
|
||||||
ConstantColor,
|
|
||||||
OneMinusConstantColor,
|
|
||||||
ConstantAlpha,
|
|
||||||
OneMinusConstantAlpha,
|
|
||||||
SrcAlphaSaturate,
|
|
||||||
Src1Color,
|
|
||||||
OneMinusSrc1Color,
|
|
||||||
Src1Alpha,
|
|
||||||
OneMinusSrc1Alpha
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BlendMask
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Red = 1,
|
|
||||||
Green = 2,
|
|
||||||
Blue = 4,
|
|
||||||
Alpha = 8,
|
|
||||||
RGB = Red | Green | Blue,
|
|
||||||
RGBA = Red | Green | Blue | Alpha,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlendMode
|
|
||||||
{
|
|
||||||
BlendOp colorOp;
|
|
||||||
BlendFactor colorSrc;
|
|
||||||
BlendFactor colorDst;
|
|
||||||
BlendOp alphaOp;
|
|
||||||
BlendFactor alphaSrc;
|
|
||||||
BlendFactor alphaDst;
|
|
||||||
BlendMask mask;
|
|
||||||
uint32_t rgba;
|
|
||||||
|
|
||||||
BlendMode() = default;
|
|
||||||
|
|
||||||
BlendMode(BlendOp op, BlendFactor src, BlendFactor dst)
|
|
||||||
{
|
|
||||||
colorOp = op;
|
|
||||||
colorSrc = src;
|
|
||||||
colorDst = dst;
|
|
||||||
alphaOp = op;
|
|
||||||
alphaSrc = src;
|
|
||||||
alphaDst = dst;
|
|
||||||
mask = BlendMask::RGBA;
|
|
||||||
rgba = 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlendMode(BlendOp rgbOp, BlendFactor rgbSrc, BlendFactor rgbDst, BlendOp aOp, BlendFactor aSrc, BlendFactor aDst, BlendMask blendMask, uint32_t blendColor)
|
|
||||||
{
|
|
||||||
colorOp = rgbOp;
|
|
||||||
colorSrc = rgbSrc;
|
|
||||||
colorDst = rgbDst;
|
|
||||||
alphaOp = aOp;
|
|
||||||
alphaSrc = aSrc;
|
|
||||||
alphaDst = aDst;
|
|
||||||
mask = blendMask;
|
|
||||||
rgba = blendColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const BlendMode& rhs) const {
|
|
||||||
return colorOp == rhs.colorOp && colorSrc == rhs.colorSrc && colorDst == rhs.colorDst &&
|
|
||||||
alphaOp == rhs.alphaOp && alphaSrc == rhs.alphaSrc && alphaDst == rhs.alphaDst &&
|
|
||||||
mask == rhs.mask && rgba == rhs.rgba;
|
|
||||||
}
|
|
||||||
inline bool operator!=(const BlendMode& rhs) const { return !(*this == rhs); }
|
|
||||||
|
|
||||||
static const BlendMode Normal;
|
|
||||||
static const BlendMode Subtract;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RenderCall
|
|
||||||
{
|
|
||||||
// Framebuffer to draw to
|
|
||||||
FrameBufferRef target;
|
|
||||||
|
|
||||||
// Mesh to draw with
|
|
||||||
MeshRef mesh;
|
|
||||||
|
|
||||||
// Material to draw with
|
|
||||||
MaterialRef material;
|
|
||||||
|
|
||||||
// Whether the Render Call should use a specific viewport
|
|
||||||
bool has_viewport;
|
|
||||||
|
|
||||||
// Whether the Render Call should use a scissor rectangle
|
|
||||||
bool has_scissor;
|
|
||||||
|
|
||||||
// The viewport (only used if hasViewport is true)
|
|
||||||
Rect viewport;
|
|
||||||
|
|
||||||
// The scissor rectangle (only used if hasScissor is true)
|
|
||||||
Rect scissor;
|
|
||||||
|
|
||||||
// First index in the Mesh to draw from
|
|
||||||
int64_t index_start;
|
|
||||||
|
|
||||||
// Total amount of indices to draw from the Mesh
|
|
||||||
int64_t index_count;
|
|
||||||
|
|
||||||
// Total amount of instances to draw from the Mesh
|
|
||||||
int64_t instance_count;
|
|
||||||
|
|
||||||
// Depth Compare Function
|
|
||||||
Compare depth;
|
|
||||||
|
|
||||||
// Cull Mode
|
|
||||||
Cull cull;
|
|
||||||
|
|
||||||
// Blend Mode
|
|
||||||
BlendMode blend;
|
|
||||||
|
|
||||||
// Initializes a default Render Call
|
|
||||||
RenderCall();
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class GraphicsRenderer
|
|
||||||
{
|
|
||||||
None = -1,
|
|
||||||
OpenGL,
|
|
||||||
D3D11,
|
|
||||||
Metal,
|
|
||||||
Count
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GraphicsInfo
|
|
||||||
{
|
|
||||||
bool instancing = false;
|
|
||||||
bool origin_bottom_left = false;
|
|
||||||
int max_texture_size = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Graphics
|
|
||||||
{
|
|
||||||
const FrameBufferRef backbuffer;
|
|
||||||
|
|
||||||
// Gets graphics information from the graphics device
|
|
||||||
const GraphicsInfo* info();
|
|
||||||
|
|
||||||
// Gets the Renderer implementation type
|
|
||||||
GraphicsRenderer renderer();
|
|
||||||
|
|
||||||
// Creates a new Texture.
|
|
||||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
|
||||||
TextureRef create_texture(const Image& image);
|
|
||||||
|
|
||||||
// Creates a new Texture.
|
|
||||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
|
||||||
TextureRef create_texture(int width, int height, unsigned char* rgba);
|
|
||||||
|
|
||||||
// Creates a new Texture.
|
|
||||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
|
||||||
TextureRef create_texture(int width, int height, TextureFormat format);
|
|
||||||
|
|
||||||
// Creates a new Texture from a Stream.
|
|
||||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
|
||||||
TextureRef create_texture(Stream& stream);
|
|
||||||
|
|
||||||
// Creates a new Texture from a File.
|
|
||||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
|
||||||
TextureRef create_texture(const char* file);
|
|
||||||
|
|
||||||
// Creates a new FrameBuffer with a single Color attachment
|
|
||||||
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
|
||||||
FrameBufferRef create_framebuffer(int width, int height);
|
|
||||||
|
|
||||||
// Creates a new FrameBuffer with the given Texture Attachments. You must provide at least one Attachment.
|
|
||||||
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
|
||||||
FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount);
|
|
||||||
|
|
||||||
// Creates a Shader with the given Shader Data.
|
|
||||||
// If the Shader creation fails, it will return an invalid ShaderRef.
|
|
||||||
ShaderRef create_shader(const ShaderData* data);
|
|
||||||
|
|
||||||
// Creates a new Material from the given Shader.
|
|
||||||
// If the Shader is invalid, it will return an invalid MaterialRef.
|
|
||||||
MaterialRef create_material(const ShaderRef& shader);
|
|
||||||
|
|
||||||
// Creates a new Mesh.
|
|
||||||
// If the Mesh creation fails, it will return an invalid Mesh.
|
|
||||||
MeshRef create_mesh();
|
|
||||||
|
|
||||||
// Submits and Flushes the given render call to the graphics device.
|
|
||||||
void render(const RenderCall& render_call);
|
|
||||||
|
|
||||||
// Clears the given FrameBuffer to the given color.
|
|
||||||
void clear(const FrameBufferRef& target, uint32_t rgba);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,14 +26,24 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
Material::Material(const ShaderRef& shader)
|
||||||
{
|
{
|
||||||
BLAH_ASSERT(shader, "Material is being created with an invalid shader");
|
BLAH_ASSERT(shader, "Material is being created with an invalid shader");
|
||||||
m_shader = shader;
|
m_shader = shader;
|
||||||
|
|
||||||
auto& uniforms = shader->uniforms();
|
auto& uniforms = shader->uniforms();
|
||||||
Vector<size_t> float_offsets;
|
Vector<int> float_offsets;
|
||||||
size_t float_size = 0;
|
int float_size = 0;
|
||||||
|
|
||||||
for (auto& uniform : uniforms)
|
for (auto& uniform : uniforms)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,15 +6,23 @@
|
||||||
|
|
||||||
namespace Blah
|
namespace Blah
|
||||||
{
|
{
|
||||||
|
class Material;
|
||||||
|
typedef std::shared_ptr<Material> MaterialRef;
|
||||||
|
|
||||||
class Material
|
class Material
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
Material(const ShaderRef& shader);
|
Material(const ShaderRef& shader);
|
||||||
Material(const Material& src) = delete;
|
Material(const Material& src) = delete;
|
||||||
Material(Material&& src) = delete;
|
Material(Material&& src) = delete;
|
||||||
Material& operator=(const Material& src) = delete;
|
Material& operator=(const Material& src) = delete;
|
||||||
Material& operator=(Material&& src) = delete;
|
Material& operator=(Material&& src) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Creates a new Material from the given Shader.
|
||||||
|
// If the Shader is invalid, it will return an invalid MaterialRef.
|
||||||
|
static MaterialRef create(const ShaderRef& shader);
|
||||||
|
|
||||||
// Returns the Shader assigned to the Material.
|
// Returns the Shader assigned to the Material.
|
||||||
const ShaderRef shader() const;
|
const ShaderRef shader() const;
|
||||||
|
|
||||||
|
@ -52,6 +60,4 @@ namespace Blah
|
||||||
Vector<float*> m_floats;
|
Vector<float*> m_floats;
|
||||||
Vector<float> m_data;
|
Vector<float> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Material> MaterialRef;
|
|
||||||
}
|
}
|
|
@ -1,7 +1,13 @@
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include <blah/internal/graphics_backend.h>
|
||||||
|
|
||||||
using namespace Blah;
|
using namespace Blah;
|
||||||
|
|
||||||
|
MeshRef Mesh::create()
|
||||||
|
{
|
||||||
|
return GraphicsBackend::create_mesh();
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::vertex_format(const VertexAttribute* attributes, int attribute_count, int stride)
|
void Mesh::vertex_format(const VertexAttribute* attributes, int attribute_count, int stride)
|
||||||
{
|
{
|
||||||
if (stride < 0)
|
if (stride < 0)
|
||||||
|
|
|
@ -44,9 +44,16 @@ namespace Blah
|
||||||
bool normalized;
|
bool normalized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Mesh;
|
||||||
|
typedef std::shared_ptr<Mesh> MeshRef;
|
||||||
|
|
||||||
class Mesh
|
class Mesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Creates a new Mesh.
|
||||||
|
// If the Mesh creation fails, it will return an invalid Mesh.
|
||||||
|
static MeshRef create();
|
||||||
|
|
||||||
virtual ~Mesh() = default;
|
virtual ~Mesh() = default;
|
||||||
|
|
||||||
// Sets the Vertex Format of the Mesh
|
// Sets the Vertex Format of the Mesh
|
||||||
|
@ -79,6 +86,4 @@ namespace Blah
|
||||||
virtual void vertex_format_internal(const VertexAttribute* attributes, int count, int stride) = 0;
|
virtual void vertex_format_internal(const VertexAttribute* attributes, int count, int stride) = 0;
|
||||||
virtual void instance_format_internal(const VertexAttribute* attributes, int count, int stride) = 0;
|
virtual void instance_format_internal(const VertexAttribute* attributes, int count, int stride) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Mesh> MeshRef;
|
|
||||||
}
|
}
|
111
public/blah/graphics/renderpass.cpp
Normal file
111
public/blah/graphics/renderpass.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include <blah/graphics/renderpass.h>
|
||||||
|
#include <blah/internal/graphics_backend.h>
|
||||||
|
#include <blah/log.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()
|
||||||
|
{
|
||||||
|
// Validate Material
|
||||||
|
if (!material)
|
||||||
|
{
|
||||||
|
Log::warn("Trying to draw with an invalid Material");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Shader
|
||||||
|
if (!material->shader())
|
||||||
|
{
|
||||||
|
Log::warn("Trying to draw with an invalid Shader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Mesh
|
||||||
|
if (!mesh)
|
||||||
|
{
|
||||||
|
Log::warn("Trying to draw with an invalid Mesh");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)",
|
||||||
|
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)",
|
||||||
|
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);
|
||||||
|
}
|
82
public/blah/graphics/renderpass.h
Normal file
82
public/blah/graphics/renderpass.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <blah/math/rect.h>
|
||||||
|
#include <blah/containers/str.h>
|
||||||
|
#include <blah/graphics/texture.h>
|
||||||
|
#include <blah/graphics/framebuffer.h>
|
||||||
|
#include <blah/graphics/mesh.h>
|
||||||
|
#include <blah/graphics/shader.h>
|
||||||
|
#include <blah/graphics/material.h>
|
||||||
|
#include <blah/graphics/blend.h>
|
||||||
|
|
||||||
|
namespace Blah
|
||||||
|
{
|
||||||
|
enum class Compare
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Always,
|
||||||
|
Never,
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
LessOrEqual,
|
||||||
|
Greater,
|
||||||
|
NotEqual,
|
||||||
|
GreatorOrEqual
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Cull
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Front = 1,
|
||||||
|
Back = 2,
|
||||||
|
Both = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderPass
|
||||||
|
{
|
||||||
|
// Framebuffer to draw to
|
||||||
|
FrameBufferRef target;
|
||||||
|
|
||||||
|
// Mesh to draw with
|
||||||
|
MeshRef mesh;
|
||||||
|
|
||||||
|
// Material to draw with
|
||||||
|
MaterialRef material;
|
||||||
|
|
||||||
|
// Whether the RenderPass should use a specific viewport
|
||||||
|
bool has_viewport;
|
||||||
|
|
||||||
|
// Whether the RenderPass should use a scissor rectangle
|
||||||
|
bool has_scissor;
|
||||||
|
|
||||||
|
// The viewport (only used if hasViewport is true)
|
||||||
|
Rect viewport;
|
||||||
|
|
||||||
|
// The scissor rectangle (only used if hasScissor is true)
|
||||||
|
Rect scissor;
|
||||||
|
|
||||||
|
// First index in the Mesh to draw from
|
||||||
|
int64_t index_start;
|
||||||
|
|
||||||
|
// Total amount of indices to draw from the Mesh
|
||||||
|
int64_t index_count;
|
||||||
|
|
||||||
|
// Total amount of instances to draw from the Mesh
|
||||||
|
int64_t instance_count;
|
||||||
|
|
||||||
|
// Depth Compare Function
|
||||||
|
Compare depth;
|
||||||
|
|
||||||
|
// Cull Mode
|
||||||
|
Cull cull;
|
||||||
|
|
||||||
|
// Blend Mode
|
||||||
|
BlendMode blend;
|
||||||
|
|
||||||
|
// Initializes a default RenderPass
|
||||||
|
RenderPass();
|
||||||
|
|
||||||
|
// Performs the render
|
||||||
|
void perform();
|
||||||
|
};
|
||||||
|
}
|
9
public/blah/graphics/shader.cpp
Normal file
9
public/blah/graphics/shader.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <blah/graphics/shader.h>
|
||||||
|
#include <blah/internal/graphics_backend.h>
|
||||||
|
|
||||||
|
using namespace Blah;
|
||||||
|
|
||||||
|
ShaderRef Shader::create(const ShaderData* data)
|
||||||
|
{
|
||||||
|
return GraphicsBackend::create_shader(data);
|
||||||
|
}
|
|
@ -30,9 +30,17 @@ namespace Blah
|
||||||
const char* fragment;
|
const char* fragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
typedef std::shared_ptr<Shader> ShaderRef;
|
||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Creates a Shader with the given Shader Data.
|
||||||
|
// If the Shader creation fails, it will return an invalid ShaderRef.
|
||||||
|
static ShaderRef create(const ShaderData* data);
|
||||||
|
|
||||||
virtual ~Shader() = default;
|
virtual ~Shader() = default;
|
||||||
|
|
||||||
// Gets a list of Shader Uniforms from Shader
|
// Gets a list of Shader Uniforms from Shader
|
||||||
|
@ -42,5 +50,4 @@ namespace Blah
|
||||||
virtual const Vector<UniformInfo>& uniforms() const = 0;
|
virtual const Vector<UniformInfo>& uniforms() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Shader> ShaderRef;
|
|
||||||
}
|
}
|
60
public/blah/graphics/texture.cpp
Normal file
60
public/blah/graphics/texture.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include <blah/graphics/texture.h>
|
||||||
|
#include <blah/images/image.h>
|
||||||
|
#include <blah/streams/stream.h>
|
||||||
|
#include <blah/internal/graphics_backend.h>
|
||||||
|
#include <blah/log.h>
|
||||||
|
|
||||||
|
using namespace Blah;
|
||||||
|
|
||||||
|
TextureRef Texture::create(const Image& image)
|
||||||
|
{
|
||||||
|
auto tex = create(image.width, image.height, TextureFormat::RGBA);
|
||||||
|
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);
|
||||||
|
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");
|
||||||
|
|
||||||
|
if (width > 0 && height > 0)
|
||||||
|
return GraphicsBackend::create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format);
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureRef Texture::create(Stream& stream)
|
||||||
|
{
|
||||||
|
Image img = Image(stream);
|
||||||
|
|
||||||
|
if (img.pixels != nullptr && img.width > 0 && img.height > 0)
|
||||||
|
{
|
||||||
|
auto tex = create(img.width, img.height, TextureFormat::RGBA);
|
||||||
|
tex->set_data((unsigned char*)img.pixels);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureRef Texture::create(const char* file)
|
||||||
|
{
|
||||||
|
Image img = Image(file);
|
||||||
|
|
||||||
|
if (img.pixels != nullptr)
|
||||||
|
{
|
||||||
|
auto tex = create(img.width, img.height, TextureFormat::RGBA);
|
||||||
|
tex->set_data((unsigned char*)img.pixels);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
|
}
|
|
@ -28,9 +28,35 @@ namespace Blah
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Image;
|
||||||
|
class Stream;
|
||||||
|
class Texture;
|
||||||
|
typedef std::shared_ptr<Texture> TextureRef;
|
||||||
|
|
||||||
class Texture
|
class Texture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Creates a new Texture.
|
||||||
|
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||||
|
static TextureRef create(const Image& image);
|
||||||
|
|
||||||
|
// Creates a new Texture.
|
||||||
|
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||||
|
static TextureRef create(int width, int height, unsigned char* rgba);
|
||||||
|
|
||||||
|
// Creates a new Texture.
|
||||||
|
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||||
|
static TextureRef create(int width, int height, TextureFormat format);
|
||||||
|
|
||||||
|
// Creates a new Texture from a Stream.
|
||||||
|
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||||
|
static TextureRef create(Stream& stream);
|
||||||
|
|
||||||
|
// Creates a new Texture from a File.
|
||||||
|
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||||
|
static TextureRef create(const char* file);
|
||||||
|
|
||||||
virtual ~Texture() = default;
|
virtual ~Texture() = default;
|
||||||
|
|
||||||
// gets the width of the texture
|
// gets the width of the texture
|
||||||
|
@ -70,6 +96,4 @@ namespace Blah
|
||||||
// Returns true if the Texture is part of a FrameBuffer
|
// Returns true if the Texture is part of a FrameBuffer
|
||||||
virtual bool is_framebuffer() const = 0;
|
virtual bool is_framebuffer() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Texture> TextureRef;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user