diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a8e2b6..af96384 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(blah public/blah/graphics/mesh.cpp public/blah/graphics/renderpass.h public/blah/graphics/renderpass.cpp + public/blah/graphics/sampler.h public/blah/graphics/shader.h public/blah/graphics/shader.cpp public/blah/graphics/texture.h diff --git a/private/blah/internal/graphics_backend.h b/private/blah/internal/graphics_backend.h index b8fa1d2..87cc1ad 100644 --- a/private/blah/internal/graphics_backend.h +++ b/private/blah/internal/graphics_backend.h @@ -43,11 +43,11 @@ namespace Blah // Creates a new Texture. // if the Texture is invalid, this should return an empty reference. - TextureRef create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format); + TextureRef create_texture(int width, int height, TextureFormat format); // Creates a new FrameBuffer. // if the FrameBuffer is invalid, this should return an empty reference. - FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount); + FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachment_count); // Creates a new Shader. // if the Shader is invalid, this should return an empty reference. diff --git a/private/blah/internal/graphics_backend_d3d11.cpp b/private/blah/internal/graphics_backend_d3d11.cpp index 11279cd..30c85df 100644 --- a/private/blah/internal/graphics_backend_d3d11.cpp +++ b/private/blah/internal/graphics_backend_d3d11.cpp @@ -58,9 +58,7 @@ namespace Blah struct StoredSampler { - TextureFilter filter; - TextureWrap wrap_x; - TextureWrap wrap_y; + TextureSampler sampler; ID3D11SamplerState* state; }; @@ -79,7 +77,7 @@ namespace Blah ID3D11InputLayout* get_layout(D3D11_Shader* shader, const VertexFormat& format); ID3D11BlendState* get_blend(const BlendMode& blend); ID3D11RasterizerState* get_rasterizer(const RenderPass& pass); - ID3D11SamplerState* get_sampler(const TextureRef& texture); + ID3D11SamplerState* get_sampler(const TextureSampler& sampler); ID3D11DepthStencilState* get_depthstencil(const RenderPass& pass); }; @@ -140,15 +138,23 @@ namespace Blah D3D11_SHADER_INPUT_BIND_DESC desc; reflector->GetResourceBindingDesc(i, &desc); - if (desc.Type == D3D_SIT_TEXTURE && - desc.Dimension == D3D_SRV_DIMENSION_TEXTURE2D) + if (desc.Type == D3D_SIT_TEXTURE && desc.Dimension == D3D_SRV_DIMENSION_TEXTURE2D) { auto uniform = append_to.expand(); uniform->name = desc.Name; uniform->shader = shader_type; uniform->buffer_index = 0; uniform->array_length = max(1, desc.BindCount); - uniform->type = UniformType::Texture; + uniform->type = UniformType::Texture2D; + } + else if (desc.Type == D3D_SIT_SAMPLER) + { + auto uniform = append_to.expand(); + uniform->name = desc.Name; + uniform->shader = shader_type; + uniform->buffer_index = 0; + uniform->array_length = max(1, desc.BindCount); + uniform->type = UniformType::Sampler2D; } } @@ -224,10 +230,7 @@ namespace Blah private: int m_width; int m_height; - TextureFilter m_filter; TextureFormat m_format; - TextureWrap m_wrap_x; - TextureWrap m_wrap_y; bool m_is_framebuffer; int m_size; @@ -235,14 +238,11 @@ namespace Blah ID3D11Texture2D* texture = nullptr; ID3D11ShaderResourceView* view = nullptr; - D3D11_Texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format, bool is_framebuffer) + D3D11_Texture(int width, int height, TextureFormat format, bool is_framebuffer) { m_width = width; m_height = height; - m_filter = filter; m_format = format; - m_wrap_x = wrap_x; - m_wrap_y = wrap_y; m_is_framebuffer = is_framebuffer; m_size = 0; @@ -320,32 +320,6 @@ namespace Blah return m_format; } - virtual void set_filter(TextureFilter filter) override - { - m_filter = filter; - } - - virtual TextureFilter get_filter() const override - { - return m_filter; - } - - virtual void set_wrap(TextureWrap x, TextureWrap y) override - { - m_wrap_x = x; - m_wrap_y = y; - } - - virtual TextureWrap get_wrap_x() const override - { - return m_wrap_x; - } - - virtual TextureWrap get_wrap_y() const override - { - return m_wrap_y; - } - virtual void set_data(unsigned char* data) override { D3D11_BOX box; @@ -386,17 +360,12 @@ namespace Blah StackVector color_views; ID3D11DepthStencilView* depth_view = nullptr; - D3D11_FrameBuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) + D3D11_FrameBuffer(int width, int height, const TextureFormat* attachments, int attachment_count) { - for (int i = 0; i < attachmentCount; i++) + for (int i = 0; i < attachment_count; i++) { - auto tex = new D3D11_Texture( - width, height, - TextureFilter::Linear, - TextureWrap::Repeat, - TextureWrap::Repeat, - attachments[i], - true); + auto tex = new D3D11_Texture(width, height, attachments[i], true); + m_attachments.push_back(TextureRef(tex)); if (attachments[i] == TextureFormat::DepthStencil) @@ -891,9 +860,9 @@ namespace Blah state.swap_chain->Present(1, 0); } - TextureRef GraphicsBackend::create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) + TextureRef GraphicsBackend::create_texture(int width, int height, TextureFormat format) { - auto result = new D3D11_Texture(width, height, filter, wrap_x, wrap_y, format, false); + auto result = new D3D11_Texture(width, height, format, false); if (result->texture) return TextureRef(result); @@ -901,9 +870,9 @@ namespace Blah return TextureRef(); } - FrameBufferRef GraphicsBackend::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount) + FrameBufferRef GraphicsBackend::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachment_count) { - return FrameBufferRef(new D3D11_FrameBuffer(width, height, attachments, attachmentCount)); + return FrameBufferRef(new D3D11_FrameBuffer(width, height, attachments, attachment_count)); } ShaderRef GraphicsBackend::create_shader(const ShaderData* data) @@ -936,7 +905,9 @@ namespace Blah const float* data = material->data(); for (auto& it : shader->uniforms()) { - if (it.type == UniformType::Texture) + if (it.type == UniformType::None || + it.type == UniformType::Texture2D || + it.type == UniformType::Sampler2D) continue; int size = 0; @@ -1071,7 +1042,7 @@ namespace Blah ctx->PSSetShader(shader->fragment, nullptr, 0); ctx->PSSetConstantBuffers(0, shader->fcb.size(), shader->fcb.begin()); - // Fragment Shader Textures & Samplers + // Fragment Shader Textures auto& textures = pass.material->textures(); for (int i = 0; i < textures.size(); i++) { @@ -1080,23 +1051,17 @@ namespace Blah // Assign the Texture auto view = ((D3D11_Texture*)textures[i].get())->view; ctx->PSSetShaderResources(i, 1, &view); - - // Assign the Sampler - - // TODO: - // This is incorrect! Textures and Samplers are separate in HLSL. - // For now, assuming there's 1 Sampler Per Texture, and we set it to - // the properties of the texture at the same index. - - // I think most modern APIs separate these, where as OpenGL makes - // them the same (afaik). Either we need to separate these in our - // API, or find some work around here. - - auto sampler = state.get_sampler(textures[i]); - if (sampler) - ctx->PSSetSamplers(i, 1, &sampler); } } + + // Fragment Shader Samplers + auto& samplers = pass.material->samplers(); + for (int i = 0; i < samplers.size(); i++) + { + auto sampler = state.get_sampler(samplers[i]); + if (sampler) + ctx->PSSetSamplers(i, 1, &sampler); + } } // RS @@ -1294,14 +1259,10 @@ namespace Blah return nullptr; } - ID3D11SamplerState* D3D11::get_sampler(const TextureRef& texture) + ID3D11SamplerState* D3D11::get_sampler(const TextureSampler& sampler) { - auto filter = texture->get_filter(); - auto wrap_x = texture->get_wrap_x(); - auto wrap_y = texture->get_wrap_y(); - for (auto& it : sampler_cache) - if (it.filter == filter && it.wrap_x == wrap_x && it.wrap_y == wrap_y) + if (it.sampler == sampler) return it.state; D3D11_SAMPLER_DESC desc = {}; @@ -1311,19 +1272,19 @@ namespace Blah desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.ComparisonFunc = D3D11_COMPARISON_NEVER; - switch (filter) + switch (sampler.filter) { case TextureFilter::Nearest: desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; break; case TextureFilter::Linear: desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; break; } - switch (wrap_x) + switch (sampler.wrap_x) { case TextureWrap::Clamp: desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; break; case TextureWrap::Repeat: desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; break; } - switch (wrap_y) + switch (sampler.wrap_y) { case TextureWrap::Clamp: desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; break; case TextureWrap::Repeat: desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; break; @@ -1335,9 +1296,7 @@ namespace Blah if (SUCCEEDED(hr)) { auto entry = sampler_cache.expand(); - entry->filter = filter; - entry->wrap_x = wrap_x; - entry->wrap_y = wrap_y; + entry->sampler = sampler; entry->state = result; return result; } diff --git a/private/blah/internal/graphics_backend_gl.cpp b/private/blah/internal/graphics_backend_gl.cpp index 886745f..d96b3a2 100644 --- a/private/blah/internal/graphics_backend_gl.cpp +++ b/private/blah/internal/graphics_backend_gl.cpp @@ -545,9 +545,7 @@ namespace Blah GLuint m_id; int m_width; int m_height; - TextureWrap m_wrap_x; - TextureWrap m_wrap_y; - TextureFilter m_filter; + TextureSampler m_sampler; TextureFormat m_format; GLenum m_gl_internal_format; GLenum m_gl_format; @@ -556,14 +554,12 @@ namespace Blah public: bool framebuffer_parent; - OpenGL_Texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) + OpenGL_Texture(int width, int height, TextureFormat format) { m_id = 0; m_width = width; m_height = height; - m_wrap_x = wrap_x; - m_wrap_y = wrap_y; - m_filter = filter; + m_sampler = TextureSampler(TextureFilter::None, TextureWrap::None, TextureWrap::None); m_format = format; framebuffer_parent = false; m_gl_internal_format = GL_RED; @@ -609,12 +605,7 @@ namespace Blah gl.GenTextures(1, &m_id); gl.ActiveTexture(GL_TEXTURE0); gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexImage2D(GL_TEXTURE_2D, 0, m_gl_internal_format, width, height, 0, m_gl_format, m_gl_type, nullptr); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (m_filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_wrap_x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_wrap_y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); } ~OpenGL_Texture() @@ -643,38 +634,18 @@ namespace Blah return m_format; } - virtual void set_filter(TextureFilter filter) override + void update_sampler(const TextureSampler& sampler) { - m_filter = filter; + if (m_sampler != sampler) + { + m_sampler = sampler; - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); - } - - virtual TextureFilter get_filter() const override - { - return m_filter; - } - - virtual void set_wrap(TextureWrap x, TextureWrap y) override - { - m_wrap_x = x; - m_wrap_y = y; - - gl.BindTexture(GL_TEXTURE_2D, m_id); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); - } - - virtual TextureWrap get_wrap_x() const override - { - return m_wrap_x; - } - - virtual TextureWrap get_wrap_y() const override - { - return m_wrap_y; + gl.BindTexture(GL_TEXTURE_2D, m_id); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (m_sampler.filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (m_sampler.filter == TextureFilter::Nearest ? GL_NEAREST : GL_LINEAR)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_sampler.wrap_x == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_sampler.wrap_y == TextureWrap::Clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT)); + } } virtual void set_data(unsigned char* data) override @@ -899,20 +870,34 @@ 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_SAMPLER_2D) { - uniform.type = UniformType::Texture; - uniform.shader = ShaderType::Fragment; + UniformInfo tex_uniform; + tex_uniform.name = name; + tex_uniform.buffer_index = 0; + tex_uniform.array_length = size; + tex_uniform.type = UniformType::Texture2D; + tex_uniform.shader = ShaderType::Fragment; + uniform_locations.push_back(gl.GetUniformLocation(id, name)); + m_uniforms.push_back(tex_uniform); + + UniformInfo sampler_uniform; + sampler_uniform.name = String(name).append("_sampler"); + sampler_uniform.buffer_index = 0; + sampler_uniform.array_length = size; + sampler_uniform.type = UniformType::Sampler2D; + sampler_uniform.shader = ShaderType::Fragment; + uniform_locations.push_back(gl.GetUniformLocation(id, name)); + m_uniforms.push_back(sampler_uniform); } else { + 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)); uniform.shader = (ShaderType)((int)ShaderType::Vertex | (int)ShaderType::Fragment); if (type == GL_FLOAT) @@ -933,9 +918,10 @@ namespace Blah Log::error("Unsupported Uniform Type"); break; } + + m_uniforms.push_back(uniform); } - m_uniforms.push_back(uniform); } } @@ -1192,9 +1178,9 @@ namespace Blah void GraphicsBackend::before_render() {} void GraphicsBackend::after_render() {} - TextureRef GraphicsBackend::create_texture(int width, int height, TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y, TextureFormat format) + TextureRef GraphicsBackend::create_texture(int width, int height, TextureFormat format) { - auto resource = new OpenGL_Texture(width, height, filter, wrap_x, wrap_y, format); + auto resource = new OpenGL_Texture(width, height, format); if (resource->gl_id() <= 0) { @@ -1272,10 +1258,9 @@ namespace Blah { gl.UseProgram(shader->gl_id()); - // upload uniform values int texture_slot = 0; + int gl_texture_slot = 0; GLint texture_ids[64]; - auto& uniforms = shader->uniforms(); auto data = pass.material->data(); @@ -1284,14 +1269,19 @@ namespace Blah auto location = shader->uniform_locations[i]; auto& uniform = uniforms[i]; - // Sampler 2D - if (uniform.type == UniformType::Texture) + // Sampler 2D's are assigned by updating texture values + if (uniform.type == UniformType::Sampler2D) + continue; + + // Texture2D + if (uniform.type == UniformType::Texture2D) { for (int n = 0; n < uniform.array_length; n++) { - auto tex = pass.material->get_texture(i, n); + auto tex = pass.material->get_texture(texture_slot, n); + auto sampler = pass.material->get_sampler(texture_slot, n); - gl.ActiveTexture(GL_TEXTURE0 + texture_slot); + gl.ActiveTexture(GL_TEXTURE0 + gl_texture_slot); if (!tex) { @@ -1299,14 +1289,17 @@ namespace Blah } else { - gl.BindTexture(GL_TEXTURE_2D, ((OpenGL_Texture*)tex.get())->gl_id()); + auto gl_tex = ((OpenGL_Texture*)tex.get()); + gl_tex->update_sampler(sampler); + gl.BindTexture(GL_TEXTURE_2D, gl_tex->gl_id()); } - texture_ids[n] = texture_slot; - texture_slot++; + texture_ids[n] = gl_texture_slot; + gl_texture_slot++; } gl.Uniform1iv(location, (GLint)uniform.array_length, &texture_ids[0]); + texture_slot++; continue; } diff --git a/public/blah.h b/public/blah.h index 796d204..8c9da8e 100644 --- a/public/blah.h +++ b/public/blah.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/public/blah/drawing/batch.cpp b/public/blah/drawing/batch.cpp index b21c95e..9fd547c 100644 --- a/public/blah/drawing/batch.cpp +++ b/public/blah/drawing/batch.cpp @@ -339,6 +339,18 @@ void Batch::set_texture(const TextureRef& texture) } } +void Batch::set_sampler(const TextureSampler& sampler) +{ + if (m_batch.elements > 0 && sampler != m_batch.sampler) + { + m_batches.push_back(m_batch); + m_batch.offset += m_batch.elements; + m_batch.elements = 0; + } + + m_batch.sampler = sampler; +} + void Batch::render(const FrameBufferRef& target) { Point size; @@ -394,7 +406,8 @@ void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4 if (!pass.material) pass.material = m_default_material; - pass.material->set_texture(0, b.texture, 0); + pass.material->set_texture(0, b.texture); + pass.material->set_sampler(0, b.sampler); pass.material->set_value(matrix_uniform, &matrix.m11, 16); pass.blend = b.blend; @@ -422,6 +435,7 @@ void Batch::clear() m_batch.blend = BlendMode::Normal; m_batch.material.reset(); m_batch.texture.reset(); + m_batch.sampler = default_sampler; m_batch.scissor.w = m_batch.scissor.h = -1; m_batch.flip_vertically = false; diff --git a/public/blah/drawing/batch.h b/public/blah/drawing/batch.h index 00bb97e..38eea63 100644 --- a/public/blah/drawing/batch.h +++ b/public/blah/drawing/batch.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,9 @@ namespace Blah // The name of the Matrix Uniform in the Shader const char* matrix_uniform; + // Default Sampler, set on clear + TextureSampler default_sampler; + Batch(); Batch(const Batch& other) = delete; Batch& operator=(const Batch& other) = delete; @@ -112,6 +116,9 @@ namespace Blah // this (ex the `str` and `tex` methods) void set_texture(const TextureRef& texture); + // Sets the current texture sampler for drawing. + void set_sampler(const TextureSampler& sampler); + // Draws the batch to the given target void render(const FrameBufferRef& target = App::backbuffer); @@ -194,6 +201,7 @@ namespace Blah MaterialRef material; BlendMode blend; TextureRef texture; + TextureSampler sampler; bool flip_vertically; Rect scissor; diff --git a/public/blah/graphics/blend.h b/public/blah/graphics/blend.h index a6624c9..20611d8 100644 --- a/public/blah/graphics/blend.h +++ b/public/blah/graphics/blend.h @@ -89,7 +89,7 @@ namespace Blah rgba = blendColor; } - inline bool operator==(const BlendMode& rhs) const + bool operator==(const BlendMode& rhs) const { return color_op == rhs.color_op && color_src == rhs.color_src && color_dst == rhs.color_dst && @@ -97,7 +97,7 @@ namespace Blah mask == rhs.mask && rgba == rhs.rgba; } - inline bool operator!=(const BlendMode& rhs) const + bool operator!=(const BlendMode& rhs) const { return !(*this == rhs); } diff --git a/public/blah/graphics/material.cpp b/public/blah/graphics/material.cpp index 62b1b8e..a4b6472 100644 --- a/public/blah/graphics/material.cpp +++ b/public/blah/graphics/material.cpp @@ -49,13 +49,20 @@ Material::Material(const ShaderRef& shader) if (uniform.type == UniformType::None) continue; - if (uniform.type == UniformType::Texture) + if (uniform.type == UniformType::Texture2D) { for (int i = 0; i < uniform.array_length; i ++) m_textures.push_back(TextureRef()); continue; } + if (uniform.type == UniformType::Sampler2D) + { + for (int i = 0; i < uniform.array_length; i++) + m_samplers.push_back(TextureSampler()); + continue; + } + float_size += calc_uniform_size(uniform); } @@ -74,7 +81,7 @@ void Material::set_texture(const char* name, const TextureRef& texture, int inde int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type != UniformType::Texture) + if (uniform.type != UniformType::Texture2D) continue; if (strcmp(uniform.name, name) == 0) @@ -99,19 +106,20 @@ void Material::set_texture(int slot, const TextureRef& texture, int index) int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type == UniformType::Texture) - { - if (s == slot) - { - if (index > uniform.array_length) - break; + if (uniform.type != UniformType::Texture2D) + continue; - m_textures[offset + index] = texture; + if (s == slot) + { + if (index > uniform.array_length) break; - } - offset += uniform.array_length; - s++; + + m_textures[offset + index] = texture; + break; } + + offset += uniform.array_length; + s++; } } @@ -122,7 +130,7 @@ TextureRef Material::get_texture(const char* name, int index) const int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type != UniformType::Texture) + if (uniform.type != UniformType::Texture2D) continue; if (strcmp(uniform.name, name) == 0) @@ -145,21 +153,21 @@ TextureRef Material::get_texture(int slot, int index) const int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type == UniformType::Texture) + if (uniform.type != UniformType::Texture2D) + continue; + + if (s == slot) { - if (s == slot) - { - if (index > uniform.array_length) - break; - - return m_textures[offset + index]; - } - - offset += uniform.array_length; - if (offset + index >= m_textures.size()) + if (index > uniform.array_length) break; + + return m_textures[offset + index]; } + offset += uniform.array_length; + if (offset + index >= m_textures.size()) + break; + s++; } @@ -167,6 +175,107 @@ TextureRef Material::get_texture(int slot, int index) const return TextureRef(); } +void Material::set_sampler(const char* name, const TextureSampler& sampler, int index) +{ + BLAH_ASSERT(m_shader, "Material Shader is invalid"); + + int offset = 0; + for (auto& uniform : m_shader->uniforms()) + { + if (uniform.type != UniformType::Sampler2D) + continue; + + if (strcmp(uniform.name, name) == 0) + { + m_samplers[offset + index] = sampler; + return; + } + + offset += uniform.array_length; + if (offset + index >= m_samplers.size()) + break; + } + + Log::warn("No Sampler Uniform '%s' at index [%i] exists", name, index); +} + +void Material::set_sampler(int slot, const TextureSampler& sampler, int index) +{ + BLAH_ASSERT(m_shader, "Material Shader is invalid"); + + int s = 0; + int offset = 0; + for (auto& uniform : m_shader->uniforms()) + { + if (uniform.type != UniformType::Sampler2D) + continue; + + if (s == slot) + { + if (index > uniform.array_length) + break; + + m_samplers[offset + index] = sampler; + break; + } + + offset += uniform.array_length; + s++; + } +} + +TextureSampler Material::get_sampler(const char* name, int index) const +{ + BLAH_ASSERT(m_shader, "Material Shader is invalid"); + + int offset = 0; + for (auto& uniform : m_shader->uniforms()) + { + if (uniform.type != UniformType::Sampler2D) + continue; + + if (strcmp(uniform.name, name) == 0) + return m_samplers[offset + index]; + + offset += uniform.array_length; + if (offset + index >= m_samplers.size()) + break; + } + + Log::warn("No Sampler Uniform '%s' at index [%i] exists", name, index); + return TextureSampler(); +} + +TextureSampler Material::get_sampler(int slot, int index) const +{ + BLAH_ASSERT(m_shader, "Material Shader is invalid"); + + int s = 0; + int offset = 0; + for (auto& uniform : m_shader->uniforms()) + { + if (uniform.type != UniformType::Sampler2D) + continue; + + if (s == slot) + { + if (index > uniform.array_length) + break; + + return m_samplers[offset + index]; + } + + offset += uniform.array_length; + if (offset + index >= m_samplers.size()) + break; + + s++; + } + + Log::warn("No Sampler Uniform ['%i'] at index [%i] exists", slot, index); + return TextureSampler(); +} + void Material::set_value(const char* name, const float* value, int64_t length) { BLAH_ASSERT(m_shader, "Material Shader is invalid"); @@ -176,7 +285,9 @@ void Material::set_value(const char* name, const float* value, int64_t length) int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type == UniformType::Texture || uniform.type == UniformType::None) + if (uniform.type == UniformType::Texture2D || + uniform.type == UniformType::Sampler2D || + uniform.type == UniformType::None) continue; if (strcmp(uniform.name, name) == 0) @@ -207,7 +318,9 @@ const float* Material::get_value(const char* name, int64_t* length) const int offset = 0; for (auto& uniform : m_shader->uniforms()) { - if (uniform.type == UniformType::Texture || uniform.type == UniformType::None) + if (uniform.type == UniformType::Texture2D || + uniform.type == UniformType::Sampler2D || + uniform.type == UniformType::None) continue; if (strcmp(uniform.name, name) == 0) @@ -231,6 +344,11 @@ const Vector& Material::textures() const return m_textures; } +const Vector& Material::samplers() const +{ + return m_samplers; +} + const float* Material::data() const { return m_data.begin(); diff --git a/public/blah/graphics/material.h b/public/blah/graphics/material.h index f0dfcd9..a39b130 100644 --- a/public/blah/graphics/material.h +++ b/public/blah/graphics/material.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include @@ -43,6 +44,18 @@ namespace Blah // Gets the texture, or an empty reference if invalid TextureRef get_texture(int slot, int array_index = 0) const; + // Sets the sampler + void set_sampler(const char* name, const TextureSampler& sampler, int array_index = 0); + + // Sets the sampler + void set_sampler(int slot, const TextureSampler& sampler, int array_index = 0); + + // Gets the sampler + TextureSampler get_sampler(const char* name, int array_index = 0) const; + + // Gets the sampler + TextureSampler get_sampler(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); @@ -52,12 +65,16 @@ namespace Blah // Returns the internal Texture buffer const Vector& textures() const; + // Returns the internal Sampler buffer + const Vector& samplers() const; + // Returns the interal float buffer of all the values const float* data() const; private: ShaderRef m_shader; Vector m_textures; + Vector m_samplers; Vector m_data; }; } \ No newline at end of file diff --git a/public/blah/graphics/sampler.h b/public/blah/graphics/sampler.h new file mode 100644 index 0000000..432c8f8 --- /dev/null +++ b/public/blah/graphics/sampler.h @@ -0,0 +1,53 @@ +#pragma once + +namespace Blah +{ + enum class TextureFilter + { + None, + Linear, + Nearest + }; + + enum class TextureWrap + { + None, + Clamp, + Repeat + }; + + struct TextureSampler + { + TextureFilter filter; + TextureWrap wrap_x; + TextureWrap wrap_y; + + TextureSampler() : + filter(TextureFilter::Linear), + wrap_x(TextureWrap::Repeat), + wrap_y(TextureWrap::Repeat) {} + + TextureSampler(TextureFilter filter) : + filter(filter), + wrap_x(TextureWrap::Repeat), + wrap_y(TextureWrap::Repeat) {} + + TextureSampler(TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y) : + filter(filter), + wrap_x(wrap_x), + wrap_y(wrap_y) {} + + bool operator==(const TextureSampler& rhs) const + { + return + filter == rhs.filter && + wrap_x == rhs.wrap_x && + wrap_y == rhs.wrap_y; + } + + bool operator!=(const TextureSampler& rhs) const + { + return !(*this == rhs); + } + }; +} \ No newline at end of file diff --git a/public/blah/graphics/shader.h b/public/blah/graphics/shader.h index 4c8f3b2..ec5d2a9 100644 --- a/public/blah/graphics/shader.h +++ b/public/blah/graphics/shader.h @@ -15,7 +15,8 @@ namespace Blah Float4, Mat3x2, Mat4x4, - Texture + Texture2D, + Sampler2D }; // Supported Shader Types diff --git a/public/blah/graphics/texture.cpp b/public/blah/graphics/texture.cpp index ef18245..04fcb5c 100644 --- a/public/blah/graphics/texture.cpp +++ b/public/blah/graphics/texture.cpp @@ -28,7 +28,7 @@ TextureRef Texture::create(int width, int height, TextureFormat format) 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 GraphicsBackend::create_texture(width, height, format); return TextureRef(); } diff --git a/public/blah/graphics/texture.h b/public/blah/graphics/texture.h index ac13190..33c4368 100644 --- a/public/blah/graphics/texture.h +++ b/public/blah/graphics/texture.h @@ -3,19 +3,6 @@ namespace Blah { - enum class TextureFilter - { - None, - Linear, - Nearest - }; - - enum class TextureWrap - { - None, - Clamp, - Repeat - }; enum class TextureFormat { @@ -76,21 +63,6 @@ namespace Blah // Gets the format of the Texture virtual TextureFormat format() const = 0; - // Sets the filter of the Texture - virtual void set_filter(TextureFilter filter) = 0; - - // Gets the filter of the Texture - virtual TextureFilter get_filter() const = 0; - - // Sets the wrap of the Texture - virtual void set_wrap(TextureWrap x, TextureWrap y) = 0; - - // Gets the wrap of the Texture - virtual TextureWrap get_wrap_x() const = 0; - - // Gets the wrap of the Texture - virtual TextureWrap get_wrap_y() const = 0; - // Sets the data of the Texture. // Note that the pixel buffer should be in the same format as the Texture. There is no row padding. // If the pixel buffer isn't the same size as the texture, it will set the minimum available amount of data.