implement grid and heightmap with lambert shading
This commit is contained in:
@@ -248,58 +248,49 @@
|
||||
</border>
|
||||
<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 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="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="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>
|
||||
<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-scale" value="0.5"/></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-height" 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-resolution" value="0.2"/></node>
|
||||
<node height="20" pad="1" width="100%"><slider-h id="grid-ground-offset" value="0.25"/></node>
|
||||
</border>
|
||||
</node>
|
||||
|
||||
<!--<border color=".2" height="20" justify="center" align="center"><text text="Box" 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>
|
||||
<node height="10"/>
|
||||
<border color=".2" height="20" justify="center" align="center"><text text="Heightmap" font-face="arial" font-size="11"/></border>
|
||||
<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"/>
|
||||
</border>
|
||||
<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="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="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>
|
||||
<border dir="col" align="center" grow="1" width="1" flood-events="1">
|
||||
<node height="20" pad="1" width="100%" 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-reload" text="Reload" width="50" height="20"></button>
|
||||
</node>
|
||||
</node>
|
||||
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-height" value="0.5"/></node>
|
||||
<node height="20" pad="1" width="100%"><slider-h id="grid-heightmap-offset" value="0.0"/></node>
|
||||
<node height="30" pad="1" width="100%" dir="row">
|
||||
<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>
|
||||
</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">
|
||||
<text text="About" font-face="arial" font-size="11"/>
|
||||
</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">
|
||||
<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"/>
|
||||
@@ -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"/>
|
||||
</button-custom>
|
||||
|
||||
<!--
|
||||
<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"/>
|
||||
</button-custom>
|
||||
-->
|
||||
|
||||
</border>
|
||||
<!-- side bar -->
|
||||
@@ -1131,11 +1120,10 @@ Here's a list of what's available in this release.
|
||||
<!--Colors-->
|
||||
<!--<panel-color id="panel-color"/>-->
|
||||
<!--Grids-->
|
||||
<!--<panel-grid/>-->
|
||||
<panel-grid/>
|
||||
</scroll>
|
||||
</node>
|
||||
<!-- timeline -->
|
||||
<!--
|
||||
<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">
|
||||
<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>
|
||||
</border>
|
||||
</node>
|
||||
-->
|
||||
|
||||
<!--<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">
|
||||
|
||||
@@ -123,11 +123,20 @@ void App::init_sidebar()
|
||||
stroke->create();
|
||||
stroke->loaded();
|
||||
|
||||
grid = std::make_shared<NodePanelGrid>();
|
||||
grid->m_manager = &layout;
|
||||
grid->init();
|
||||
grid->create();
|
||||
grid->loaded();
|
||||
auto grid_find = std::find_if(panels->m_children.begin(), panels->m_children.end(),
|
||||
[](const std::shared_ptr<Node>&p) { return (bool)std::dynamic_pointer_cast<NodePanelGrid>(p); });
|
||||
if (grid_find != panels->m_children.end())
|
||||
{
|
||||
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->m_manager = &layout;
|
||||
|
||||
@@ -486,6 +486,27 @@ void App::initShaders()
|
||||
" 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");
|
||||
if (!ShaderManager::create(kShader::Texture, shader_v, shader_f))
|
||||
@@ -524,6 +545,8 @@ void App::initShaders()
|
||||
LOG("Failed to create shader BrushStroke");
|
||||
if (!ShaderManager::create(kShader::VertexColor, shader_vertcol_v, shader_vertcol_f))
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void Image::flip()
|
||||
std::swap(m_data, flipped);
|
||||
}
|
||||
|
||||
Image Image::resize(int w, int h)
|
||||
Image Image::resize(int w, int h) const
|
||||
{
|
||||
Image ret;
|
||||
ret.create(w, h);
|
||||
|
||||
@@ -31,5 +31,5 @@ public:
|
||||
}
|
||||
void flip();
|
||||
void create() { m_data = std::make_unique<uint8_t[]>(size()); }
|
||||
Image resize(int w, int h);
|
||||
Image resize(int w, int h) const;
|
||||
};
|
||||
|
||||
12
src/node.h
12
src/node.h
@@ -188,6 +188,18 @@ public:
|
||||
return static_cast<T*>(found);
|
||||
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()
|
||||
{
|
||||
auto* n = new T;
|
||||
|
||||
@@ -290,32 +290,42 @@ void NodeCanvas::draw()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
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
|
||||
ShaderManager::use(kShader::Color);
|
||||
|
||||
// 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)
|
||||
if (App::I.grid->m_hm_wireframe->get_value() > 0.f)
|
||||
{
|
||||
m_grid_divs = grid_divs;
|
||||
m_grid.create(1, 1, grid_divs);
|
||||
glEnable(GL_BLEND);
|
||||
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(
|
||||
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();
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
// box grid
|
||||
|
||||
@@ -25,41 +25,73 @@ void NodePanelGrid::init()
|
||||
void NodePanelGrid::init_controls()
|
||||
{
|
||||
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_height = find<NodeSliderH>("grid-ground-height");
|
||||
//m_box_opacity = find<NodeSliderH>("grid-box-opacity");
|
||||
//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_groud_resolution = find<NodeSliderH>("grid-ground-resolution");
|
||||
m_groud_offset = find<NodeSliderH>("grid-ground-offset");
|
||||
|
||||
m_hm_preview = find<NodeImageTexture>("grid-heightmap-preview");
|
||||
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_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_plane.create(1, 1);
|
||||
m_hm_plane.create(1, 1, 100);
|
||||
|
||||
m_hm_load->on_click = [this](Node*) {
|
||||
App::I.pick_image([this](std::string path) {
|
||||
Image img;
|
||||
async_start();
|
||||
if (img.load_file(path))
|
||||
{
|
||||
m_file_path = 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_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);
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,19 +14,21 @@ class NodePanelGrid : public Node
|
||||
{
|
||||
public:
|
||||
NodeSliderH* m_groud_opacity;
|
||||
NodeSliderH* m_groud_scale;
|
||||
NodeSliderH* m_groud_value;
|
||||
NodeSliderH* m_groud_height;
|
||||
NodeSliderH* m_box_opacity;
|
||||
NodeSliderH* m_box_width;
|
||||
NodeSliderH* m_box_height;
|
||||
NodeSliderH* m_box_depth;
|
||||
NodeSliderH* m_groud_resolution;
|
||||
NodeSliderH* m_groud_offset;
|
||||
NodeImageTexture* m_hm_preview;
|
||||
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_wireframe;
|
||||
NodeSliderH* m_hm_lyaw;
|
||||
NodeSliderH* m_hm_lpitch;
|
||||
HeightmapPlane m_hm_plane;
|
||||
Image m_hm_image;
|
||||
std::string m_file_path;
|
||||
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_finalize(Node* dest) const override;
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <glm/gtx/intersect.hpp>
|
||||
#include <glm/gtx/component_wise.hpp>
|
||||
#include <glm/gtx/normal.hpp>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <jpge.h>
|
||||
|
||||
@@ -75,6 +75,9 @@ bool Shader::create(const char* vertex, const char* fragment)
|
||||
if (glGetAttribLocation(ps, "col") != -1)
|
||||
glBindAttribLocation(ps, 3, "col");
|
||||
|
||||
if (glGetAttribLocation(ps, "nor") != -1)
|
||||
glBindAttribLocation(ps, 3, "nor");
|
||||
|
||||
glLinkProgram(ps);
|
||||
glGetProgramiv(ps, GL_LINK_STATUS, &status);
|
||||
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)
|
||||
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)
|
||||
{
|
||||
@@ -171,6 +180,11 @@ void ShaderManager::u_vec4(kShaderUniform id, const glm::vec4& 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)
|
||||
{
|
||||
m_current->u_vec2(id, v);
|
||||
|
||||
@@ -29,6 +29,7 @@ enum class kShaderUniform : uint16_t
|
||||
Noise = const_hash("noise"),
|
||||
Direction = const_hash("dir"),
|
||||
UseFragCoordUV2 = const_hash("fragUV2"),
|
||||
LightDir = const_hash("light_dir"),
|
||||
};
|
||||
|
||||
enum class kShader : uint16_t
|
||||
@@ -52,6 +53,7 @@ enum class kShader : uint16_t
|
||||
Equirect = const_hash("equirect"),
|
||||
BrushStroke = const_hash("brush-stroke"),
|
||||
VertexColor = const_hash("vertex-color"),
|
||||
Lambert = const_hash("lambert"),
|
||||
};
|
||||
|
||||
class Shader
|
||||
@@ -63,6 +65,7 @@ public:
|
||||
bool create(const char* vertex, const char* fragment);
|
||||
void use();
|
||||
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_mat4(kShaderUniform id, const glm::mat4& m);
|
||||
void u_int(kShaderUniform id, int i);
|
||||
@@ -80,6 +83,7 @@ public:
|
||||
static void use(const char* name);
|
||||
static Shader* get(kShader id);
|
||||
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_mat4(kShaderUniform id, const glm::mat4& m);
|
||||
static void u_int(kShaderUniform id, int i);
|
||||
|
||||
113
src/shape.cpp
113
src/shape.cpp
@@ -43,11 +43,13 @@ bool Shape::create_buffers_imp(GLvoid* idx, GLvoid* vertices, int isize, int vsi
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[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(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);
|
||||
#endif
|
||||
@@ -81,10 +83,12 @@ bool Shape::create_buffers(GLvoid* vertices, int vsize)
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffers[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(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);
|
||||
#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)
|
||||
{
|
||||
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 vertices_size = (div + 1)*(div + 1);
|
||||
auto idx = std::make_unique<GLuint[]>(idx_size);
|
||||
auto vertices = std::make_unique<vertex_t[]>(vertices_size);
|
||||
std::vector<GLuint> idx(idx_size);
|
||||
std::vector<vertex_t> vertices(vertices_size);
|
||||
std::vector<int> nor_count((size_t)vertices_size, 0);
|
||||
|
||||
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();
|
||||
auto px = (glm::u8vec4*)img.data();
|
||||
auto pv = vertices.data();
|
||||
auto pi = idx.data();
|
||||
|
||||
const float dx = w / 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;
|
||||
v.pos.x = ox + dx * (float)x;
|
||||
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.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
|
||||
*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
|
||||
for (int y = 0; y < div; y++)
|
||||
{
|
||||
|
||||
@@ -126,6 +126,7 @@ class HeightmapPlane : public Shape
|
||||
{
|
||||
public:
|
||||
bool create(float w, float h, const Image& img, float scale);
|
||||
bool create(float w, float h, int div);
|
||||
};
|
||||
|
||||
class RectShape : public Shape
|
||||
|
||||
@@ -39,6 +39,7 @@ void TextureManager::invalidate()
|
||||
|
||||
bool Texture2D::create(int width, int height, GLint internal_format, GLint format, const uint8_t* data)
|
||||
{
|
||||
destroy();
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_format = format;
|
||||
|
||||
17
src/util.h
17
src/util.h
@@ -11,14 +11,15 @@ struct vertex_t
|
||||
glm::vec4 pos;
|
||||
glm::vec2 uvs;
|
||||
glm::vec2 uvs2;
|
||||
vertex_t() : pos(0), uvs(0), uvs2(0) {}
|
||||
vertex_t(glm::vec2 p) : pos(p, 0, 1), uvs(0), uvs2(0) {}
|
||||
vertex_t(glm::vec2 p, glm::vec2 uv) : pos(p, 0, 1), uvs(uv), uvs2(0) {}
|
||||
vertex_t(glm::vec3 p) : pos(p, 1), uvs(0), uvs2(0) {}
|
||||
vertex_t(glm::vec3 p, glm::vec2 uv) : pos(p, 1), uvs(uv), uvs2(0) {}
|
||||
vertex_t(glm::vec4 p) : pos(p), uvs(0), uvs2(0) {}
|
||||
vertex_t(glm::vec4 p, glm::vec2 uv) : pos(p), uvs(uv), uvs2(0) {}
|
||||
vertex_t(glm::vec4 p, glm::vec2 uv, glm::vec2 uv2) : pos(p), uvs(uv), uvs2(uv2) {}
|
||||
glm::vec3 nor;
|
||||
vertex_t() : pos(0), uvs(0), uvs2(0), nor(0) {}
|
||||
vertex_t(glm::vec2 p) : pos(p, 0, 1), uvs(0), uvs2(0), nor(0) {}
|
||||
vertex_t(glm::vec2 p, glm::vec2 uv) : pos(p, 0, 1), uvs(uv), uvs2(0), nor(0) {}
|
||||
vertex_t(glm::vec3 p) : pos(p, 1), uvs(0), uvs2(0), nor(0) {}
|
||||
vertex_t(glm::vec3 p, glm::vec2 uv) : pos(p, 1), uvs(uv), uvs2(0), nor(0) {}
|
||||
vertex_t(glm::vec4 p) : pos(p), uvs(0), uvs2(0), nor(0) {}
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user