added singleton shader manager, custom widget attribute forward, parse border thickness and color for Border widget, parse and cache uniform locations, remove unused attrubutes code

This commit is contained in:
2017-01-30 19:52:32 +00:00
parent 16c1b6481e
commit a80556f418
8 changed files with 179 additions and 172 deletions

View File

@@ -34,7 +34,7 @@
</plane> </plane>
<!-- content panel --> <!-- content panel -->
<plane width="1" grow="1" height="100%" pad="30" wrap="1"> <plane width="1" grow="1" height="100%" pad="30" wrap="1">
<border color=".2" height="100%"></border> <border thickness="5" border-color="1" color=".4" height="100%"></border>
</plane> </plane>
</plane> </plane>
<!-- status bar --> <!-- status bar -->

View File

@@ -78,10 +78,10 @@ void App::init()
layout.update(width, height); layout.update(width, height);
sampler.create(); sampler.create();
shader.create(shader_v, shader_f); ShaderManager::create(kShader::Texture, shader_v, shader_f);
shader_color.create(shader_color_v, shader_color_f); ShaderManager::create(kShader::Color, shader_color_v, shader_color_f);
shader_uv.create(shader_v, shader_uv_f); ShaderManager::create(kShader::UVs, shader_v, shader_uv_f);
plane.create<5>(1, 1); WidgetBorder::m_plane.create<1>(1, 1);
if (!tex.load("data/uvs.jpg")) if (!tex.load("data/uvs.jpg"))
printf("error loading image\n"); printf("error loading image\n");
@@ -118,10 +118,8 @@ void App::update(float dt)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
tex.bind(); tex.bind();
sampler.bind(0); sampler.bind(0);
shader.use(); ShaderManager::use(kShader::Texture);
shader.u_int("tex", 0); ShaderManager::u_int(kShaderUniform::Tex, 0);
shader_color.use();
shader_color.u_vec4("col", { .3f, .3f, .3f, 1 });
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
@@ -132,15 +130,7 @@ void App::update(float dt)
if (n.m_widget) if (n.m_widget)
{ {
shader_color.u_vec4("col", n.color); n.m_widget->draw();
shader_color.use();
shader_color.u_mat4("mvp", n.m_widget->mvp);
plane.draw_fill();
shader_color.u_vec4("col", { 1, 1, 1, 1 });
shader_color.use();
shader_color.u_mat4("mvp", n.m_widget->mvp);
plane.draw_stroke();
} }
} }
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);

View File

@@ -8,10 +8,6 @@
class App class App
{ {
Sampler sampler; Sampler sampler;
Shader shader;
Shader shader_color;
Shader shader_uv;
Plane plane;
Texture2D tex; Texture2D tex;
Node layout; Node layout;
public: public:

View File

@@ -2,7 +2,7 @@
#include "layout.h" #include "layout.h"
#include "util.hpp" #include "util.hpp"
Plane* WidgetBorder::m_plane; Plane WidgetBorder::m_plane;
void Node::update(float width, float height) void Node::update(float width, float height)
{ {
@@ -34,11 +34,11 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
c.update_internal(m_pos, proj); c.update_internal(m_pos, proj);
} }
void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr) void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
{ {
switch (ka) switch (ka)
{ {
case att::kAttribute::Width: case kAttribute::Width:
if (strcmp(attr->Value(), "auto") == 0) if (strcmp(attr->Value(), "auto") == 0)
{ {
YGNodeStyleSetWidth(y_node, YGUndefined); YGNodeStyleSetWidth(y_node, YGUndefined);
@@ -52,16 +52,16 @@ void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* at
YGNodeStyleSetWidth(y_node, attr->FloatValue()); YGNodeStyleSetWidth(y_node, attr->FloatValue());
} }
break; break;
case att::kAttribute::MinWidth: case kAttribute::MinWidth:
if (strchr(attr->Value(), '%')) if (strchr(attr->Value(), '%'))
YGNodeStyleSetMinWidthPercent(y_node, attr->FloatValue()); YGNodeStyleSetMinWidthPercent(y_node, attr->FloatValue());
else else
YGNodeStyleSetMinWidth(y_node, attr->FloatValue()); YGNodeStyleSetMinWidth(y_node, attr->FloatValue());
break; break;
case att::kAttribute::MaxWidth: case kAttribute::MaxWidth:
YGNodeStyleSetMaxWidth(y_node, attr->FloatValue()); YGNodeStyleSetMaxWidth(y_node, attr->FloatValue());
break; break;
case att::kAttribute::Height: case kAttribute::Height:
if (strcmp(attr->Value(), "auto") == 0) if (strcmp(attr->Value(), "auto") == 0)
{ {
YGNodeStyleSetHeight(y_node, YGUndefined); YGNodeStyleSetHeight(y_node, YGUndefined);
@@ -75,19 +75,19 @@ void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* at
YGNodeStyleSetHeight(y_node, attr->FloatValue()); YGNodeStyleSetHeight(y_node, attr->FloatValue());
} }
break; break;
case att::kAttribute::MinHeight: case kAttribute::MinHeight:
YGNodeStyleSetMinHeight(y_node, attr->FloatValue()); YGNodeStyleSetMinHeight(y_node, attr->FloatValue());
break; break;
case att::kAttribute::MaxHeight: case kAttribute::MaxHeight:
YGNodeStyleSetMaxHeight(y_node, attr->FloatValue()); YGNodeStyleSetMaxHeight(y_node, attr->FloatValue());
break; break;
case att::kAttribute::Grow: case kAttribute::Grow:
YGNodeStyleSetFlexGrow(y_node, attr->FloatValue()); YGNodeStyleSetFlexGrow(y_node, attr->FloatValue());
break; break;
case att::kAttribute::Shrink: case kAttribute::Shrink:
YGNodeStyleSetFlexShrink(y_node, attr->FloatValue()); YGNodeStyleSetFlexShrink(y_node, attr->FloatValue());
break; break;
case att::kAttribute::FlexDir: case kAttribute::FlexDir:
{ {
YGFlexDirection dir = YGFlexDirectionRow; YGFlexDirection dir = YGFlexDirectionRow;
if (strcmp("col", attr->Value()) == 0) if (strcmp("col", attr->Value()) == 0)
@@ -101,10 +101,10 @@ void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* at
YGNodeStyleSetFlexDirection(y_node, dir); YGNodeStyleSetFlexDirection(y_node, dir);
break; break;
} }
case att::kAttribute::FlexWrap: case kAttribute::FlexWrap:
YGNodeStyleSetFlexWrap(y_node, attr->IntValue() ? YGWrapWrap : YGWrapNoWrap); YGNodeStyleSetFlexWrap(y_node, attr->IntValue() ? YGWrapWrap : YGWrapNoWrap);
break; break;
case att::kAttribute::Padding: case kAttribute::Padding:
{ {
glm::vec4 pad; glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
@@ -124,7 +124,7 @@ void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* at
} }
break; break;
} }
case att::kAttribute::Margin: case kAttribute::Margin:
{ {
glm::vec4 pad; glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
@@ -144,22 +144,9 @@ void Node::parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* at
} }
break; break;
} }
case att::kAttribute::Color:
{
glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
if (n == 1)
{
color = glm::vec4(pad.x);
}
else
{
color = pad;
}
break;
}
default: default:
// other_attributes_handler() if (m_widget)
m_widget->parse_attributes(ka, attr);
break; break;
} }
} }
@@ -189,17 +176,17 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
m_name = x_node->Name(); m_name = x_node->Name();
auto attr = x_node->FirstAttribute(); auto attr = x_node->FirstAttribute();
att::kWidget widget_id = (att::kWidget)const_hash(x_node->Name()); kWidget widget_id = (kWidget)const_hash(x_node->Name());
switch (widget_id) switch (widget_id)
{ {
case att::kWidget::Border: case kWidget::Border:
m_widget = std::make_unique<WidgetBorder>(); m_widget = std::make_unique<WidgetBorder>();
break; break;
} }
while (attr) while (attr)
{ {
parse_attributes((att::kAttribute)const_hash(attr->Name()), attr); parse_attributes((kAttribute)const_hash(attr->Name()), attr);
attr = attr->Next(); attr = attr->Next();
} }

View File

@@ -1,104 +1,34 @@
#pragma once #pragma once
#include "shape.hpp" #include "shape.hpp"
#include "util.hpp" #include "util.hpp"
#include "shader.hpp"
namespace att enum class kAttribute : uint16_t
{ {
enum class kAttribute : uint16_t Width = const_hash("width"),
{ MinWidth = const_hash("max-width"),
Width = const_hash("width"), MaxWidth = const_hash("min-width"),
MinWidth = const_hash("max-width"), Height = const_hash("height"),
MaxWidth = const_hash("min-width"), MinHeight = const_hash("min-height"),
Height = const_hash("height"), MaxHeight = const_hash("max-height"),
MinHeight = const_hash("min-height"), Divisions = const_hash("divisions"),
MaxHeight = const_hash("max-height"), InnerRadius = const_hash("inner-radius"),
Divisions = const_hash("divisions"), OuterRadius = const_hash("outer-radius"),
InnerRadius = const_hash("inner-radius"), Grow = const_hash("grow"),
OuterRadius = const_hash("outer-radius"), Shrink = const_hash("shrink"),
Grow = const_hash("grow"), FlexDir = const_hash("dir"),
Shrink = const_hash("shrink"), FlexWrap = const_hash("wrap"),
FlexDir = const_hash("dir"), Padding = const_hash("pad"),
FlexWrap = const_hash("wrap"), Margin = const_hash("margin"),
Padding = const_hash("pad"), Color = const_hash("color"),
Margin = const_hash("margin"), Thickness = const_hash("thickness"),
Color = const_hash("color"), BorderColor = const_hash("border-color"),
}; };
enum class kWidget : uint16_t enum class kWidget : uint16_t
{ {
Border = const_hash("border"), Border = const_hash("border"),
}; };
struct AttributeBase
{
kAttribute id;
};
typedef std::map<att::kAttribute, std::unique_ptr<att::AttributeBase>> AttrubutesMap;
template<kAttribute T, typename V>
struct Attribute : public AttributeBase
{
static const kAttribute static_id = T;
V value;
Attribute() : value{ 0 } { id = static_id; }
Attribute(V v) : value(v) { id = static_id; }
};
struct kAttributeMap
{
kAttribute value;
const char* name;
};
static constexpr kAttributeMap map[] =
{
{ kAttribute::Width, "width" },
{ kAttribute::MinWidth, "min-width" },
{ kAttribute::MaxWidth, "max-width" },
{ kAttribute::Height, "height" },
{ kAttribute::MinHeight, "min-height" },
{ kAttribute::MaxHeight, "max-height" },
{ kAttribute::Divisions, "divisions" },
{ kAttribute::InnerRadius, "inner-radius" },
{ kAttribute::OuterRadius, "outer-radius" },
{ kAttribute::Grow, "grow" },
{ kAttribute::Shrink, "shrink" },
{ kAttribute::FlexDir, "dir" },
{ kAttribute::FlexWrap, "wrap" },
{ kAttribute::Padding, "pad" },
{ kAttribute::Margin, "margin" },
{ kAttribute::Color, "color" },
};
constexpr const char* string(const kAttribute value, int i = 0)
{
// no check on size, value MUST be found
return (map[i].value == value) ? map[i].name : string(value, i + 1);
}
#define DECLARE_ATTRIBUTE(N,T) \
struct N : public Attribute<kAttribute::N,T> \
{ using Attribute<kAttribute::N,T>::Attribute; };
DECLARE_ATTRIBUTE(Width, float);
DECLARE_ATTRIBUTE(MinWidth, float);
DECLARE_ATTRIBUTE(MaxWidth, float);
DECLARE_ATTRIBUTE(Height, float);
DECLARE_ATTRIBUTE(MinHeight, float);
DECLARE_ATTRIBUTE(MaxHeight, float);
DECLARE_ATTRIBUTE(Divisions, int);
DECLARE_ATTRIBUTE(InnerRadius, float);
DECLARE_ATTRIBUTE(OuterRadius, float);
DECLARE_ATTRIBUTE(Grow, float);
DECLARE_ATTRIBUTE(Shrink, float);
DECLARE_ATTRIBUTE(FlexDir, int);
DECLARE_ATTRIBUTE(FlexWrap, int);
DECLARE_ATTRIBUTE(Padding, glm::vec4);
DECLARE_ATTRIBUTE(Margin, glm::vec4);
DECLARE_ATTRIBUTE(Color, glm::vec4);
#undef DECLARE_ATTRIBUTE
}
class Widget class Widget
{ {
@@ -106,15 +36,56 @@ public:
glm::mat4 mvp; glm::mat4 mvp;
glm::vec4 clip; glm::vec4 clip;
virtual void draw() { }; virtual void draw() { };
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { };
}; };
class WidgetBorder : public Widget class WidgetBorder : public Widget
{ {
public: public:
static Plane* m_plane; static Plane m_plane;
glm::vec4 m_color;
glm::vec4 m_border_color;
float m_thinkness{ 1 };
virtual void draw() override virtual void draw() override
{ {
m_plane->draw_fill(); ShaderManager::use(kShader::Color);
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
ShaderManager::u_vec4(kShaderUniform::Col, m_color);
m_plane.draw_fill();
glLineWidth(m_thinkness);
ShaderManager::u_vec4(kShaderUniform::Col, m_border_color);
m_plane.draw_stroke();
}
virtual void parse_attributes(kAttribute id, const tinyxml2::XMLAttribute* attr)
{
switch (id)
{
case kAttribute::Color:
{
glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
if (n == 1)
m_color = glm::vec4(pad.x);
else
m_color = pad;
break;
}
case kAttribute::BorderColor:
{
glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
if (n == 1)
m_border_color = glm::vec4(pad.x);
else
m_border_color = pad;
break;
}
case kAttribute::Thickness:
m_thinkness = attr->FloatValue();
break;
}
} }
}; };
@@ -131,7 +102,6 @@ public:
glm::vec2 m_pos; glm::vec2 m_pos;
glm::vec2 m_size; glm::vec2 m_size;
glm::vec4 m_clip; glm::vec4 m_clip;
glm::vec4 color;
std::string m_name; std::string m_name;
Node(const Node&) = delete; Node(const Node&) = delete;
Node& operator=(const Node&) = delete; Node& operator=(const Node&) = delete;
@@ -143,7 +113,6 @@ public:
c.parent = this; c.parent = this;
parent = o.parent; parent = o.parent;
y_node = o.y_node; y_node = o.y_node;
color = o.color;
m_pos = o.m_pos; m_pos = o.m_pos;
m_size = o.m_size; m_size = o.m_size;
m_clip = o.m_clip; m_clip = o.m_clip;
@@ -189,7 +158,7 @@ public:
void update(float width, float height); void update(float width, float height);
void update_internal(const glm::vec2& origin, const glm::mat4& proj); void update_internal(const glm::vec2& origin, const glm::mat4& proj);
void parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr); void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
void load(const char* path); void load(const char* path);
void load_internal(const tinyxml2::XMLElement* x_node); void load_internal(const tinyxml2::XMLElement* x_node);
void reload(); void reload();

View File

@@ -1,7 +1,10 @@
#include "pch.h" #include "pch.h"
#include "shader.hpp" #include "shader.hpp"
bool Shader::create(std::string vertex, std::string fragment) std::map<kShader, Shader> ShaderManager::m_shaders;
Shader* ShaderManager::m_current;
bool Shader::create(const char* vertex, const char* fragment)
{ {
GLint status; GLint status;
static char infolog[4096]; static char infolog[4096];
@@ -13,7 +16,7 @@ bool Shader::create(std::string vertex, std::string fragment)
{ {
return false; return false;
} }
source = vertex.c_str(); source = vertex;
glShaderSource(vs, 1, &source, nullptr); glShaderSource(vs, 1, &source, nullptr);
glCompileShader(vs); glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &status); glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
@@ -32,7 +35,7 @@ bool Shader::create(std::string vertex, std::string fragment)
glDeleteShader(vs); glDeleteShader(vs);
return false; return false;
} }
source = fragment.c_str(); source = fragment;
glShaderSource(fs, 1, &source, nullptr); glShaderSource(fs, 1, &source, nullptr);
glCompileShader(fs); glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &status); glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
@@ -71,6 +74,23 @@ bool Shader::create(std::string vertex, std::string fragment)
glDeleteProgram(ps); glDeleteProgram(ps);
return false; return false;
} }
// Parse shader uniforms
{
GLint count;
GLint size; // size of the variable
GLenum type; // type of the variable (float, vec3 or mat4, etc)
const GLsizei bufSize = 16; // maximum name length
GLchar name[bufSize]; // variable name in GLSL
GLsizei length; // name length
glGetProgramiv(ps, GL_ACTIVE_UNIFORMS, &count);
for (int i = 0; i < count; i++)
{
glGetActiveUniform(ps, (GLuint)i, bufSize, &length, &size, &type, name);
m_umap[(kShaderUniform)const_hash(name)] = glGetUniformLocation(ps, name);
//printf("Uniform #%d Type: %u Name: %s Loc: %d\n", i, type, name, glGetUniformLocation(ps, name));
}
}
prog = ps; prog = ps;
@@ -80,18 +100,47 @@ void Shader::use()
{ {
glUseProgram(prog); glUseProgram(prog);
} }
void Shader::u_vec4(const char* name, const glm::vec4& v) void Shader::u_vec4(kShaderUniform id, const glm::vec4& v)
{ {
auto loc = glGetUniformLocation(prog, name); glUniform4fv(m_umap[id], 1, glm::value_ptr(v));
glUniform4fv(loc, 1, glm::value_ptr(v));
} }
void Shader::u_mat4(const char* name, const glm::mat4& m) void Shader::u_mat4(kShaderUniform id, const glm::mat4& m)
{ {
auto loc = glGetUniformLocation(prog, name); glUniformMatrix4fv(m_umap[id], 1, GL_FALSE, glm::value_ptr(m));
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(m));
} }
void Shader::u_int(const char* name, int i) void Shader::u_int(kShaderUniform id, int i)
{ {
auto loc = glGetUniformLocation(prog, name); glUniform1i(m_umap[id], i);
glUniform1i(loc, i); }
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
{
return m_shaders[id].create(vertex, fragment);
}
void ShaderManager::use(kShader id)
{
m_current = &m_shaders[id];
m_current->use();
}
void ShaderManager::use(const char* name)
{
m_current = &m_shaders[(kShader)const_hash(name)];
m_current->use();
}
void ShaderManager::u_vec4(kShaderUniform id, const glm::vec4& v)
{
m_current->u_vec4(id, v);
}
void ShaderManager::u_mat4(kShaderUniform id, const glm::mat4& m)
{
m_current->u_mat4(id, m);
}
void ShaderManager::u_int(kShaderUniform id, int i)
{
m_current->u_int(id, i);
} }

View File

@@ -1,25 +1,41 @@
#pragma once #pragma once
#include "util.hpp" #include "util.hpp"
enum class kShaderUniform : uint16_t
{
MVP = const_hash("mvp"),
Tex = const_hash("tex"),
Col = const_hash("col"),
};
class Shader class Shader
{ {
std::map<kShaderUniform, GLuint> m_umap;
GLuint prog; GLuint prog;
public: public:
bool create(std::string vertex, std::string fragment); bool create(const char* vertex, const char* fragment);
void use(); void use();
void u_vec4(const char* name, const glm::vec4& v); void u_vec4(kShaderUniform id, const glm::vec4& v);
void u_mat4(const char* name, const glm::mat4& m); void u_mat4(kShaderUniform id, const glm::mat4& m);
void u_int(const char* name, int i); void u_int(kShaderUniform id, int i);
}; };
enum class kShader : uint16_t enum class kShader : uint16_t
{ {
Color = const_hash("color"), Color = const_hash("color"),
Texture = const_hash("texture"),
UVs = const_hash("uvs"),
}; };
class ShaderManager class ShaderManager
{ {
static std::map<kShader, Shader> m_shaders;
static Shader* m_current;
public: public:
static bool create(kShader id, const char* vertex, const char* fragment);
static void use(kShader id); static void use(kShader id);
static void use(const char* name); static void use(const char* name);
static void u_vec4(kShaderUniform id, const glm::vec4& v);
static void u_mat4(kShaderUniform id, const glm::mat4& m);
static void u_int(kShaderUniform id, int i);
}; };

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
uint16_t constexpr const_hash(char const *input) uint16_t constexpr const_hash(const char* input)
{ {
return *input ? return *input ?
static_cast<uint16_t>(*input) + 33 * const_hash(input + 1) : static_cast<uint16_t>(*input) + 33 * const_hash(input + 1) :