Implement raytraced lightmap
This commit is contained in:
@@ -292,7 +292,7 @@
|
|||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node height="30" pad="1" width="100%" dir="row" margin="5 0 0 0">
|
<node height="30" pad="1" width="100%" dir="row" margin="5 0 0 0">
|
||||||
<combobox id="grid-heightmap-shading" width="100%" height="30" combo-list="Transparent,Flat,Solid" default="0"/>
|
<combobox id="grid-heightmap-shading" width="100%" height="30" combo-list="Transparent,Flat,Solid,Textured" default="0"/>
|
||||||
</node>
|
</node>
|
||||||
<node height="20" pad="1" width="100%" margin="5 0 0 0"><slider-h id="grid-heightmap-wireframe" value="1.0"/></node>
|
<node height="20" pad="1" width="100%" margin="5 0 0 0"><slider-h id="grid-heightmap-wireframe" value="1.0"/></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-height" value="0.25"/></node>
|
||||||
@@ -301,6 +301,7 @@
|
|||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<button id="grid-render" text="Render" height="30" margin="5 0 0 0"/>
|
<button id="grid-render" text="Render" height="30" margin="5 0 0 0"/>
|
||||||
|
<button id="grid-commit" text="Commit" height="30" margin="5 0 0 0"/>
|
||||||
|
|
||||||
</border>
|
</border>
|
||||||
</node>
|
</node>
|
||||||
|
|||||||
@@ -328,7 +328,10 @@ void App::init()
|
|||||||
LOG("OPENGL: %.*s", length, message);
|
LOG("OPENGL: %.*s", length, message);
|
||||||
FlushConsoleInputBuffer(GetStdHandle(STD_OUTPUT_HANDLE));
|
FlushConsoleInputBuffer(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), info.wAttributes);
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), info.wAttributes);
|
||||||
//__debugbreak();
|
#ifdef _WIN32
|
||||||
|
if (severity == GL_DEBUG_SEVERITY_HIGH)
|
||||||
|
__debugbreak();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}, nullptr);
|
}, nullptr);
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
|||||||
@@ -509,6 +509,7 @@ void App::initShaders()
|
|||||||
"uniform mat4 mvp;\n"
|
"uniform mat4 mvp;\n"
|
||||||
"in vec4 pos;\n"
|
"in vec4 pos;\n"
|
||||||
"in vec3 nor;\n"
|
"in vec3 nor;\n"
|
||||||
|
"in vec2 uvs;\n"
|
||||||
"out vec3 n;\n"
|
"out vec3 n;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" n = nor;\n"
|
" n = nor;\n"
|
||||||
@@ -522,6 +523,61 @@ void App::initShaders()
|
|||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" mediump float d = max(0.0, dot(normalize(n), light_dir));\n"
|
" mediump float d = max(0.0, dot(normalize(n), light_dir));\n"
|
||||||
" frag = vec4(vec3(d), 1.0);\n"
|
" frag = vec4(vec3(d), 1.0);\n"
|
||||||
|
//" frag = vec4(normalize(n) * 0.5 + 0.5, 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
// LAMBERT LIGHTMAP
|
||||||
|
static const char* shader_lambert_lightmap_v =
|
||||||
|
SHADER_VERSION
|
||||||
|
"uniform mat4 mvp;\n"
|
||||||
|
"in vec4 pos;\n"
|
||||||
|
"in vec3 nor;\n"
|
||||||
|
"in vec2 uvs;\n"
|
||||||
|
"out vec3 n;\n"
|
||||||
|
"out vec2 uv;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" n = nor;\n"
|
||||||
|
" uv = uvs;\n"
|
||||||
|
" gl_Position = mvp * pos;\n"
|
||||||
|
"}\n";
|
||||||
|
static const char* shader_lambert_lightmap_f =
|
||||||
|
SHADER_VERSION
|
||||||
|
"uniform mediump sampler2D tex;\n"
|
||||||
|
"uniform mediump vec3 light_dir;\n"
|
||||||
|
"in mediump vec3 n;\n"
|
||||||
|
"in mediump vec2 uv;\n"
|
||||||
|
"out mediump vec4 frag;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" mediump float d = max(0.0, dot(normalize(n), light_dir));\n"
|
||||||
|
" mediump vec4 c = texture(tex, uv);\n"
|
||||||
|
" frag = vec4(c.rgb * d, 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
// BAKE UVS
|
||||||
|
static const char* shader_bakeuv_v =
|
||||||
|
SHADER_VERSION
|
||||||
|
"uniform mat4 mvp;\n"
|
||||||
|
"in vec4 pos;\n"
|
||||||
|
"in vec3 nor;\n"
|
||||||
|
"in vec2 uvs;\n"
|
||||||
|
"out vec3 n;\n"
|
||||||
|
"out vec3 p;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" n = nor;\n"
|
||||||
|
" p = vec3(mvp * pos);\n"
|
||||||
|
" gl_Position = vec4(uvs * 2.0 - 1.0, 0.0, 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
static const char* shader_bakeuv_f =
|
||||||
|
SHADER_VERSION
|
||||||
|
"uniform int mode;\n"
|
||||||
|
"in highp vec3 n;\n"
|
||||||
|
"in highp vec3 p;\n"
|
||||||
|
"out highp vec3 frag;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" switch(mode) {\n"
|
||||||
|
" case 0: frag = normalize(n); break;\n"
|
||||||
|
" case 1: frag = p; break;\n"
|
||||||
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
|
||||||
@@ -566,6 +622,10 @@ void App::initShaders()
|
|||||||
LOG("Failed to create shader VertexColor");
|
LOG("Failed to create shader VertexColor");
|
||||||
if (!ShaderManager::create(kShader::Lambert, shader_lambert_v, shader_lambert_f))
|
if (!ShaderManager::create(kShader::Lambert, shader_lambert_v, shader_lambert_f))
|
||||||
LOG("Failed to create shader Lambert");
|
LOG("Failed to create shader Lambert");
|
||||||
|
if (!ShaderManager::create(kShader::LambertLightmap, shader_lambert_lightmap_v, shader_lambert_lightmap_f))
|
||||||
|
LOG("Failed to create shader LambertLightmap");
|
||||||
|
if (!ShaderManager::create(kShader::BakeUV, shader_bakeuv_v, shader_bakeuv_f))
|
||||||
|
LOG("Failed to create shader BakeUV");
|
||||||
LOG("shaders initialized");
|
LOG("shaders initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ void NodePanelGrid::init_controls()
|
|||||||
m_hm_lpitch = find<NodeSliderH>("grid-heightmap-lpitch");
|
m_hm_lpitch = find<NodeSliderH>("grid-heightmap-lpitch");
|
||||||
m_hm_shading = find<NodeComboBox>("grid-heightmap-shading");
|
m_hm_shading = find<NodeComboBox>("grid-heightmap-shading");
|
||||||
m_render = find<NodeButton>("grid-render");
|
m_render = find<NodeButton>("grid-render");
|
||||||
|
m_commit = find<NodeButton>("grid-commit");
|
||||||
|
|
||||||
m_hm_preview->SetHeight(0);
|
m_hm_preview->SetHeight(0);
|
||||||
m_hm_plane.create(1, 1, 100);
|
m_hm_plane.create(1, 1, 100);
|
||||||
@@ -49,12 +50,14 @@ void NodePanelGrid::init_controls()
|
|||||||
m_hm_plane.create(1, 1, m_hm_image, v * 5.f, get_height());
|
m_hm_plane.create(1, 1, m_hm_image, v * 5.f, get_height());
|
||||||
else
|
else
|
||||||
m_hm_plane.create(1, 1, 100 * v * 5.f);
|
m_hm_plane.create(1, 1, 100 * v * 5.f);
|
||||||
|
m_rt_dirty = true;
|
||||||
LOG("resolution value %f", v);
|
LOG("resolution value %f", v);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_hm_height->on_value_final = [this](Node* target, float v) {
|
m_hm_height->on_value_final = [this](Node* target, float v) {
|
||||||
if (m_hm_image.data())
|
if (m_hm_image.data())
|
||||||
m_hm_plane.create(1, 1, m_hm_image, m_groud_resolution->get_value() * 5.f, get_height());
|
m_hm_plane.create(1, 1, m_hm_image, m_groud_resolution->get_value() * 5.f, get_height());
|
||||||
|
m_rt_dirty = true;
|
||||||
LOG("height value %f", v);
|
LOG("height value %f", v);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,6 +82,7 @@ void NodePanelGrid::init_controls()
|
|||||||
m_hm_preview->SetHeight(100);
|
m_hm_preview->SetHeight(100);
|
||||||
if (m_groud_opacity->get_value() == 0.f)
|
if (m_groud_opacity->get_value() == 0.f)
|
||||||
m_groud_opacity->set_value(1.f);
|
m_groud_opacity->set_value(1.f);
|
||||||
|
m_rt_dirty = true;
|
||||||
}
|
}
|
||||||
async_update();
|
async_update();
|
||||||
async_end();
|
async_end();
|
||||||
@@ -106,18 +110,31 @@ void NodePanelGrid::init_controls()
|
|||||||
m_hm_plane.create(1, 1, m_hm_image,
|
m_hm_plane.create(1, 1, m_hm_image,
|
||||||
m_groud_resolution->get_value() * 5.f, get_height());
|
m_groud_resolution->get_value() * 5.f, get_height());
|
||||||
m_hm_preview->SetHeight(100);
|
m_hm_preview->SetHeight(100);
|
||||||
|
m_rt_dirty = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_render->on_click = [this](Node*)
|
m_render->on_click = [this](Node*)
|
||||||
|
{
|
||||||
|
gl_state gl;
|
||||||
|
gl.save();
|
||||||
|
bake_uvs();
|
||||||
|
m_hm_shading->set_index(3);
|
||||||
|
m_shade_mode = ShadeMode::Textured;
|
||||||
|
gl.restore();
|
||||||
|
};
|
||||||
|
m_commit->on_click = [this](Node*)
|
||||||
{
|
{
|
||||||
gl_state gl;
|
gl_state gl;
|
||||||
gl.save();
|
gl.save();
|
||||||
Canvas::I->draw_objects([this](const glm::mat4& camera, const glm::mat4& proj, int i) {
|
Canvas::I->draw_objects([this](const glm::mat4& camera, const glm::mat4& proj, int i) {
|
||||||
draw_heightmap(proj, camera);
|
draw_heightmap(proj, camera);
|
||||||
});
|
});
|
||||||
|
m_groud_opacity->set_value(0);
|
||||||
gl.restore();
|
gl.restore();
|
||||||
};
|
};
|
||||||
|
m_texture.create(1024, 1024);
|
||||||
|
m_sampler_linear.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
float NodePanelGrid::get_height() const
|
float NodePanelGrid::get_height() const
|
||||||
@@ -134,27 +151,26 @@ void NodePanelGrid::draw_heightmap(const glm::mat4& proj, const glm::mat4& camer
|
|||||||
{
|
{
|
||||||
if (m_groud_opacity->get_value() > 0.f)
|
if (m_groud_opacity->get_value() > 0.f)
|
||||||
{
|
{
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
auto mvp = proj * camera
|
auto mvp = proj * camera
|
||||||
* glm::translate(glm::vec3(0, get_offset(), 0))
|
* glm::translate(glm::vec3(0, get_offset(), 0));
|
||||||
* glm::scale(glm::vec3(1, get_height(), 1))
|
|
||||||
* glm::eulerAngleX(glm::radians(90.f));
|
|
||||||
|
|
||||||
// DRAW SOLID
|
// DRAW SOLID
|
||||||
if (m_hm_image.m_data)
|
if (m_hm_image.m_data)
|
||||||
{
|
{
|
||||||
|
auto light_yaw = m_hm_lyaw->get_value() * glm::pi<float>() * 2.f;
|
||||||
|
auto light_pitch = m_hm_lpitch->get_value() * 5;
|
||||||
|
auto light_pos = glm::vec3(sinf(light_yaw), light_pitch, cosf(light_yaw));
|
||||||
|
auto light_dir = glm::normalize(light_pos);
|
||||||
|
|
||||||
if (m_shade_mode == ShadeMode::Solid)
|
if (m_shade_mode == ShadeMode::Solid)
|
||||||
{
|
{
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
ShaderManager::use(kShader::Lambert);
|
ShaderManager::use(kShader::Lambert);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
||||||
auto light_yaw = m_hm_lyaw->get_value() * glm::pi<float>() * 2.f;
|
ShaderManager::u_vec3(kShaderUniform::LightDir, light_dir);
|
||||||
auto light_pitch = 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));
|
|
||||||
m_hm_plane.draw_fill();
|
m_hm_plane.draw_fill();
|
||||||
}
|
}
|
||||||
else if (m_shade_mode == ShadeMode::Flat)
|
else if (m_shade_mode == ShadeMode::Flat)
|
||||||
@@ -167,6 +183,17 @@ void NodePanelGrid::draw_heightmap(const glm::mat4& proj, const glm::mat4& camer
|
|||||||
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
||||||
m_hm_plane.draw_fill();
|
m_hm_plane.draw_fill();
|
||||||
}
|
}
|
||||||
|
else if(m_shade_mode == ShadeMode::Textured)
|
||||||
|
{
|
||||||
|
ShaderManager::use(kShader::LambertLightmap);
|
||||||
|
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
||||||
|
ShaderManager::u_vec3(kShaderUniform::LightDir, light_dir);
|
||||||
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
|
m_sampler_linear.bind(0);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
m_texture.bind();
|
||||||
|
m_hm_plane.draw_fill();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DRAW GRIDS
|
// DRAW GRIDS
|
||||||
@@ -191,3 +218,89 @@ void NodePanelGrid::draw_heightmap(const glm::mat4& proj, const glm::mat4& camer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodePanelGrid::bake_uvs()
|
||||||
|
{
|
||||||
|
if (!m_hm_image.m_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RTT fb;
|
||||||
|
fb.create(m_texture.size().x, m_texture.size().y, -1, GL_RGBA32F);
|
||||||
|
fb.bindFramebuffer();
|
||||||
|
fb.clear({ 1, 0, 0, 1 });
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glViewport(0, 0, fb.getWidth(), fb.getHeight());
|
||||||
|
ShaderManager::use(kShader::BakeUV);
|
||||||
|
ShaderManager::u_mat4(kShaderUniform::MVP, glm::mat4(1));
|
||||||
|
|
||||||
|
// bake normal
|
||||||
|
ShaderManager::u_int(kShaderUniform::Mode, 0);
|
||||||
|
m_hm_plane.draw_fill();
|
||||||
|
std::unique_ptr<float[]> data_nor(fb.readTextureDataFloat());
|
||||||
|
//stbi_write_jpg("bake-nor.jpg", fb.getWidth(), fb.getHeight(), 4, fb.readTextureData(), 75);
|
||||||
|
|
||||||
|
// bake position
|
||||||
|
ShaderManager::u_int(kShaderUniform::Mode, 1);
|
||||||
|
m_hm_plane.draw_fill();
|
||||||
|
std::unique_ptr<float[]> data_pos(fb.readTextureDataFloat());
|
||||||
|
//stbi_write_jpg("bake-pos.jpg", fb.getWidth(), fb.getHeight(), 4, fb.readTextureData(), 75);
|
||||||
|
|
||||||
|
fb.unbindFramebuffer();
|
||||||
|
fb.destroy();
|
||||||
|
|
||||||
|
if (m_rt_dirty)
|
||||||
|
{
|
||||||
|
nanort::BVHBuildOptions<float> build_options; // Use default option
|
||||||
|
build_options.cache_bbox = false;
|
||||||
|
nanort::TriangleMesh<float> triangle_mesh(reinterpret_cast<float*>(m_hm_plane.vertices.data()), m_hm_plane.idx.data(), sizeof(vertex_t));
|
||||||
|
nanort::TriangleSAHPred<float> triangle_pred(reinterpret_cast<float*>(m_hm_plane.vertices.data()), m_hm_plane.idx.data(), sizeof(vertex_t));
|
||||||
|
bool ret = m_rt_accel.Build(static_cast<unsigned int>(m_hm_plane.idx.size() / 3), triangle_mesh, triangle_pred, build_options);
|
||||||
|
if (!ret)
|
||||||
|
return;
|
||||||
|
m_rt_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto light_yaw = m_hm_lyaw->get_value() * glm::pi<float>() * 2.f;
|
||||||
|
auto light_pitch = m_hm_lpitch->get_value() * 5;
|
||||||
|
auto light_pos = glm::vec3(sinf(light_yaw), light_pitch, cosf(light_yaw));
|
||||||
|
auto light_dir = glm::normalize(light_pos);
|
||||||
|
|
||||||
|
auto data_out = std::make_unique<uint8_t[]>(fb.getWidth() * fb.getHeight() * 4);
|
||||||
|
for (int y = 0; y < fb.getHeight(); y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < fb.getWidth(); x++)
|
||||||
|
{
|
||||||
|
int i = y * fb.getHeight() + x;
|
||||||
|
auto nor = glm::make_vec4(&data_nor[i * 4]);
|
||||||
|
auto pos = glm::make_vec4(&data_pos[i * 4]);
|
||||||
|
auto& out = *reinterpret_cast<glm::i8vec4*>(&data_out[i * 4]);
|
||||||
|
|
||||||
|
nanort::Ray<float> ray;
|
||||||
|
ray.org[0] = pos.x;// + nor.x * 0.005;
|
||||||
|
ray.org[1] = pos.y;// + nor.y * 0.005;
|
||||||
|
ray.org[2] = pos.z;// + nor.z * 0.005;
|
||||||
|
ray.dir[0] = light_dir.x;
|
||||||
|
ray.dir[1] = light_dir.y;
|
||||||
|
ray.dir[2] = light_dir.z;
|
||||||
|
|
||||||
|
float kFar = 1.0e+30f;
|
||||||
|
ray.min_t = 0.001f;
|
||||||
|
ray.max_t = kFar;
|
||||||
|
|
||||||
|
nanort::TriangleIntersector<> triangle_intersector(reinterpret_cast<float*>(m_hm_plane.vertices.data()), m_hm_plane.idx.data(), sizeof(vertex_t));
|
||||||
|
nanort::TriangleIntersection<> isect;
|
||||||
|
bool hit = m_rt_accel.Traverse(ray, triangle_intersector, &isect);
|
||||||
|
if (hit)
|
||||||
|
{
|
||||||
|
out = { 50, 50, 50, 255 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out = { 255, 255, 255, 255 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//stbi_write_jpg("bake-out.jpg", fb.getWidth(), fb.getHeight(), 4, data_out.get(), 75);
|
||||||
|
m_texture.update(data_out.get());
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,11 +9,12 @@
|
|||||||
#include "node_button.h"
|
#include "node_button.h"
|
||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "nanort.h"
|
||||||
|
|
||||||
class NodePanelGrid : public Node
|
class NodePanelGrid : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class ShadeMode : uint8_t { Transparent, Flat, Solid };
|
enum class ShadeMode : uint8_t { Transparent, Flat, Solid, Textured };
|
||||||
|
|
||||||
NodeSliderH* m_groud_opacity;
|
NodeSliderH* m_groud_opacity;
|
||||||
NodeSliderH* m_groud_value;
|
NodeSliderH* m_groud_value;
|
||||||
@@ -29,9 +30,14 @@ public:
|
|||||||
NodeSliderH* m_hm_lyaw;
|
NodeSliderH* m_hm_lyaw;
|
||||||
NodeSliderH* m_hm_lpitch;
|
NodeSliderH* m_hm_lpitch;
|
||||||
NodeButton* m_render;
|
NodeButton* m_render;
|
||||||
|
NodeButton* m_commit;
|
||||||
HeightmapPlane m_hm_plane;
|
HeightmapPlane m_hm_plane;
|
||||||
Image m_hm_image;
|
Image m_hm_image;
|
||||||
|
Texture2D m_texture;
|
||||||
|
Sampler m_sampler_linear;
|
||||||
std::string m_file_path;
|
std::string m_file_path;
|
||||||
|
nanort::BVHAccel<float> m_rt_accel;
|
||||||
|
bool m_rt_dirty = true;;
|
||||||
ShadeMode m_shade_mode{ ShadeMode::Transparent };
|
ShadeMode m_shade_mode{ ShadeMode::Transparent };
|
||||||
|
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
@@ -41,4 +47,5 @@ public:
|
|||||||
float get_height() const;
|
float get_height() const;
|
||||||
float get_offset() const;
|
float get_offset() const;
|
||||||
void draw_heightmap(const glm::mat4& proj, const glm::mat4& camera) const;
|
void draw_heightmap(const glm::mat4& proj, const glm::mat4& camera) const;
|
||||||
|
void bake_uvs();
|
||||||
};
|
};
|
||||||
|
|||||||
33
src/rtt.cpp
33
src/rtt.cpp
@@ -167,6 +167,8 @@ void RTT::bindFramebuffer()
|
|||||||
|
|
||||||
void RTT::unbindFramebuffer()
|
void RTT::unbindFramebuffer()
|
||||||
{
|
{
|
||||||
|
if (!bound)
|
||||||
|
return;
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
|
||||||
oldRFboID = 0;
|
oldRFboID = 0;
|
||||||
@@ -180,14 +182,28 @@ void RTT::clear(glm::vec4 color)
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTT::readTextureData(uint8_t* buffer)
|
uint8_t* RTT::readTextureData(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
glReadBuffer(GL_BACK);
|
if (!buffer)
|
||||||
bindFramebuffer();
|
buffer = createBuffer();
|
||||||
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
GLint old;
|
||||||
|
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
|
||||||
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||||
unbindFramebuffer();
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
|
||||||
//glReadBuffer(GL_NONE);
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
float* RTT::readTextureDataFloat(float* buffer)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
buffer = createBufferFloat();
|
||||||
|
GLint old;
|
||||||
|
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
|
||||||
|
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, buffer);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* RTT::createBuffer()
|
uint8_t* RTT::createBuffer()
|
||||||
@@ -195,6 +211,11 @@ uint8_t* RTT::createBuffer()
|
|||||||
return new uint8_t[w * h * 4];
|
return new uint8_t[w * h * 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float * RTT::createBufferFloat()
|
||||||
|
{
|
||||||
|
return new float[w * h * 4];
|
||||||
|
}
|
||||||
|
|
||||||
void RTT::bindTexture()
|
void RTT::bindTexture()
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, texID);
|
glBindTexture(GL_TEXTURE_2D, texID);
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ public:
|
|||||||
bool create(int width, int height, int tex = -1, GLint internal_format = GL_RGBA8);
|
bool create(int width, int height, int tex = -1, GLint internal_format = GL_RGBA8);
|
||||||
bool recreate() { return create(w, h); }
|
bool recreate() { return create(w, h); }
|
||||||
void clear(glm::vec4 color = glm::vec4(0));
|
void clear(glm::vec4 color = glm::vec4(0));
|
||||||
void readTextureData(uint8_t* buffer);
|
uint8_t* readTextureData(uint8_t* buffer = nullptr);
|
||||||
|
float* readTextureDataFloat(float* buffer = nullptr);
|
||||||
uint8_t* createBuffer();
|
uint8_t* createBuffer();
|
||||||
|
float* createBufferFloat();
|
||||||
void bindFramebuffer();
|
void bindFramebuffer();
|
||||||
void unbindFramebuffer();
|
void unbindFramebuffer();
|
||||||
void bindTexture();
|
void bindTexture();
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ enum class kShaderUniform : uint16_t
|
|||||||
Direction = const_hash("dir"),
|
Direction = const_hash("dir"),
|
||||||
UseFragCoordUV2 = const_hash("fragUV2"),
|
UseFragCoordUV2 = const_hash("fragUV2"),
|
||||||
LightDir = const_hash("light_dir"),
|
LightDir = const_hash("light_dir"),
|
||||||
|
Mode = const_hash("mode"),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class kShader : uint16_t
|
enum class kShader : uint16_t
|
||||||
@@ -56,6 +57,8 @@ enum class kShader : uint16_t
|
|||||||
BrushStroke = const_hash("brush-stroke"),
|
BrushStroke = const_hash("brush-stroke"),
|
||||||
VertexColor = const_hash("vertex-color"),
|
VertexColor = const_hash("vertex-color"),
|
||||||
Lambert = const_hash("lambert"),
|
Lambert = const_hash("lambert"),
|
||||||
|
LambertLightmap = const_hash("lambert-lightmap"),
|
||||||
|
BakeUV = const_hash("bakeuv"),
|
||||||
};
|
};
|
||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ bool HeightmapPlane::create(float w, float h, const Image& img, float scale, flo
|
|||||||
int div = new_size.x - 1; // TODO: handle height also
|
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);
|
||||||
std::vector<GLuint> idx(idx_size);
|
idx.resize(idx_size);
|
||||||
std::vector<vertex_t> vertices(vertices_size);
|
vertices.resize(vertices_size);
|
||||||
std::vector<int> nor_count((size_t)vertices_size, 0);
|
std::vector<int> nor_count((size_t)vertices_size, 0);
|
||||||
|
|
||||||
count[0] = div * div * 6;
|
count[0] = div * div * 6;
|
||||||
@@ -277,8 +277,8 @@ bool HeightmapPlane::create(float w, float h, const Image& img, float scale, flo
|
|||||||
{
|
{
|
||||||
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 = (*px++).r / 255.f * height;
|
||||||
v.pos.z = (*px++).r / 255.f;
|
v.pos.z = oy + dy * (float)y;
|
||||||
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;
|
||||||
@@ -286,7 +286,7 @@ bool HeightmapPlane::create(float w, float h, const Image& img, float scale, flo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate indices
|
// generate indices
|
||||||
const glm::vec3 yscale(1, 1, height);
|
const glm::vec3 yscale(1, height, 1);
|
||||||
for (int y = 0; y < div; y++)
|
for (int y = 0; y < div; y++)
|
||||||
{
|
{
|
||||||
int i = y * (div + 1);
|
int i = y * (div + 1);
|
||||||
@@ -363,8 +363,8 @@ bool HeightmapPlane::create(float w, float h, int div)
|
|||||||
{
|
{
|
||||||
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 = 0.f;
|
||||||
v.pos.z = 0.f;
|
v.pos.z = oy + dy * (float)y;
|
||||||
v.pos.w = 1.f;
|
v.pos.w = 1.f;
|
||||||
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
|
v.uvs2 = v.uvs = glm::vec2(x, y) / (float)div;
|
||||||
v.nor = { 0, 1, 0 };
|
v.nor = { 0, 1, 0 };
|
||||||
|
|||||||
@@ -125,6 +125,8 @@ public:
|
|||||||
class HeightmapPlane : public Shape
|
class HeightmapPlane : public Shape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::vector<GLuint> idx;
|
||||||
|
std::vector<vertex_t> vertices;
|
||||||
bool create(float w, float h, const Image& img, float scale, float height);
|
bool create(float w, float h, const Image& img, float scale, float height);
|
||||||
bool create(float w, float h, int div);
|
bool create(float w, float h, int div);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ void Sampler::set_filter(GLint filter_min, GLint filter_mag)
|
|||||||
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter_mag);
|
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter_mag);
|
||||||
#endif // USE_SAMPLER
|
#endif // USE_SAMPLER
|
||||||
}
|
}
|
||||||
void Sampler::bind(int unit)
|
void Sampler::bind(int unit) const
|
||||||
{
|
{
|
||||||
current_unit = unit;
|
current_unit = unit;
|
||||||
#if USE_SAMPLER
|
#if USE_SAMPLER
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ public:
|
|||||||
class Sampler
|
class Sampler
|
||||||
{
|
{
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
GLint current_unit = 0;
|
mutable GLint current_unit = 0;
|
||||||
public:
|
public:
|
||||||
bool create(GLint filter = GL_LINEAR, GLint wrap = GL_CLAMP_TO_EDGE);
|
bool create(GLint filter = GL_LINEAR, GLint wrap = GL_CLAMP_TO_EDGE);
|
||||||
void set(GLint filter = GL_LINEAR, GLint wrap = GL_CLAMP_TO_EDGE);
|
void set(GLint filter = GL_LINEAR, GLint wrap = GL_CLAMP_TO_EDGE);
|
||||||
void set_filter(GLint filter_min, GLint filter_mag);
|
void set_filter(GLint filter_min, GLint filter_mag);
|
||||||
void bind(int unit);
|
void bind(int unit) const;
|
||||||
void unbind();
|
void unbind();
|
||||||
bool ready() const { return id != 0; }
|
bool ready() const { return id != 0; }
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user