implement grid and heightmap with lambert shading

This commit is contained in:
2018-12-24 22:22:16 +01:00
parent 4d2706bfab
commit 52c87d9ec6
16 changed files with 297 additions and 101 deletions

View File

@@ -248,58 +248,49 @@
</border> </border>
<border color=".3" pad="5" dir="col" width="100%"> <border color=".3" pad="5" dir="col" width="100%">
<border color=".2" height="20" justify="center" align="center"><text text="Ground" font-face="arial" font-size="11"/></border>
<node dir="row"> <node dir="row">
<node width="30%" dir="col"> <node width="40%" dir="col">
<node height="20" justify="center"><text text="Opacity" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="Opacity" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Scale" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Value" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="Value" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Height" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="Resolution" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Offset" font-face="arial" font-size="11"/></node>
</node> </node>
<border dir="col" align="center" grow="1" width="1" flood-events="1"> <border dir="col" align="center" grow="1" width="1" flood-events="1">
<node height="20" pad="1" width="100%"><slider-h id="grid-ground-opacity"/></node> <node height="20" pad="1" width="100%"><slider-h id="grid-ground-opacity"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-ground-scale" value="0.5"/></node> <node height="20" pad="1" width="100%"><slider-h id="grid-ground-value" value="0.0"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-ground-value" value="0.5"/></node> <node height="20" pad="1" width="100%"><slider-h id="grid-ground-resolution" value="0.2"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-ground-height" value="0.5"/></node> <node height="20" pad="1" width="100%"><slider-h id="grid-ground-offset" value="0.25"/></node>
</border> </border>
</node> </node>
<node height="10"/>
<!--<border color=".2" height="20" justify="center" align="center"><text text="Box" font-face="arial" font-size="11"/></border> <border color=".2" height="20" justify="center" align="center"><text text="Heightmap" font-face="arial" font-size="11"/></border>
<node dir="row">
<node width="30%" dir="col">
<node height="20" justify="center"><text text="Opacity" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Width" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Height" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Depth" font-face="arial" font-size="11"/></node>
</node>
<border dir="col" align="center" grow="1" width="1" flood-events="1">
<node height="20" pad="1" width="100%"><slider-h id="grid-box-opacity"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-box-width" value="0.5"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-box-height" value="0.5"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-box-depth" value="0.5"/></node>
</border>
</node>-->
<border color=".2" height="20" justify="center" align="center"><text text="Box" font-face="arial" font-size="11"/></border>
<border color="1" align="center" pad="5" margin="0 0 5 0"> <border color="1" align="center" pad="5" margin="0 0 5 0">
<image-texture id="grid-heightmap-preview" width="100%" grow="1" height="100" aspect-ratio="1"/> <image-texture id="grid-heightmap-preview" width="100%" grow="1" height="100" aspect-ratio="1"/>
</border> </border>
<node dir="row"> <node dir="row">
<node width="30%" dir="col"> <node width="40%" dir="col">
<node height="20" justify="center"><text text="File" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="File" font-face="arial" font-size="11"/></node>
<node height="30" justify="center"><text text="Shading" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Wireframe" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Height" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="Height" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Offset" font-face="arial" font-size="11"/></node> <node height="20" justify="center"><text text="L-Yaw" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="L-Pitch" font-face="arial" font-size="11"/></node>
</node> </node>
<border dir="col" align="center" grow="1" width="1" flood-events="1"> <border dir="col" align="center" grow="1" width="1" flood-events="1">
<node height="20" pad="1" width="100%" dir="row"> <node height="20" pad="1" width="100%" dir="row">
<node width="20" grow="1" pad="0" margin="0 0 0 2" dir="row"> <node width="20" grow="1" pad="0" margin="0 0 0 2" dir="row">
<button id="grid-heightmap-load" text="..." width="40" height="20"></button> <button id="grid-heightmap-load" text="..." width="20" height="20"></button>
<button id="grid-heightmap-clear" text="Clear" width="50" height="20"></button> <button id="grid-heightmap-clear" text="Clear" width="50" height="20"></button>
<button id="grid-heightmap-reload" text="Reload" width="50" height="20"></button> <button id="grid-heightmap-reload" text="Reload" width="50" height="20"></button>
</node> </node>
</node> </node>
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-height" value="0.5"/></node> <node height="30" pad="1" width="100%" dir="row">
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-offset" value="0.0"/></node> <combobox id="grid-heightmap-shading" text="Normal" width="100%" height="30" combo-list="Transparent,Flat,Solid" default="0"/>
</node>
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-wireframe"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-height" value="0.25"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-lyaw" value="0.5"/></node>
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-lpitch" value="0.5"/></node>
</border> </border>
</node> </node>
@@ -1044,7 +1035,7 @@ Here's a list of what's available in this release.
<button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1"> <button-custom id="menu-about" width="60" height="100%" margin="0 0 0 0" justify="center" align="center" pad="8" color=".1">
<text text="About" font-face="arial" font-size="11"/> <text text="About" font-face="arial" font-size="11"/>
</button-custom> </button-custom>
<!--<button id="btn-anim" width="70" height="100%" margin="1 0 0 10" text="Animate"/>--> <button id="btn-anim" width="70" height="100%" margin="1 0 0 10" text="Animate"/>
<node dir="row" justify="center" grow="1"> <node dir="row" justify="center" grow="1">
<button-custom id="btn-pen" width="50" height="100%" margin="0 0 0 5" thickness="1" border-color="0 0 0 1" pad="2"> <button-custom id="btn-pen" width="50" height="100%" margin="0 0 0 5" thickness="1" border-color="0 0 0 1" pad="2">
<image path="data/ui/pen.png" width="100%" height="100%" align="center" justify="flex-end"/> <image path="data/ui/pen.png" width="100%" height="100%" align="center" justify="flex-end"/>
@@ -1112,11 +1103,9 @@ Here's a list of what's available in this release.
<image path="data/ui/layers.png" width="100%" height="100%" align="center" justify="flex-end"/> <image path="data/ui/layers.png" width="100%" height="100%" align="center" justify="flex-end"/>
</button-custom> </button-custom>
<!--
<button-custom id="btn-grids-panel" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2"> <button-custom id="btn-grids-panel" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2">
<image path="data/ui/grid.png" width="100%" height="100%" align="center" justify="flex-end" mips="true"/> <image path="data/ui/grid.png" width="100%" height="100%" align="center" justify="flex-end" mips="true"/>
</button-custom> </button-custom>
-->
</border> </border>
<!-- side bar --> <!-- side bar -->
@@ -1131,11 +1120,10 @@ Here's a list of what's available in this release.
<!--Colors--> <!--Colors-->
<!--<panel-color id="panel-color"/>--> <!--<panel-color id="panel-color"/>-->
<!--Grids--> <!--Grids-->
<!--<panel-grid/>--> <panel-grid/>
</scroll> </scroll>
</node> </node>
<!-- timeline --> <!-- timeline -->
<!--
<node height="100%" width="1" grow="1" dir="col" justify="flex-start" rtl="ltr"> <node height="100%" width="1" grow="1" dir="col" justify="flex-start" rtl="ltr">
<border color=".3 .3 .3 .4" height="50" width="100%" pad="10" dir="row"> <border color=".3 .3 .3 .4" height="50" width="100%" pad="10" dir="row">
<text text="Timeline: " font-face="arial" font-size="11" margin="8 10 0 0"/> <text text="Timeline: " font-face="arial" font-size="11" margin="8 10 0 0"/>
@@ -1145,7 +1133,6 @@ Here's a list of what's available in this release.
</node> </node>
</border> </border>
</node> </node>
-->
<!--<node height="100%" width="1" grow="1" dir="col" align="center" justify="flex-start" rtl="ltr"> <!--<node height="100%" width="1" grow="1" dir="col" align="center" justify="flex-start" rtl="ltr">
<border border-color="0 0 0 0" thickness="2" color=".2 .2 .2 .6" pad="10" dir="row" margin="2 0 0 0"> <border border-color="0 0 0 0" thickness="2" color=".2 .2 .2 .6" pad="10" dir="row" margin="2 0 0 0">

View File

@@ -123,11 +123,20 @@ void App::init_sidebar()
stroke->create(); stroke->create();
stroke->loaded(); stroke->loaded();
grid = std::make_shared<NodePanelGrid>(); auto grid_find = std::find_if(panels->m_children.begin(), panels->m_children.end(),
grid->m_manager = &layout; [](const std::shared_ptr<Node>&p) { return (bool)std::dynamic_pointer_cast<NodePanelGrid>(p); });
grid->init(); if (grid_find != panels->m_children.end())
grid->create(); {
grid->loaded(); grid = std::static_pointer_cast<NodePanelGrid>(*grid_find);
}
else
{
grid = std::make_shared<NodePanelGrid>();
grid->m_manager = &layout;
grid->init();
grid->create();
grid->loaded();
}
presets = std::make_shared<NodePanelBrushPreset>(); presets = std::make_shared<NodePanelBrushPreset>();
presets->m_manager = &layout; presets->m_manager = &layout;

View File

@@ -485,7 +485,28 @@ void App::initShaders()
"void main(){" "void main(){"
" frag = c;" " frag = c;"
"}"; "}";
// LAMBERT
static const char* shader_lambert_v =
SHADER_VERSION
"uniform mat4 mvp;\n"
"in vec4 pos;\n"
"in vec3 nor;\n"
"out vec3 n;\n"
"void main(){\n"
" n = nor;\n"
" gl_Position = mvp * pos;\n"
"}";
static const char* shader_lambert_f =
SHADER_VERSION
"uniform mediump vec3 light_dir;\n"
"in mediump vec3 n;\n"
"out mediump vec4 frag;\n"
"void main(){\n"
" mediump float d = max(0.0, dot(normalize(n), light_dir));\n"
" frag = vec4(vec3(d), 1.0);\n"
"}";
LOG("initializing shaders"); LOG("initializing shaders");
if (!ShaderManager::create(kShader::Texture, shader_v, shader_f)) if (!ShaderManager::create(kShader::Texture, shader_v, shader_f))
@@ -524,6 +545,8 @@ void App::initShaders()
LOG("Failed to create shader BrushStroke"); LOG("Failed to create shader BrushStroke");
if (!ShaderManager::create(kShader::VertexColor, shader_vertcol_v, shader_vertcol_f)) if (!ShaderManager::create(kShader::VertexColor, shader_vertcol_v, shader_vertcol_f))
LOG("Failed to create shader VertexColor"); LOG("Failed to create shader VertexColor");
if (!ShaderManager::create(kShader::Lambert, shader_lambert_v, shader_lambert_f))
LOG("Failed to create shader Lambert");
LOG("shaders initialized"); LOG("shaders initialized");
} }

View File

@@ -45,7 +45,7 @@ void Image::flip()
std::swap(m_data, flipped); std::swap(m_data, flipped);
} }
Image Image::resize(int w, int h) Image Image::resize(int w, int h) const
{ {
Image ret; Image ret;
ret.create(w, h); ret.create(w, h);

View File

@@ -31,5 +31,5 @@ public:
} }
void flip(); void flip();
void create() { m_data = std::make_unique<uint8_t[]>(size()); } void create() { m_data = std::make_unique<uint8_t[]>(size()); }
Image resize(int w, int h); Image resize(int w, int h) const;
}; };

View File

@@ -188,6 +188,18 @@ public:
return static_cast<T*>(found); return static_cast<T*>(found);
return nullptr; return nullptr;
} }
template<class T = Node> std::shared_ptr<T> find_ref(const char* ids)
{
uint16_t id = const_hash(ids);
for (auto& c : m_children)
{
if (c->m_nodeID == id)
return std::static_pointer_cast<T>(c);
else if (auto found = c->find_ref(ids))
return std::static_pointer_cast<T>(found);
}
return nullptr;
}
template<class T> T* add_child() template<class T> T* add_child()
{ {
auto* n = new T; auto* n = new T;

View File

@@ -290,32 +290,42 @@ void NodeCanvas::draw()
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
bool blend = glIsEnabled(GL_BLEND);
auto mvp = proj * camera
* glm::translate(glm::vec3(0, glm::pow(App::I.grid->m_groud_offset->get_value() - 0.5f, 3), 0))
* glm::scale(glm::vec3(1, glm::pow(App::I.grid->m_hm_height->get_value() - 0.5f, 3.f) * 10.f, 1))
* glm::eulerAngleX(glm::radians(90.f));
// DRAW SOLID
glDisable(GL_BLEND);
ShaderManager::use(kShader::Lambert);
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
auto light_yaw = App::I.grid->m_hm_lyaw->get_value() * glm::pi<float>() * 2.f;
auto light_pitch = App::I.grid->m_hm_lpitch->get_value();
auto light_pos = glm::vec3(sinf(light_yaw), cosf(light_yaw), light_pitch);
ShaderManager::u_vec3(kShaderUniform::LightDir, glm::normalize(-light_pos));
App::I.grid->m_hm_plane.draw_fill();
// DRAW GRIDS // DRAW GRIDS
ShaderManager::use(kShader::Color); if (App::I.grid->m_hm_wireframe->get_value() > 0.f)
// ground grid
int grid_divs = glm::floor(App::I.grid->m_groud_scale->get_value() * 100);
if (grid_divs != m_grid_divs && (grid_divs % 2) == 0)
{ {
m_grid_divs = grid_divs; glEnable(GL_BLEND);
m_grid.create(1, 1, grid_divs); ShaderManager::use(kShader::Color);
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(
glm::vec3(App::I.grid->m_groud_value->get_value()),
App::I.grid->m_groud_opacity->get_value() *
App::I.grid->m_hm_wireframe->get_value()
));
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
//glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
//App::I.grid->m_hm_plane.draw_fill();
//glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
App::I.grid->m_hm_plane.draw_stroke();
} }
float grid_scale = m_grid_divs * 0.01f;
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4( blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glm::vec3(App::I.grid->m_groud_value->get_value()),
App::I.grid->m_groud_opacity->get_value()));
ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera
* glm::translate(glm::vec3(0, glm::pow(App::I.grid->m_groud_height->get_value() - 0.5f, 3), 0))
* glm::eulerAngleX(glm::radians(90.f))
* glm::scale(glm::vec3(grid_scale, grid_scale, 1))
);
//m_grid.draw_stroke();
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
App::I.grid->m_hm_plane.draw_fill();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
App::I.grid->m_hm_plane.draw_stroke();
} }
// box grid // box grid

View File

@@ -25,41 +25,73 @@ void NodePanelGrid::init()
void NodePanelGrid::init_controls() void NodePanelGrid::init_controls()
{ {
m_groud_opacity = find<NodeSliderH>("grid-ground-opacity"); m_groud_opacity = find<NodeSliderH>("grid-ground-opacity");
m_groud_scale = find<NodeSliderH>("grid-ground-scale");
m_groud_value = find<NodeSliderH>("grid-ground-value"); m_groud_value = find<NodeSliderH>("grid-ground-value");
m_groud_height = find<NodeSliderH>("grid-ground-height"); m_groud_resolution = find<NodeSliderH>("grid-ground-resolution");
//m_box_opacity = find<NodeSliderH>("grid-box-opacity"); m_groud_offset = find<NodeSliderH>("grid-ground-offset");
//m_box_width = find<NodeSliderH>("grid-box-width");
//m_box_height = find<NodeSliderH>("grid-box-height");
//m_box_depth = find<NodeSliderH>("grid-box-depth");
auto update_hm = [this](Node* target, float v) {
m_hm_plane.create(1, 1, m_hm_image, -m_hm_height->get_value());
};
m_hm_preview = find<NodeImageTexture>("grid-heightmap-preview"); m_hm_preview = find<NodeImageTexture>("grid-heightmap-preview");
m_hm_load = find<NodeButton>("grid-heightmap-load"); m_hm_load = find<NodeButton>("grid-heightmap-load");
m_hm_offset = find<NodeSliderH>("grid-heightmap-offset"); m_hm_clear = find<NodeButton>("grid-heightmap-clear");
m_hm_reload = find<NodeButton>("grid-heightmap-reload");
m_hm_wireframe = find<NodeSliderH>("grid-heightmap-wireframe");
m_hm_height = find<NodeSliderH>("grid-heightmap-height"); m_hm_height = find<NodeSliderH>("grid-heightmap-height");
m_hm_lyaw = find<NodeSliderH>("grid-heightmap-lyaw");
m_hm_lpitch = find<NodeSliderH>("grid-heightmap-lpitch");
m_hm_height->on_value_changed = update_hm; //m_hm_height->on_value_changed = update_hm;
m_groud_resolution->on_value_changed = [this](Node* target, float v) {
if (m_hm_image.data())
m_hm_plane.create(1, 1, m_hm_image, v * 5.f);
else
m_hm_plane.create(1, 1, 100 * v * 5.f);
LOG("resolution value %f", v);
};
m_hm_preview->SetHeight(0); m_hm_preview->SetHeight(0);
//m_hm_plane.create(1, 1); m_hm_plane.create(1, 1, 100);
m_hm_load->on_click = [this](Node*) { m_hm_load->on_click = [this](Node*) {
App::I.pick_image([this](std::string path) { App::I.pick_image([this](std::string path) {
Image img; Image img;
async_start();
if (img.load_file(path)) if (img.load_file(path))
{ {
m_file_path = path;
m_hm_image = img.resize(128, 128); m_hm_image = img.resize(128, 128);
m_hm_preview->tex.create(m_hm_image); m_hm_preview->tex.create(m_hm_image);
m_hm_preview->tex.create_mipmaps(); m_hm_preview->tex.create_mipmaps();
auto sz = m_hm_preview->tex.size(); auto sz = m_hm_preview->tex.size();
m_hm_preview->SetAspectRatio(sz.x / sz.y); m_hm_preview->SetAspectRatio(sz.x / sz.y);
m_hm_plane.create(1, 1, m_hm_image, -m_hm_height->get_value()); m_hm_plane.create(1, 1, m_hm_image, m_groud_resolution->get_value() * 5.f);
m_hm_preview->SetHeight(100); m_hm_preview->SetHeight(100);
if (m_groud_opacity->get_value() == 0.f)
m_groud_opacity->set_value(1.f);
} }
async_update();
async_end();
}); });
}; };
m_hm_clear->on_click = [this](Node*)
{
m_hm_plane.create(1, 1, 100 * m_groud_resolution->get_value() * 5.f);
m_hm_image.destroy();
m_hm_preview->tex.destroy();
m_hm_preview->SetHeight(0);
};
m_hm_reload->on_click = [this](Node*)
{
Image img;
if (img.load_file(m_file_path))
{
m_hm_image = img.resize(128, 128);
m_hm_preview->tex.create(m_hm_image);
m_hm_preview->tex.create_mipmaps();
auto sz = m_hm_preview->tex.size();
m_hm_preview->SetAspectRatio(sz.x / sz.y);
m_hm_plane.create(1, 1, m_hm_image, m_groud_resolution->get_value() * 5.f);
m_hm_preview->SetHeight(100);
}
};
} }

View File

@@ -14,19 +14,21 @@ class NodePanelGrid : public Node
{ {
public: public:
NodeSliderH* m_groud_opacity; NodeSliderH* m_groud_opacity;
NodeSliderH* m_groud_scale;
NodeSliderH* m_groud_value; NodeSliderH* m_groud_value;
NodeSliderH* m_groud_height; NodeSliderH* m_groud_resolution;
NodeSliderH* m_box_opacity; NodeSliderH* m_groud_offset;
NodeSliderH* m_box_width;
NodeSliderH* m_box_height;
NodeSliderH* m_box_depth;
NodeImageTexture* m_hm_preview; NodeImageTexture* m_hm_preview;
NodeButton* m_hm_load; NodeButton* m_hm_load;
NodeSliderH* m_hm_offset; NodeButton* m_hm_clear;
NodeButton* m_hm_reload;
NodeComboBox* m_hm_shading;
NodeSliderH* m_hm_height; NodeSliderH* m_hm_height;
NodeSliderH* m_hm_wireframe;
NodeSliderH* m_hm_lyaw;
NodeSliderH* m_hm_lpitch;
HeightmapPlane m_hm_plane; HeightmapPlane m_hm_plane;
Image m_hm_image; Image m_hm_image;
std::string m_file_path;
virtual Node* clone_instantiate() const override; virtual Node* clone_instantiate() const override;
virtual void clone_finalize(Node* dest) const override; virtual void clone_finalize(Node* dest) const override;

View File

@@ -107,6 +107,7 @@
#include <glm/gtx/vector_angle.hpp> #include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/intersect.hpp> #include <glm/gtx/intersect.hpp>
#include <glm/gtx/component_wise.hpp> #include <glm/gtx/component_wise.hpp>
#include <glm/gtx/normal.hpp>
#include <tinyxml2.h> #include <tinyxml2.h>
#include <jpge.h> #include <jpge.h>

View File

@@ -75,6 +75,9 @@ bool Shader::create(const char* vertex, const char* fragment)
if (glGetAttribLocation(ps, "col") != -1) if (glGetAttribLocation(ps, "col") != -1)
glBindAttribLocation(ps, 3, "col"); glBindAttribLocation(ps, 3, "col");
if (glGetAttribLocation(ps, "nor") != -1)
glBindAttribLocation(ps, 3, "nor");
glLinkProgram(ps); glLinkProgram(ps);
glGetProgramiv(ps, GL_LINK_STATUS, &status); glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog); glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
@@ -117,6 +120,12 @@ void Shader::u_vec4(kShaderUniform id, const glm::vec4& v)
LOG("UNIFORM vec4 %d NOT FOUND in shader %d", (int)id, (int)name) LOG("UNIFORM vec4 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform4fv(m_umap[id], 1, glm::value_ptr(v)); else glUniform4fv(m_umap[id], 1, glm::value_ptr(v));
} }
void Shader::u_vec3(kShaderUniform id, const glm::vec3& v)
{
if (m_umap.count(id) == 0)
LOG("UNIFORM vec3 %d NOT FOUND in shader %d", (int)id, (int)name)
else glUniform3fv(m_umap[id], 1, glm::value_ptr(v));
}
void Shader::u_vec2(kShaderUniform id, const glm::vec2& v) void Shader::u_vec2(kShaderUniform id, const glm::vec2& v)
{ {
@@ -171,6 +180,11 @@ void ShaderManager::u_vec4(kShaderUniform id, const glm::vec4& v)
m_current->u_vec4(id, v); m_current->u_vec4(id, v);
} }
void ShaderManager::u_vec3(kShaderUniform id, const glm::vec3& v)
{
m_current->u_vec3(id, v);
}
void ShaderManager::u_vec2(kShaderUniform id, const glm::vec2& v) void ShaderManager::u_vec2(kShaderUniform id, const glm::vec2& v)
{ {
m_current->u_vec2(id, v); m_current->u_vec2(id, v);

View File

@@ -29,6 +29,7 @@ enum class kShaderUniform : uint16_t
Noise = const_hash("noise"), Noise = const_hash("noise"),
Direction = const_hash("dir"), Direction = const_hash("dir"),
UseFragCoordUV2 = const_hash("fragUV2"), UseFragCoordUV2 = const_hash("fragUV2"),
LightDir = const_hash("light_dir"),
}; };
enum class kShader : uint16_t enum class kShader : uint16_t
@@ -52,6 +53,7 @@ enum class kShader : uint16_t
Equirect = const_hash("equirect"), Equirect = const_hash("equirect"),
BrushStroke = const_hash("brush-stroke"), BrushStroke = const_hash("brush-stroke"),
VertexColor = const_hash("vertex-color"), VertexColor = const_hash("vertex-color"),
Lambert = const_hash("lambert"),
}; };
class Shader class Shader
@@ -63,6 +65,7 @@ public:
bool create(const char* vertex, const char* fragment); bool create(const char* vertex, const char* fragment);
void use(); void use();
void u_vec4(kShaderUniform id, const glm::vec4& v); void u_vec4(kShaderUniform id, const glm::vec4& v);
void u_vec3(kShaderUniform id, const glm::vec3& v);
void u_vec2(kShaderUniform id, const glm::vec2& v); void u_vec2(kShaderUniform id, const glm::vec2& v);
void u_mat4(kShaderUniform id, const glm::mat4& m); void u_mat4(kShaderUniform id, const glm::mat4& m);
void u_int(kShaderUniform id, int i); void u_int(kShaderUniform id, int i);
@@ -80,6 +83,7 @@ public:
static void use(const char* name); static void use(const char* name);
static Shader* get(kShader id); static Shader* get(kShader id);
static void u_vec4(kShaderUniform id, const glm::vec4& v); static void u_vec4(kShaderUniform id, const glm::vec4& v);
static void u_vec3(kShaderUniform id, const glm::vec3& v);
static void u_vec2(kShaderUniform id, const glm::vec2& v); static void u_vec2(kShaderUniform id, const glm::vec2& v);
static void u_mat4(kShaderUniform id, const glm::mat4& m); static void u_mat4(kShaderUniform id, const glm::mat4& m);
static void u_int(kShaderUniform id, int i); static void u_int(kShaderUniform id, int i);

View File

@@ -43,11 +43,13 @@ bool Shape::create_buffers_imp(GLvoid* idx, GLvoid* vertices, int isize, int vsi
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2)); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
} }
glBindVertexArray(0); glBindVertexArray(0);
#endif #endif
@@ -81,10 +83,12 @@ bool Shape::create_buffers(GLvoid* vertices, int vsize)
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2)); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
} }
glBindVertexArray(0); glBindVertexArray(0);
#endif #endif
@@ -239,20 +243,29 @@ void Plane::create_impl(float w, float h, int div, GLushort *idx, vertex_t *vert
bool HeightmapPlane::create(float w, float h, const Image& img, float scale) bool HeightmapPlane::create(float w, float h, const Image& img, float scale)
{ {
int div = img.width - 1; // TODO: handle height also Image img_tmp;
glm::u8vec4* px = (glm::u8vec4*)img.data();
glm::vec2 new_size = glm::clamp(glm::ceil(glm::vec2(img.width, img.height) * scale), { 16, 16 }, glm::vec2(8192));
if (scale != 1.f)
{
img_tmp = img.resize(new_size.x, new_size.y);
px = (glm::u8vec4*)img_tmp.data();
}
int div = new_size.x - 1; // TODO: handle height also
int idx_size = (div * div * 6) + (div * (div + 1) * 4); int idx_size = (div * div * 6) + (div * (div + 1) * 4);
int vertices_size = (div + 1)*(div + 1); int vertices_size = (div + 1)*(div + 1);
auto idx = std::make_unique<GLuint[]>(idx_size); std::vector<GLuint> idx(idx_size);
auto vertices = std::make_unique<vertex_t[]>(vertices_size); std::vector<vertex_t> vertices(vertices_size);
std::vector<int> nor_count((size_t)vertices_size, 0);
count[0] = div * div * 6; count[0] = div * div * 6;
count[1] = div * (div + 1) * 4; count[1] = div * (div + 1) * 4;
ioff[0] = (GLvoid*)0; ioff[0] = (GLvoid*)0;
ioff[1] = (GLvoid*)(count[0] * sizeof(GLuint)); ioff[1] = (GLvoid*)(count[0] * sizeof(GLuint));
auto pv = vertices.get(); auto pv = vertices.data();
auto pi = idx.get(); auto pi = idx.data();
auto px = (glm::u8vec4*)img.data();
const float dx = w / div; const float dx = w / div;
const float dy = h / div; const float dy = h / div;
@@ -265,13 +278,99 @@ bool HeightmapPlane::create(float w, float h, const Image& img, float scale)
vertex_t v; vertex_t v;
v.pos.x = ox + dx * (float)x; v.pos.x = ox + dx * (float)x;
v.pos.y = oy + dy * (float)y; v.pos.y = oy + dy * (float)y;
v.pos.z = (*px++).r / 255.f * scale; v.pos.z = (*px++).r / 255.f;
v.pos.w = 1; v.pos.w = 1;
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div; v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
*pv++ = v; *pv++ = v;
} }
} }
// generate indices
for (int y = 0; y < div; y++)
{
int i = y * (div + 1);
for (int x = 0; x < div; x++)
{
*pi++ = i;
*pi++ = i + div + 1;
*pi++ = i + div + 2;
*pi++ = i;
*pi++ = i + div + 2;
*pi++ = i + 1;
auto n = glm::triangleNormal(xyz(vertices[i].pos),
xyz(vertices[i + div + 1].pos), xyz(vertices[i + 1].pos));
vertices[i].nor += n;
vertices[i + 1].nor += n;
vertices[i + div + 1].nor += n;
vertices[i + div + 2].nor += n;
nor_count[i]++;
nor_count[i + 1]++;
nor_count[i + div + 1]++;
nor_count[i + div + 2]++;
i++;
}
}
for (int i = 0; i < vertices_size; i++)
vertices[i].nor /= (float)nor_count[i];
// generate indices
for (int y = 0; y <= div; y++)
{
//int i = y * (div + 1);
for (int x = 0; x <= div; x++)
{
if (x < div)
{
*pi++ = y * (div + 1) + x;
*pi++ = y * (div + 1) + x + 1;
}
if (y < div)
{
*pi++ = y * (div + 1) + x;
*pi++ = (y + 1) * (div + 1) + x;
}
}
}
return create_buffers(idx.data(), vertices.data(), sizeof(GLuint) * idx_size, sizeof(vertex_t) * vertices_size);
}
bool HeightmapPlane::create(float w, float h, int div)
{
int idx_size = (div * div * 6) + (div * (div + 1) * 4);
int vertices_size = (div + 1)*(div + 1);
auto idx = std::make_unique<GLuint[]>(idx_size);
auto vertices = std::make_unique<vertex_t[]>(vertices_size);
count[0] = div * div * 6;
count[1] = div * (div + 1) * 4;
ioff[0] = (GLvoid*)0;
ioff[1] = (GLvoid*)(count[0] * sizeof(GLuint));
auto pv = vertices.get();
auto pi = idx.get();
const float dx = w / div;
const float dy = h / div;
const float ox = -w * 0.5f;
const float oy = -h * 0.5f;
for (int y = 0; y <= div; y++)
{
for (int x = 0; x <= div; x++)
{
vertex_t v;
v.pos.x = ox + dx * (float)x;
v.pos.y = oy + dy * (float)y;
v.pos.z = 0.f;
v.pos.w = 1.f;
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
v.nor = { 0, 1, 0 };
*pv++ = v;
}
}
// generate indices // generate indices
for (int y = 0; y < div; y++) for (int y = 0; y < div; y++)
{ {

View File

@@ -126,6 +126,7 @@ class HeightmapPlane : public Shape
{ {
public: public:
bool create(float w, float h, const Image& img, float scale); bool create(float w, float h, const Image& img, float scale);
bool create(float w, float h, int div);
}; };
class RectShape : public Shape class RectShape : public Shape

View File

@@ -39,6 +39,7 @@ void TextureManager::invalidate()
bool Texture2D::create(int width, int height, GLint internal_format, GLint format, const uint8_t* data) bool Texture2D::create(int width, int height, GLint internal_format, GLint format, const uint8_t* data)
{ {
destroy();
m_width = width; m_width = width;
m_height = height; m_height = height;
m_format = format; m_format = format;

View File

@@ -11,14 +11,15 @@ struct vertex_t
glm::vec4 pos; glm::vec4 pos;
glm::vec2 uvs; glm::vec2 uvs;
glm::vec2 uvs2; glm::vec2 uvs2;
vertex_t() : pos(0), uvs(0), uvs2(0) {} glm::vec3 nor;
vertex_t(glm::vec2 p) : pos(p, 0, 1), uvs(0), uvs2(0) {} vertex_t() : pos(0), uvs(0), uvs2(0), nor(0) {}
vertex_t(glm::vec2 p, glm::vec2 uv) : pos(p, 0, 1), uvs(uv), uvs2(0) {} vertex_t(glm::vec2 p) : pos(p, 0, 1), uvs(0), uvs2(0), nor(0) {}
vertex_t(glm::vec3 p) : pos(p, 1), uvs(0), uvs2(0) {} vertex_t(glm::vec2 p, glm::vec2 uv) : pos(p, 0, 1), uvs(uv), uvs2(0), nor(0) {}
vertex_t(glm::vec3 p, glm::vec2 uv) : pos(p, 1), uvs(uv), uvs2(0) {} vertex_t(glm::vec3 p) : pos(p, 1), uvs(0), uvs2(0), nor(0) {}
vertex_t(glm::vec4 p) : pos(p), uvs(0), uvs2(0) {} vertex_t(glm::vec3 p, glm::vec2 uv) : pos(p, 1), uvs(uv), uvs2(0), nor(0) {}
vertex_t(glm::vec4 p, glm::vec2 uv) : pos(p), uvs(uv), uvs2(0) {} vertex_t(glm::vec4 p) : pos(p), uvs(0), uvs2(0), nor(0) {}
vertex_t(glm::vec4 p, glm::vec2 uv, glm::vec2 uv2) : pos(p), uvs(uv), uvs2(uv2) {} vertex_t(glm::vec4 p, glm::vec2 uv) : pos(p), uvs(uv), uvs2(0), nor(0) {}
vertex_t(glm::vec4 p, glm::vec2 uv, glm::vec2 uv2) : pos(p), uvs(uv), uvs2(uv2), nor(0) {}
}; };
uint16_t constexpr const_hash(const char* input) uint16_t constexpr const_hash(const char* input)