mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
very WIP D3D11 support
This commit is contained in:
parent
52e362e1b2
commit
41ae0ac6d5
|
@ -103,12 +103,13 @@ add_library(blah
|
|||
private/blah/third_party/stb_truetype.h
|
||||
private/blah/internal/graphics_backend.h
|
||||
private/blah/internal/graphics_backend_gl.cpp
|
||||
private/blah/internal/graphics_backend_d3d11.cpp
|
||||
private/blah/internal/input_backend.h
|
||||
private/blah/internal/platform_backend.h
|
||||
private/blah/internal/platform_backend_sdl2.cpp
|
||||
)
|
||||
|
||||
target_include_directories(blah
|
||||
target_include_directories(blah
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public>
|
||||
PRIVATE
|
||||
|
@ -119,16 +120,27 @@ target_include_directories(blah
|
|||
set(SDL2_ENABLED true CACHE BOOL "Use SDL2 as the System implementation")
|
||||
set(SDL2_INCLUDE_DIRS "" CACHE FILEPATH "SDL2 Headers")
|
||||
set(SDL2_LIBRARIES "" CACHE FILEPATH "SDL2 Headers")
|
||||
set(OPENGL_ENABLED true CACHE BOOL "Include OpenGL graphics implementation")
|
||||
set(OPENGL_ENABLED true CACHE BOOL "Use OpenGL graphics implementation")
|
||||
set(D3D11_ENABLED false CACHE BOOL "Use D3D11 graphics implementation")
|
||||
|
||||
set(LIBS "")
|
||||
|
||||
# add OpenGL definition if we're using OpenGL
|
||||
if (OPENGL_ENABLED)
|
||||
add_compile_definitions(BLAH_USE_OPENGL)
|
||||
endif()
|
||||
|
||||
# add D3D11 definition if we're using OpenGL
|
||||
if (D3D11_ENABLED)
|
||||
add_compile_definitions(BLAH_USE_D3D11)
|
||||
set(LIBS ${LIBS} d3d11.lib dxguid.lib D3Dcompiler.lib)
|
||||
endif()
|
||||
|
||||
# Link and create SDL2 Definition if we're using SDL2
|
||||
if (SDL2_ENABLED)
|
||||
add_compile_definitions(BLAH_USE_SDL2)
|
||||
target_include_directories(blah PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
|
||||
target_link_libraries(blah PUBLIC ${SDL2_LIBRARIES})
|
||||
endif()
|
||||
set(LIBS ${LIBS} ${SDL2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(blah PUBLIC ${LIBS})
|
1255
private/blah/internal/graphics_backend_d3d11.cpp
Normal file
1255
private/blah/internal/graphics_backend_d3d11.cpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -406,7 +406,7 @@ namespace Blah
|
|||
}
|
||||
|
||||
// assign attributes
|
||||
GLuint gl_mesh_assign_attributes(GLuint buffer, GLenum buffer_type, const VertexAttribute* vertex_attributes, int vertex_attribute_count, int stride, GLint divisor)
|
||||
GLuint gl_mesh_assign_attributes(GLuint buffer, GLenum buffer_type, const VertexFormat& format, GLint divisor)
|
||||
{
|
||||
// bind
|
||||
gl.BindBuffer(buffer_type, buffer);
|
||||
|
@ -417,49 +417,83 @@ namespace Blah
|
|||
|
||||
// enable attributes
|
||||
size_t ptr = 0;
|
||||
for (int n = 0; n < vertex_attribute_count; n++)
|
||||
for (int n = 0; n < format.attributes.size(); n++)
|
||||
{
|
||||
const VertexAttribute* attrib = (vertex_attributes + n);
|
||||
auto& attribute = format.attributes[n];
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
size_t component_size = 0;
|
||||
int components = 1;
|
||||
|
||||
for (int i = 0, loc = 0; i < (int)attrib->components; i += 4, loc++)
|
||||
if (attribute.type == VertexType::Float)
|
||||
{
|
||||
int components = attrib->components - i;
|
||||
if (components > 4)
|
||||
components = 4;
|
||||
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
size_t component_size = 0;
|
||||
if (attrib->type == VertexAttributeType::Byte)
|
||||
{
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
component_size = 1;
|
||||
}
|
||||
else if (attrib->type == VertexAttributeType::Short)
|
||||
{
|
||||
type = GL_SHORT;
|
||||
component_size = 2;
|
||||
}
|
||||
else if (attrib->type == VertexAttributeType::Int)
|
||||
{
|
||||
type = GL_INT;
|
||||
component_size = 4;
|
||||
}
|
||||
else if (attrib->type == VertexAttributeType::Float)
|
||||
{
|
||||
type = GL_FLOAT;
|
||||
component_size = 4;
|
||||
}
|
||||
|
||||
uint32_t location = (uint32_t)(attrib->index + loc);
|
||||
gl.EnableVertexAttribArray(location);
|
||||
gl.VertexAttribPointer(location, components, type, attrib->normalized, stride, (void*)ptr);
|
||||
gl.VertexAttribDivisor(location, divisor);
|
||||
|
||||
ptr += components * component_size;
|
||||
type = GL_FLOAT;
|
||||
component_size = 4;
|
||||
components = 1;
|
||||
}
|
||||
else if (attribute.type == VertexType::Float2)
|
||||
{
|
||||
type = GL_FLOAT;
|
||||
component_size = 4;
|
||||
components = 2;
|
||||
}
|
||||
else if (attribute.type == VertexType::Float3)
|
||||
{
|
||||
type = GL_FLOAT;
|
||||
component_size = 4;
|
||||
components = 3;
|
||||
}
|
||||
else if (attribute.type == VertexType::Float4)
|
||||
{
|
||||
type = GL_FLOAT;
|
||||
component_size = 4;
|
||||
components = 4;
|
||||
}
|
||||
else if (attribute.type == VertexType::Byte4)
|
||||
{
|
||||
type = GL_BYTE;
|
||||
component_size = 1;
|
||||
components = 4;
|
||||
}
|
||||
else if (attribute.type == VertexType::UByte4)
|
||||
{
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
component_size = 1;
|
||||
components = 4;
|
||||
}
|
||||
else if (attribute.type == VertexType::Short2)
|
||||
{
|
||||
type = GL_SHORT;
|
||||
component_size = 2;
|
||||
components = 2;
|
||||
}
|
||||
else if (attribute.type == VertexType::UShort2)
|
||||
{
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
component_size = 2;
|
||||
components = 2;
|
||||
}
|
||||
else if (attribute.type == VertexType::Short4)
|
||||
{
|
||||
type = GL_SHORT;
|
||||
component_size = 2;
|
||||
components = 4;
|
||||
}
|
||||
else if (attribute.type == VertexType::UShort4)
|
||||
{
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
component_size = 2;
|
||||
components = 4;
|
||||
}
|
||||
|
||||
uint32_t location = (uint32_t)(attribute.index);
|
||||
gl.EnableVertexAttribArray(location);
|
||||
gl.VertexAttribPointer(location, components, type, attribute.normalized, format.stride, (void*)ptr);
|
||||
gl.VertexAttribDivisor(location, divisor);
|
||||
|
||||
ptr += components * component_size;
|
||||
}
|
||||
|
||||
return stride;
|
||||
return format.stride;
|
||||
}
|
||||
|
||||
// convert blend op enum
|
||||
|
@ -554,12 +588,6 @@ namespace Blah
|
|||
m_gl_format = GL_RG;
|
||||
m_gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (format == TextureFormat::RGB)
|
||||
{
|
||||
m_gl_internal_format = GL_RGB;
|
||||
m_gl_format = GL_RGB;
|
||||
m_gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (format == TextureFormat::RGBA)
|
||||
{
|
||||
m_gl_internal_format = GL_RGBA;
|
||||
|
@ -779,7 +807,6 @@ namespace Blah
|
|||
{
|
||||
m_id = 0;
|
||||
|
||||
// vertex shader
|
||||
if (data->vertex == nullptr)
|
||||
{
|
||||
Log::error("Vertex Shader is required");
|
||||
|
@ -819,33 +846,32 @@ namespace Blah
|
|||
|
||||
if (log_length > 0)
|
||||
{
|
||||
gl.DeleteShader(vertex_shader);
|
||||
gl.DeleteShader(fragment_shader);
|
||||
Log::error(log);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create actual shader program
|
||||
GLuint id = gl.CreateProgram();
|
||||
gl.AttachShader(id, vertex_shader);
|
||||
gl.AttachShader(id, fragment_shader);
|
||||
gl.LinkProgram(id);
|
||||
gl.GetProgramInfoLog(id, 1024, &log_length, log);
|
||||
gl.DetachShader(id, vertex_shader);
|
||||
gl.DetachShader(id, fragment_shader);
|
||||
gl.DeleteShader(vertex_shader);
|
||||
gl.DeleteShader(fragment_shader);
|
||||
|
||||
if (log_length > 0)
|
||||
{
|
||||
gl.DetachShader(id, vertex_shader);
|
||||
gl.DetachShader(id, fragment_shader);
|
||||
gl.DeleteShader(vertex_shader);
|
||||
gl.DeleteShader(fragment_shader);
|
||||
|
||||
Log::error(log);
|
||||
return;
|
||||
}
|
||||
|
||||
// ready to go
|
||||
m_id = id;
|
||||
|
||||
// get uniforms
|
||||
bool valid_uniforms = true;
|
||||
{
|
||||
const int max_name_length = 256;
|
||||
|
||||
|
@ -876,32 +902,48 @@ namespace Blah
|
|||
UniformInfo uniform;
|
||||
uniform.name = name;
|
||||
uniform.type = UniformType::None;
|
||||
uniform.buffer_index = 0;
|
||||
uniform.array_length = size;
|
||||
uniform_locations.push_back(gl.GetUniformLocation(id, name));
|
||||
|
||||
if (type == GL_FLOAT)
|
||||
uniform.type = UniformType::Float;
|
||||
else if (type == GL_FLOAT_VEC2)
|
||||
uniform.type = UniformType::Float2;
|
||||
else if (type == GL_FLOAT_VEC3)
|
||||
uniform.type = UniformType::Float3;
|
||||
else if (type == GL_FLOAT_VEC4)
|
||||
uniform.type = UniformType::Float4;
|
||||
else if (type == GL_FLOAT_MAT3x2)
|
||||
uniform.type = UniformType::Mat3x2;
|
||||
else if (type == GL_FLOAT_MAT4)
|
||||
uniform.type = UniformType::Mat4x4;
|
||||
else if (type == GL_SAMPLER_2D)
|
||||
if (type == GL_SAMPLER_2D)
|
||||
{
|
||||
uniform.type = UniformType::Texture;
|
||||
uniform.shader = ShaderType::Fragment;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Unsupported Uniform Type. Must be either FLOAT, MAT3x2, MAT4, or SAMPLER_2D");
|
||||
break;
|
||||
uniform.shader = (ShaderType)((int)ShaderType::Vertex | (int)ShaderType::Fragment);
|
||||
|
||||
if (type == GL_FLOAT)
|
||||
uniform.type = UniformType::Float;
|
||||
else if (type == GL_FLOAT_VEC2)
|
||||
uniform.type = UniformType::Float2;
|
||||
else if (type == GL_FLOAT_VEC3)
|
||||
uniform.type = UniformType::Float3;
|
||||
else if (type == GL_FLOAT_VEC4)
|
||||
uniform.type = UniformType::Float4;
|
||||
else if (type == GL_FLOAT_MAT3x2)
|
||||
uniform.type = UniformType::Mat3x2;
|
||||
else if (type == GL_FLOAT_MAT4)
|
||||
uniform.type = UniformType::Mat4x4;
|
||||
else
|
||||
{
|
||||
valid_uniforms = false;
|
||||
Log::error("Unsupported Uniform Type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_uniforms.push_back(uniform);
|
||||
}
|
||||
}
|
||||
|
||||
// assign ID if the uniforms were valid
|
||||
if (!valid_uniforms)
|
||||
gl.DeleteProgram(id);
|
||||
else
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
~OpenGL_Shader()
|
||||
|
@ -943,6 +985,8 @@ namespace Blah
|
|||
uint8_t m_instance_attribs_enabled;
|
||||
Vector<GLuint> m_vertex_attribs;
|
||||
Vector<GLuint> m_instance_attribs;
|
||||
GLenum m_index_format;
|
||||
int m_index_size;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -981,31 +1025,17 @@ namespace Blah
|
|||
return m_id;
|
||||
}
|
||||
|
||||
virtual void vertex_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override
|
||||
GLenum gl_index_format() const
|
||||
{
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
if (m_vertex_buffer == 0)
|
||||
gl.GenBuffers(1, &(m_vertex_buffer));
|
||||
|
||||
m_vertex_size = gl_mesh_assign_attributes(m_vertex_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 0);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
return m_index_format;
|
||||
}
|
||||
|
||||
virtual void instance_format_internal(const VertexAttribute* attributes, int attribute_count, int stride = -1) override
|
||||
int gl_index_size() const
|
||||
{
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
if (m_instance_buffer == 0)
|
||||
gl.GenBuffers(1, &(m_instance_buffer));
|
||||
|
||||
m_instance_size = gl_mesh_assign_attributes(m_instance_buffer, GL_ARRAY_BUFFER, attributes, attribute_count, stride, 1);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
return m_index_size;
|
||||
}
|
||||
|
||||
virtual void index_data(const void* indices, int64_t count) override
|
||||
virtual void index_data(IndexFormat format, const void* indices, int64_t count) override
|
||||
{
|
||||
m_index_count = count;
|
||||
|
||||
|
@ -1014,48 +1044,64 @@ namespace Blah
|
|||
if (m_index_buffer == 0)
|
||||
gl.GenBuffers(1, &(m_index_buffer));
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case IndexFormat::UInt16:
|
||||
m_index_format = GL_UNSIGNED_SHORT;
|
||||
m_index_size = 2;
|
||||
break;
|
||||
case IndexFormat::UInt32:
|
||||
m_index_format = GL_UNSIGNED_INT;
|
||||
m_index_size = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
|
||||
gl.BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_DYNAMIC_DRAW);
|
||||
gl.BufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_size * count, indices, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
}
|
||||
|
||||
virtual void vertex_data(const void* vertices, int64_t count) override
|
||||
virtual void vertex_data(const VertexFormat& format, const void* vertices, int64_t count) override
|
||||
{
|
||||
if (m_vertex_buffer == 0 || m_vertex_size <= 0)
|
||||
{
|
||||
Log::error("You must assign a Vertex Format before setting Vertex Data");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex_count = count;
|
||||
m_vertex_count = count;
|
||||
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
gl.BindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||
gl.BufferData(GL_ARRAY_BUFFER, m_vertex_size * count, vertices, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
// Create Buffer if it doesn't exist yet
|
||||
if (m_vertex_buffer == 0)
|
||||
gl.GenBuffers(1, &(m_vertex_buffer));
|
||||
|
||||
// TODO:
|
||||
// Cache this
|
||||
m_vertex_size = gl_mesh_assign_attributes(m_vertex_buffer, GL_ARRAY_BUFFER, format, 0);
|
||||
|
||||
// Upload Buffer
|
||||
gl.BindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||
gl.BufferData(GL_ARRAY_BUFFER, m_vertex_size * count, vertices, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
}
|
||||
|
||||
virtual void instance_data(const void* instances, int64_t count) override
|
||||
virtual void instance_data(const VertexFormat& format, const void* instances, int64_t count) override
|
||||
{
|
||||
if (m_instance_buffer == 0 || m_instance_size <= 0)
|
||||
{
|
||||
Log::error("You must assign an Instance Format before setting Instance Data");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_instance_count = count;
|
||||
m_instance_count = count;
|
||||
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
gl.BindBuffer(GL_ARRAY_BUFFER, m_instance_buffer);
|
||||
gl.BufferData(GL_ARRAY_BUFFER, m_instance_size * count, instances, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
gl.BindVertexArray(m_id);
|
||||
{
|
||||
// Create Buffer if it doesn't exist yet
|
||||
if (m_instance_buffer == 0)
|
||||
gl.GenBuffers(1, &(m_instance_buffer));
|
||||
|
||||
// TODO:
|
||||
// Cache this
|
||||
m_instance_size = gl_mesh_assign_attributes(m_instance_buffer, GL_ARRAY_BUFFER, format, 1);
|
||||
|
||||
// Upload Buffer
|
||||
gl.BindBuffer(GL_ARRAY_BUFFER, m_instance_buffer);
|
||||
gl.BufferData(GL_ARRAY_BUFFER, m_instance_size * count, instances, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
gl.BindVertexArray(0);
|
||||
}
|
||||
|
||||
virtual int64_t index_count() const override
|
||||
|
@ -1222,6 +1268,7 @@ namespace Blah
|
|||
|
||||
// Use the Shader
|
||||
// TODO: I don't love how material values are assigned or set here
|
||||
// TODO: this should be cached?
|
||||
{
|
||||
gl.UseProgram(shader->gl_id());
|
||||
|
||||
|
@ -1230,6 +1277,8 @@ namespace Blah
|
|||
GLint texture_ids[64];
|
||||
|
||||
auto& uniforms = shader->uniforms();
|
||||
auto data = pass.material->data();
|
||||
|
||||
for (int i = 0; i < uniforms.size(); i++)
|
||||
{
|
||||
auto location = shader->uniform_locations[i];
|
||||
|
@ -1258,36 +1307,44 @@ namespace Blah
|
|||
}
|
||||
|
||||
gl.Uniform1iv(location, (GLint)uniform.array_length, &texture_ids[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Float
|
||||
else if (uniform.type == UniformType::Float)
|
||||
if (uniform.type == UniformType::Float)
|
||||
{
|
||||
gl.Uniform1fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.Uniform1fv(location, (GLint)uniform.array_length, data);
|
||||
data += uniform.array_length;
|
||||
}
|
||||
// Float2
|
||||
else if (uniform.type == UniformType::Float2)
|
||||
{
|
||||
gl.Uniform2fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.Uniform2fv(location, (GLint)uniform.array_length, data);
|
||||
data += 2 * uniform.array_length;
|
||||
}
|
||||
// Float3
|
||||
else if (uniform.type == UniformType::Float3)
|
||||
{
|
||||
gl.Uniform3fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.Uniform3fv(location, (GLint)uniform.array_length, data);
|
||||
data += 3 * uniform.array_length;
|
||||
}
|
||||
// Float4
|
||||
else if (uniform.type == UniformType::Float4)
|
||||
{
|
||||
gl.Uniform4fv(location, (GLint)uniform.array_length, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.Uniform4fv(location, (GLint)uniform.array_length, data);
|
||||
data += 4 * uniform.array_length;
|
||||
}
|
||||
// Matrix3x2
|
||||
else if (uniform.type == UniformType::Mat3x2)
|
||||
{
|
||||
gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.UniformMatrix3x2fv(location, (GLint)uniform.array_length, 0, data);
|
||||
data += 6 * uniform.array_length;
|
||||
}
|
||||
// Matrix4x4
|
||||
else if (uniform.type == UniformType::Mat4x4)
|
||||
{
|
||||
gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, (const GLfloat*)pass.material->get_value(i));
|
||||
gl.UniformMatrix4fv(location, (GLint)uniform.array_length, 0, data);
|
||||
data += 16 * uniform.array_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1416,13 +1473,16 @@ namespace Blah
|
|||
{
|
||||
gl.BindVertexArray(mesh->gl_id());
|
||||
|
||||
GLenum index_format = mesh->gl_index_format();
|
||||
int index_size = mesh->gl_index_size();
|
||||
|
||||
if (pass.instance_count > 0)
|
||||
{
|
||||
gl.DrawElementsInstanced(
|
||||
GL_TRIANGLES,
|
||||
(GLint)(pass.index_count),
|
||||
GL_UNSIGNED_INT,
|
||||
(void*)(sizeof(int) * pass.index_start),
|
||||
index_format,
|
||||
(void*)(index_size* pass.index_start),
|
||||
(GLint)pass.instance_count);
|
||||
}
|
||||
else
|
||||
|
@ -1430,8 +1490,8 @@ namespace Blah
|
|||
gl.DrawElements(
|
||||
GL_TRIANGLES,
|
||||
(GLint)(pass.index_count),
|
||||
GL_UNSIGNED_INT,
|
||||
(void*)(sizeof(int) * pass.index_start));
|
||||
index_format,
|
||||
(void*)(index_size * pass.index_start));
|
||||
}
|
||||
|
||||
gl.BindVertexArray(0);
|
||||
|
|
|
@ -113,5 +113,8 @@ namespace Blah
|
|||
void* gl_context_create();
|
||||
void gl_context_make_current(void* context);
|
||||
void gl_context_destroy(void* context);
|
||||
|
||||
// D3D11 Methods
|
||||
void* d3d11_get_hwnd();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <SDL.h>
|
||||
#include <SDL_vulkan.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#if _WIN32
|
||||
// on Windows we're using the C++ <filesystem> API for now
|
||||
|
@ -75,7 +76,7 @@ bool PlatformBackend::init(const Config* config)
|
|||
|
||||
int flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
// GL Attributes
|
||||
// enable OpenGL
|
||||
if (App::renderer() == Renderer::OpenGL)
|
||||
{
|
||||
flags |= SDL_WINDOW_OPENGL;
|
||||
|
@ -93,6 +94,11 @@ bool PlatformBackend::init(const Config* config)
|
|||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||||
}
|
||||
// enable DirectX
|
||||
else if (App::renderer() == Renderer::D3D11)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// create the window
|
||||
window = SDL_CreateWindow(config->name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config->width, config->height, flags);
|
||||
|
@ -643,4 +649,12 @@ void PlatformBackend::gl_context_destroy(void* context)
|
|||
SDL_GL_DeleteContext(context);
|
||||
}
|
||||
|
||||
void* PlatformBackend::d3d11_get_hwnd()
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
SDL_GetWindowWMInfo(window, &info);
|
||||
return info.info.win.window;
|
||||
}
|
||||
|
||||
#endif // BLAH_USE_SDL2
|
||||
|
|
|
@ -15,8 +15,10 @@ namespace Blah
|
|||
int m_count;
|
||||
|
||||
public:
|
||||
static inline constexpr size_t MaxCapacity = Capacity;
|
||||
|
||||
StackVector();
|
||||
StackVector(const std::initializer_list<T>& init);
|
||||
StackVector(const StackVector& src);
|
||||
StackVector(StackVector&& src) noexcept;
|
||||
~StackVector();
|
||||
|
@ -59,6 +61,14 @@ namespace Blah
|
|||
m_count = 0;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector(const std::initializer_list<T>& init)
|
||||
{
|
||||
m_count = 0;
|
||||
for (auto& it : init)
|
||||
push_back(it);
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector(const StackVector& src)
|
||||
{
|
||||
|
|
|
@ -8,52 +8,121 @@
|
|||
#include <blah/app.h>
|
||||
|
||||
using namespace Blah;
|
||||
namespace
|
||||
{
|
||||
|
||||
// TODO:
|
||||
// This shader needs to be graphics API agnostic
|
||||
// TODO:
|
||||
// This shader needs to be graphics API agnostic
|
||||
|
||||
const ShaderData data = {
|
||||
// vertex shader
|
||||
"#version 330\n"
|
||||
"uniform mat4 u_matrix;\n"
|
||||
"layout(location=0) in vec2 a_position;\n"
|
||||
"layout(location=1) in vec2 a_tex;\n"
|
||||
"layout(location=2) in vec4 a_color;\n"
|
||||
"layout(location=3) in vec3 a_type;\n"
|
||||
"out vec2 v_tex;\n"
|
||||
"out vec4 v_col;\n"
|
||||
"out vec3 v_type;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = u_matrix * vec4(a_position.xy, 0, 1);\n"
|
||||
" v_tex = a_tex;\n"
|
||||
" v_col = a_color;\n"
|
||||
" v_type = a_type;\n"
|
||||
"}",
|
||||
#ifdef BLAH_USE_OPENGL
|
||||
|
||||
// fragment shader
|
||||
"#version 330\n"
|
||||
"uniform sampler2D u_texture;\n"
|
||||
"in vec2 v_tex;\n"
|
||||
"in vec4 v_col;\n"
|
||||
"in vec3 v_type;\n"
|
||||
"out vec4 o_color;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" vec4 color = texture(u_texture, v_tex);\n"
|
||||
" o_color = \n"
|
||||
" v_type.x * color * v_col + \n"
|
||||
" v_type.y * color.a * v_col + \n"
|
||||
" v_type.z * v_col;\n"
|
||||
"}"
|
||||
};
|
||||
const ShaderData shader_data = {
|
||||
// vertex shader
|
||||
"#version 330\n"
|
||||
"uniform mat4 u_matrix;\n"
|
||||
"layout(location=0) in vec2 a_position;\n"
|
||||
"layout(location=1) in vec2 a_tex;\n"
|
||||
"layout(location=2) in vec4 a_color;\n"
|
||||
"layout(location=3) in vec4 a_type;\n"
|
||||
"out vec2 v_tex;\n"
|
||||
"out vec4 v_col;\n"
|
||||
"out vec4 v_type;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = u_matrix * vec4(a_position.xy, 0, 1);\n"
|
||||
" v_tex = a_tex;\n"
|
||||
" v_col = a_color;\n"
|
||||
" v_type = a_type;\n"
|
||||
"}",
|
||||
|
||||
const VertexAttribute attributes[4] = {
|
||||
{ 0, VertexSemantics::Position, VertexAttributeType::Float, 2, false },
|
||||
{ 1, VertexSemantics::Texcoord0, VertexAttributeType::Float, 2, false },
|
||||
{ 2, VertexSemantics::Color0, VertexAttributeType::Byte, 4, true },
|
||||
{ 3, VertexSemantics::Texcoord1, VertexAttributeType::Byte, 3, true },
|
||||
};
|
||||
// fragment shader
|
||||
"#version 330\n"
|
||||
"uniform sampler2D u_texture;\n"
|
||||
"in vec2 v_tex;\n"
|
||||
"in vec4 v_col;\n"
|
||||
"in vec4 v_type;\n"
|
||||
"out vec4 o_color;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" vec4 color = texture(u_texture, v_tex);\n"
|
||||
" o_color = \n"
|
||||
" v_type.x * color * v_col + \n"
|
||||
" v_type.y * color.a * v_col + \n"
|
||||
" v_type.z * v_col;\n"
|
||||
"}"
|
||||
};
|
||||
|
||||
#elif BLAH_USE_D3D11
|
||||
|
||||
const char* d3d11_shader = ""
|
||||
"cbuffer constants : register(b0)\n"
|
||||
"{\n"
|
||||
" row_major float4x4 u_matrix;\n"
|
||||
"}\n"
|
||||
|
||||
"struct vs_in\n"
|
||||
"{\n"
|
||||
" float2 position : POS;\n"
|
||||
" float2 texcoord : TEX;\n"
|
||||
" float4 color : COL;\n"
|
||||
" float4 mask : MASK;\n"
|
||||
"};\n"
|
||||
|
||||
"struct vs_out\n"
|
||||
"{\n"
|
||||
" float4 position : SV_POSITION;\n"
|
||||
" float2 texcoord : TEX;\n"
|
||||
" float4 color : COL;\n"
|
||||
" float4 mask : MASK;\n"
|
||||
"};\n"
|
||||
|
||||
"Texture2D u_texture : register(t0);\n"
|
||||
"SamplerState u_sampler : register(s0);\n"
|
||||
|
||||
"vs_out vs_main(vs_in input)\n"
|
||||
"{\n"
|
||||
" vs_out output;\n"
|
||||
|
||||
" output.position = mul(float4(input.position, 0.0f, 1.0f), u_matrix);\n"
|
||||
" output.texcoord = input.texcoord;\n"
|
||||
" output.color = input.color;\n"
|
||||
" output.mask = input.mask;\n"
|
||||
|
||||
" return output;\n"
|
||||
"}\n"
|
||||
|
||||
"float4 ps_main(vs_out input) : SV_TARGET\n"
|
||||
"{\n"
|
||||
" float4 color = u_texture.Sample(u_sampler, input.texcoord);\n"
|
||||
" return\n"
|
||||
" input.mask.x * color * input.color + \n"
|
||||
" input.mask.y * color.a * input.color + \n"
|
||||
" input.mask.z * input.color;\n"
|
||||
"}\n";
|
||||
|
||||
const ShaderData shader_data = {
|
||||
d3d11_shader,
|
||||
d3d11_shader,
|
||||
{
|
||||
{ "POS", 0 },
|
||||
{ "TEX", 0 },
|
||||
{ "COL", 0 },
|
||||
{ "MASK", 0 },
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
const ShaderData shader_data;
|
||||
#endif
|
||||
|
||||
const VertexFormat format = VertexFormat(
|
||||
{
|
||||
{ 0, VertexType::Float2, false },
|
||||
{ 1, VertexType::Float2, false },
|
||||
{ 2, VertexType::UByte4, true },
|
||||
{ 3, VertexType::UByte4, true },
|
||||
});
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -84,13 +153,13 @@ namespace
|
|||
#define PUSH_QUAD(px0, py0, px1, py1, px2, py2, px3, py3, tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3, col0, col1, col2, col3, mult, fill, wash) \
|
||||
{ \
|
||||
m_batch.elements += 2; \
|
||||
int* _i = m_indices.expand(6); \
|
||||
*_i++ = (int)m_vertices.size() + 0; \
|
||||
*_i++ = (int)m_vertices.size() + 1; \
|
||||
*_i++ = (int)m_vertices.size() + 2; \
|
||||
*_i++ = (int)m_vertices.size() + 0; \
|
||||
*_i++ = (int)m_vertices.size() + 2; \
|
||||
*_i++ = (int)m_vertices.size() + 3; \
|
||||
auto _i = m_indices.expand(6); \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 0; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 1; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 2; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 0; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 2; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 3; \
|
||||
Vertex* _v = m_vertices.expand(4); \
|
||||
MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
|
||||
MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
|
||||
|
@ -101,10 +170,10 @@ namespace
|
|||
#define PUSH_TRIANGLE(px0, py0, px1, py1, px2, py2, tx0, ty0, tx1, ty1, tx2, ty2, col0, col1, col2, mult, fill, wash) \
|
||||
{ \
|
||||
m_batch.elements += 1; \
|
||||
int* _i = m_indices.expand(3); \
|
||||
*_i++ = (int)m_vertices.size() + 0; \
|
||||
*_i++ = (int)m_vertices.size() + 1; \
|
||||
*_i++ = (int)m_vertices.size() + 2; \
|
||||
auto* _i = m_indices.expand(3); \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 0; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 1; \
|
||||
*_i++ = (uint32_t)m_vertices.size() + 2; \
|
||||
Vertex* _v = m_vertices.expand(3); \
|
||||
MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
|
||||
MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
|
||||
|
@ -126,8 +195,6 @@ ShaderRef Batch::m_default_shader;
|
|||
Batch::Batch()
|
||||
{
|
||||
matrix_uniform = "u_matrix";
|
||||
texture_uniform = "u_texture";
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
|
@ -292,21 +359,18 @@ void Batch::render(const FrameBufferRef& target, const Mat4x4& matrix)
|
|||
// define defaults
|
||||
{
|
||||
if (!m_mesh)
|
||||
{
|
||||
m_mesh = Mesh::create();
|
||||
m_mesh->vertex_format(attributes, 4, sizeof(Vertex));
|
||||
}
|
||||
|
||||
if (!m_default_shader)
|
||||
m_default_shader = Shader::create(&data);
|
||||
m_default_shader = Shader::create(&shader_data);
|
||||
|
||||
if (!m_default_material)
|
||||
m_default_material = Material::create(m_default_shader);
|
||||
}
|
||||
|
||||
// upload data
|
||||
m_mesh->index_data(m_indices.data(), m_indices.size());
|
||||
m_mesh->vertex_data(m_vertices.data(), m_vertices.size());
|
||||
m_mesh->index_data(IndexFormat::UInt32, m_indices.data(), m_indices.size());
|
||||
m_mesh->vertex_data(format, m_vertices.data(), m_vertices.size());
|
||||
|
||||
RenderPass pass;
|
||||
pass.target = target;
|
||||
|
@ -330,7 +394,7 @@ void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4
|
|||
if (!pass.material)
|
||||
pass.material = m_default_material;
|
||||
|
||||
pass.material->set_texture(texture_uniform, b.texture, 0);
|
||||
pass.material->set_texture(0, b.texture, 0);
|
||||
pass.material->set_value(matrix_uniform, &matrix.m11, 16);
|
||||
|
||||
pass.blend = b.blend;
|
||||
|
|
|
@ -45,9 +45,6 @@ namespace Blah
|
|||
// The name of the Matrix Uniform in the Shader
|
||||
const char* matrix_uniform;
|
||||
|
||||
// The name of the Texture Uniform in the Shader
|
||||
const char* texture_uniform;
|
||||
|
||||
Batch();
|
||||
Batch(const Batch& other) = delete;
|
||||
Batch& operator=(const Batch& other) = delete;
|
||||
|
@ -186,6 +183,7 @@ namespace Blah
|
|||
uint8_t mult;
|
||||
uint8_t wash;
|
||||
uint8_t fill;
|
||||
uint8_t pad;
|
||||
};
|
||||
|
||||
struct DrawBatch
|
||||
|
@ -217,7 +215,7 @@ namespace Blah
|
|||
uint8_t m_tex_wash;
|
||||
DrawBatch m_batch;
|
||||
Vector<Vertex> m_vertices;
|
||||
Vector<int> m_indices;
|
||||
Vector<uint32_t> m_indices;
|
||||
Vector<Mat3x2> m_matrix_stack;
|
||||
Vector<Rect> m_scissor_stack;
|
||||
Vector<BlendMode> m_blend_stack;
|
||||
|
|
|
@ -42,7 +42,6 @@ Material::Material(const ShaderRef& shader)
|
|||
m_shader = shader;
|
||||
|
||||
auto& uniforms = shader->uniforms();
|
||||
Vector<int> float_offsets;
|
||||
int float_size = 0;
|
||||
|
||||
for (auto& uniform : uniforms)
|
||||
|
@ -57,13 +56,10 @@ Material::Material(const ShaderRef& shader)
|
|||
continue;
|
||||
}
|
||||
|
||||
float_offsets.push_back(float_size);
|
||||
float_size += calc_uniform_size(uniform);
|
||||
}
|
||||
|
||||
m_data.expand(float_size);
|
||||
for (auto& it : float_offsets)
|
||||
m_floats.push_back(m_data.begin() + it);
|
||||
}
|
||||
|
||||
const ShaderRef Material::shader() const
|
||||
|
@ -75,29 +71,50 @@ void Material::set_texture(const char* name, const TextureRef& texture, int inde
|
|||
{
|
||||
BLAH_ASSERT(m_shader, "Material Shader is invalid");
|
||||
|
||||
if (m_textures.size() > 0)
|
||||
int offset = 0;
|
||||
for (auto& uniform : m_shader->uniforms())
|
||||
{
|
||||
int offset = 0;
|
||||
for (auto& uniform : m_shader->uniforms())
|
||||
if (uniform.type != UniformType::Texture)
|
||||
continue;
|
||||
|
||||
if (strcmp(uniform.name, name) == 0)
|
||||
{
|
||||
if (uniform.type != UniformType::Texture)
|
||||
continue;
|
||||
|
||||
if (strcmp(uniform.name, name) == 0)
|
||||
{
|
||||
m_textures[offset + index] = texture;
|
||||
return;
|
||||
}
|
||||
|
||||
offset += uniform.array_length;
|
||||
if (offset + index >= m_textures.size())
|
||||
break;
|
||||
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::Texture)
|
||||
{
|
||||
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");
|
||||
|
@ -124,14 +141,19 @@ TextureRef Material::get_texture(int slot, int index) const
|
|||
{
|
||||
BLAH_ASSERT(m_shader, "Material Shader is invalid");
|
||||
|
||||
int offset = 0;
|
||||
int s = 0;
|
||||
int offset = 0;
|
||||
for (auto& uniform : m_shader->uniforms())
|
||||
{
|
||||
if (uniform.type == UniformType::Texture)
|
||||
{
|
||||
if (s == slot)
|
||||
{
|
||||
if (index > uniform.array_length)
|
||||
break;
|
||||
|
||||
return m_textures[offset + index];
|
||||
}
|
||||
|
||||
offset += uniform.array_length;
|
||||
if (offset + index >= m_textures.size())
|
||||
|
@ -151,6 +173,7 @@ void Material::set_value(const char* name, const float* value, int64_t length)
|
|||
BLAH_ASSERT(length >= 0, "Length must be >= 0");
|
||||
|
||||
int index = 0;
|
||||
int offset = 0;
|
||||
for (auto& uniform : m_shader->uniforms())
|
||||
{
|
||||
if (uniform.type == UniformType::Texture || uniform.type == UniformType::None)
|
||||
|
@ -165,10 +188,11 @@ void Material::set_value(const char* name, const float* value, int64_t length)
|
|||
length = max;
|
||||
}
|
||||
|
||||
memcpy(m_floats[index], value, sizeof(float) * length);
|
||||
memcpy(m_data.begin() + offset, value, sizeof(float) * length);
|
||||
return;
|
||||
}
|
||||
|
||||
offset += calc_uniform_size(uniform);
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -180,6 +204,7 @@ 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::Texture || uniform.type == UniformType::None)
|
||||
|
@ -189,10 +214,11 @@ const float* Material::get_value(const char* name, int64_t* length) const
|
|||
{
|
||||
if (length != nullptr)
|
||||
*length = calc_uniform_size(uniform);
|
||||
return m_floats[index];
|
||||
return m_data.begin() + offset;
|
||||
}
|
||||
|
||||
index++;
|
||||
offset += calc_uniform_size(uniform);
|
||||
}
|
||||
|
||||
*length = 0;
|
||||
|
@ -200,29 +226,12 @@ const float* Material::get_value(const char* name, int64_t* length) const
|
|||
Log::warn("No Uniform '%s' exists", name);
|
||||
}
|
||||
|
||||
const float* Material::get_value(int slot, int64_t* length) const
|
||||
const Vector<TextureRef>& Material::textures() const
|
||||
{
|
||||
BLAH_ASSERT(m_shader, "Material Shader is invalid");
|
||||
return m_textures;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
int s = 0;
|
||||
for (auto& uniform : m_shader->uniforms())
|
||||
{
|
||||
if (uniform.type != UniformType::Texture && uniform.type != UniformType::None)
|
||||
{
|
||||
if (index == slot)
|
||||
{
|
||||
if (length != nullptr)
|
||||
*length = calc_uniform_size(uniform);
|
||||
return m_floats[index];
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
Log::warn("No Uniform [%i] exists", slot);
|
||||
*length = 0;
|
||||
return nullptr;
|
||||
}
|
||||
const float* Material::data() const
|
||||
{
|
||||
return m_data.begin();
|
||||
}
|
||||
|
|
|
@ -31,38 +31,33 @@ namespace Blah
|
|||
// Returns the Shader assigned to the Material.
|
||||
const ShaderRef shader() const;
|
||||
|
||||
// Sets the texture. If the index is out of bounds, the Material is not valid, the Uniform
|
||||
// is not a Texture Uniform, or the Uniform does not exist, this will do nothing.
|
||||
void set_texture(const char* name, const TextureRef& texture, int index = 0);
|
||||
// Sets the texture
|
||||
void set_texture(const char* name, const TextureRef& texture, int array_index = 0);
|
||||
|
||||
// Gets the texture.
|
||||
// If the Uniform does not exist, or the index is out of bounds, this will return
|
||||
// an invalid Texture reference.
|
||||
TextureRef get_texture(const char* name, int index = 0) const;
|
||||
// Sets the texture
|
||||
void set_texture(int slot, const TextureRef& texture, int array_index = 0);
|
||||
|
||||
// Gets the texture from the given slot.
|
||||
// If the slot is not a Texture Uniform, or the index is out of bounds, this will return
|
||||
// an invalid Texture reference.
|
||||
TextureRef get_texture(int slot, int index = 0) const;
|
||||
// Gets the texture, or an empty reference if invalid
|
||||
TextureRef get_texture(const char* name, int array_index = 0) const;
|
||||
|
||||
// Sets the value. Length is the total amount of values to set. For example, if the Uniform type
|
||||
// is a float2, and there are 4 elements, the maximum length should be 8.
|
||||
// Gets the texture, or an empty reference if invalid
|
||||
TextureRef get_texture(int slot, int array_index = 0) const;
|
||||
|
||||
// Sets the value. `length` is the total number of floats to set
|
||||
void set_value(const char* name, const float* value, int64_t length);
|
||||
|
||||
// Gets a pointer to the values of the given Uniform, or nullptr if it doesn't exist.
|
||||
// Length is the total amount of values. For example, if the Uniform type
|
||||
// is a float2, and there are 4 elements, the length should be 8.
|
||||
const float* get_value(const char* name, int64_t* length = nullptr) const;
|
||||
|
||||
// Gets a pointer to the values of the given Uniform, or nullptr if it doesn't exist.
|
||||
// Length is the total amount of values. For example, if the Uniform type
|
||||
// is a float2, and there are 4 elements, the length should be 8.
|
||||
const float* get_value(int slot, int64_t* length = nullptr) const;
|
||||
// Returns the internal Texture buffer
|
||||
const Vector<TextureRef>& textures() const;
|
||||
|
||||
// Returns the interal float buffer of all the values
|
||||
const float* data() const;
|
||||
|
||||
private:
|
||||
ShaderRef m_shader;
|
||||
Vector<TextureRef> m_textures;
|
||||
Vector<float*> m_floats;
|
||||
Vector<float> m_data;
|
||||
};
|
||||
}
|
|
@ -3,55 +3,38 @@
|
|||
|
||||
using namespace Blah;
|
||||
|
||||
|
||||
MeshRef Mesh::create()
|
||||
{
|
||||
return GraphicsBackend::create_mesh();
|
||||
}
|
||||
|
||||
void Mesh::vertex_format(const VertexAttribute* attributes, int attribute_count, int stride)
|
||||
VertexFormat::VertexFormat(std::initializer_list<VertexAttribute> attributes, int stride)
|
||||
{
|
||||
if (stride < 0)
|
||||
for (auto& it : attributes)
|
||||
this->attributes.push_back(it);
|
||||
|
||||
if (stride <= 0)
|
||||
{
|
||||
stride = 0;
|
||||
|
||||
for (int n = 0; n < attribute_count; n++)
|
||||
for (auto& it : attributes)
|
||||
{
|
||||
const VertexAttribute* attrib = (attributes + n);
|
||||
|
||||
if (attrib->type == VertexAttributeType::Byte)
|
||||
stride += attrib->components * 1;
|
||||
else if (attrib->type == VertexAttributeType::Short)
|
||||
stride += attrib->components * 2;
|
||||
else if (attrib->type == VertexAttributeType::Int)
|
||||
stride += attrib->components * 4;
|
||||
else if (attrib->type == VertexAttributeType::Float)
|
||||
stride += attrib->components * 4;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vertex_format_internal(attributes, attribute_count, stride);
|
||||
}
|
||||
|
||||
void Mesh::instance_format(const VertexAttribute* attributes, int attribute_count, int stride)
|
||||
{
|
||||
if (stride < 0)
|
||||
{
|
||||
stride = 0;
|
||||
|
||||
for (int n = 0; n < attribute_count; n++)
|
||||
{
|
||||
const VertexAttribute* attrib = (attributes + n);
|
||||
|
||||
if (attrib->type == VertexAttributeType::Byte)
|
||||
stride += attrib->components * 1;
|
||||
else if (attrib->type == VertexAttributeType::Short)
|
||||
stride += attrib->components * 2;
|
||||
else if (attrib->type == VertexAttributeType::Int)
|
||||
stride += attrib->components * 4;
|
||||
else if (attrib->type == VertexAttributeType::Float)
|
||||
stride += attrib->components * 4;
|
||||
}
|
||||
}
|
||||
|
||||
instance_format_internal(attributes, attribute_count, stride);
|
||||
}
|
||||
this->stride = stride;
|
||||
}
|
|
@ -1,47 +1,53 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <blah/containers/stackvector.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class VertexSemantics
|
||||
enum class VertexType
|
||||
{
|
||||
None,
|
||||
Position,
|
||||
Normal,
|
||||
Bitangent,
|
||||
Color0,
|
||||
Color1,
|
||||
Color2,
|
||||
Color3,
|
||||
Indices,
|
||||
Weight,
|
||||
Texcoord0,
|
||||
Texcoord1,
|
||||
Texcoord2,
|
||||
Texcoord3,
|
||||
Texcoord4,
|
||||
Texcoord5,
|
||||
Texcoord6,
|
||||
Texcoord7
|
||||
};
|
||||
|
||||
enum class VertexAttributeType
|
||||
{
|
||||
None,
|
||||
Byte,
|
||||
Short,
|
||||
Int,
|
||||
Float
|
||||
Float,
|
||||
Float2,
|
||||
Float3,
|
||||
Float4,
|
||||
Byte4,
|
||||
UByte4,
|
||||
Short2,
|
||||
UShort2,
|
||||
Short4,
|
||||
UShort4
|
||||
};
|
||||
|
||||
struct VertexAttribute
|
||||
{
|
||||
int index;
|
||||
VertexSemantics semantics;
|
||||
VertexAttributeType type;
|
||||
int components;
|
||||
bool normalized;
|
||||
// Location / Attribute Index
|
||||
int index = 0;
|
||||
|
||||
// Vertex Type
|
||||
VertexType type = VertexType::None;
|
||||
|
||||
// Whether the Vertex should be normalized (doesn't apply to Floats)
|
||||
bool normalized = false;
|
||||
};
|
||||
|
||||
struct VertexFormat
|
||||
{
|
||||
// List of Attributes
|
||||
StackVector<VertexAttribute, 16> attributes;
|
||||
|
||||
// Total size in bytes of each Vertex element
|
||||
int stride = 0;
|
||||
|
||||
VertexFormat() = default;
|
||||
VertexFormat(std::initializer_list<VertexAttribute> attributes, int stride = 0);
|
||||
};
|
||||
|
||||
enum class IndexFormat
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
};
|
||||
|
||||
class Mesh;
|
||||
|
@ -66,22 +72,14 @@ namespace Blah
|
|||
// If the Mesh creation fails, it will return an invalid Mesh.
|
||||
static MeshRef create();
|
||||
|
||||
// Sets the Vertex Format of the Mesh
|
||||
void vertex_format(const VertexAttribute* attributes, int attribute_count, int stride = -1);
|
||||
|
||||
// Sets the Instance Format of the Mesh
|
||||
void instance_format(const VertexAttribute* attributes, int attribute_count, int stride = -1);
|
||||
|
||||
// Uploads the given index buffer to the Mesh
|
||||
virtual void index_data(const void* indices, int64_t count) = 0;
|
||||
virtual void index_data(IndexFormat format, const void* indices, int64_t count) = 0;
|
||||
|
||||
// Uploads the given vertex buffer to the Mesh
|
||||
// Note you must call vertex_format at least once before uploading vertices.
|
||||
virtual void vertex_data(const void* vertices, int64_t count) = 0;
|
||||
virtual void vertex_data(const VertexFormat& format, const void* vertices, int64_t count) = 0;
|
||||
|
||||
// Uploads the given instance buffer to the Mesh
|
||||
// Note you must call instance_format at least once before uploading instances.
|
||||
virtual void instance_data(const void* instances, int64_t count) = 0;
|
||||
virtual void instance_data(const VertexFormat& format, const void* instances, int64_t count) = 0;
|
||||
|
||||
// Gets the index count of the Mesh
|
||||
virtual int64_t index_count() const = 0;
|
||||
|
@ -91,9 +89,5 @@ namespace Blah
|
|||
|
||||
// Gets the instance count of the Mesh
|
||||
virtual int64_t instance_count() const = 0;
|
||||
|
||||
protected:
|
||||
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;
|
||||
};
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace Blah
|
||||
{
|
||||
// Supported Uniform Types
|
||||
enum class UniformType
|
||||
{
|
||||
None,
|
||||
|
@ -17,17 +18,54 @@ namespace Blah
|
|||
Texture
|
||||
};
|
||||
|
||||
// Supported Shader Types
|
||||
enum class ShaderType
|
||||
{
|
||||
None = 0,
|
||||
Vertex = 1 << 0,
|
||||
Fragment = 1 << 1
|
||||
};
|
||||
|
||||
// Uniform Info, provided by the Shader
|
||||
struct UniformInfo
|
||||
{
|
||||
// Name of the Uniform
|
||||
String name;
|
||||
|
||||
// The Value type of the Uniform
|
||||
UniformType type;
|
||||
|
||||
// The Shader type the Uniform is a part of
|
||||
ShaderType shader;
|
||||
|
||||
// Some rendering APIs have uniform buffers. The `buffer_index`
|
||||
// specifies which buffer the uniform belongs to
|
||||
int buffer_index;
|
||||
|
||||
// Array length of the Uniform (ex. a vec2[4] would be 4)
|
||||
int array_length;
|
||||
};
|
||||
|
||||
// Data to be passed to the shader to construct it
|
||||
struct ShaderData
|
||||
{
|
||||
struct HLSL_Attribute
|
||||
{
|
||||
// Semantic Name
|
||||
const char* semantic_name = nullptr;
|
||||
|
||||
// (optional) Semantic Index
|
||||
int semantic_index = 0;
|
||||
};
|
||||
|
||||
// Vertex Shader Program data
|
||||
const char* vertex;
|
||||
|
||||
// Fragment Shader Program data
|
||||
const char* fragment;
|
||||
|
||||
// HLSL Attributes - required for D3D11
|
||||
StackVector<HLSL_Attribute, 16> hlsl_attributes;
|
||||
};
|
||||
|
||||
class Shader;
|
||||
|
|
|
@ -9,14 +9,16 @@ 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);
|
||||
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);
|
||||
tex->set_data(rgba);
|
||||
if (tex)
|
||||
tex->set_data(rgba);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -35,10 +37,11 @@ TextureRef Texture::create(Stream& stream)
|
|||
{
|
||||
Image img = Image(stream);
|
||||
|
||||
if (img.pixels != nullptr && img.width > 0 && img.height > 0)
|
||||
if (img.pixels && img.width > 0 && img.height > 0)
|
||||
{
|
||||
auto tex = create(img.width, img.height, TextureFormat::RGBA);
|
||||
tex->set_data((unsigned char*)img.pixels);
|
||||
if (tex)
|
||||
tex->set_data((unsigned char*)img.pixels);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -49,10 +52,11 @@ TextureRef Texture::create(const char* file)
|
|||
{
|
||||
Image img = Image(file);
|
||||
|
||||
if (img.pixels != nullptr)
|
||||
if (img.pixels)
|
||||
{
|
||||
auto tex = create(img.width, img.height, TextureFormat::RGBA);
|
||||
tex->set_data((unsigned char*)img.pixels);
|
||||
if (tex)
|
||||
tex->set_data((unsigned char*)img.pixels);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Blah
|
|||
None,
|
||||
R,
|
||||
RG,
|
||||
RGB,
|
||||
RGBA,
|
||||
DepthStencil,
|
||||
Count
|
||||
|
|
Loading…
Reference in New Issue
Block a user