Grass example: implement z-slice (no density yet)
This commit is contained in:
parent
f18fbfdcdb
commit
71e9fdf6ea
1 changed files with 134 additions and 11 deletions
|
|
@ -4,6 +4,8 @@
|
|||
#include <psemek/gfx/program.hpp>
|
||||
#include <psemek/gfx/texture.hpp>
|
||||
#include <psemek/gfx/painter.hpp>
|
||||
#include <psemek/gfx/framebuffer.hpp>
|
||||
#include <psemek/gfx/renderbuffer.hpp>
|
||||
#include <psemek/geom/camera.hpp>
|
||||
#include <psemek/geom/math.hpp>
|
||||
#include <psemek/geom/rotation.hpp>
|
||||
|
|
@ -86,7 +88,8 @@ void main()
|
|||
float h = mix(mix(u_height00, u_height01, d.x), mix(u_height10, u_height11, d.x), d.y);
|
||||
|
||||
gl_Position = u_transform * vec4(p, in_position.z * h, 1.0);
|
||||
color = mix(vec4(0.0, 0.0, 0.0, 1.0), texture(u_texture, in_t), in_position.z);
|
||||
// color = mix(vec4(0.0, 0.0, 0.0, 1.0), texture(u_texture, in_t), in_position.z);
|
||||
color = texture(u_texture, in_t);
|
||||
}
|
||||
)";
|
||||
|
||||
|
|
@ -103,6 +106,39 @@ void main()
|
|||
}
|
||||
)";
|
||||
|
||||
static char const grass_slice_vs[] =
|
||||
R"(#version 330
|
||||
|
||||
uniform mat4 u_transform;
|
||||
|
||||
layout (location = 0) in vec4 in_position;
|
||||
layout (location = 1) in vec2 in_texcoord;
|
||||
|
||||
out vec2 texcoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_transform * in_position;
|
||||
texcoord = in_texcoord;
|
||||
}
|
||||
)";
|
||||
|
||||
static char const grass_slice_fs[] =
|
||||
R"(#version 330
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
in vec2 texcoord;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(u_texture, texcoord);
|
||||
out_color = vec4(c.rgb / c.a, c.a);
|
||||
}
|
||||
)";
|
||||
|
||||
struct grass_app
|
||||
: app::app
|
||||
{
|
||||
|
|
@ -119,6 +155,13 @@ struct grass_app
|
|||
gfx::indexed_mesh grass_mesh;
|
||||
gfx::texture_1d grass_texture;
|
||||
|
||||
gfx::program grass_slice_program{grass_slice_vs, grass_slice_fs};
|
||||
gfx::texture_2d grass_slice_z_texture;
|
||||
gfx::mesh grass_slice_z_mesh;
|
||||
|
||||
gfx::framebuffer grass_slice_framebuffer;
|
||||
gfx::renderbuffer grass_slice_renderbuffer;
|
||||
|
||||
geom::matrix<float, 4, 4> random_transform[8];
|
||||
util::array<int, 2> random_transform_index;
|
||||
|
||||
|
|
@ -135,7 +178,7 @@ struct grass_app
|
|||
vsync(false);
|
||||
|
||||
camera.fov_y = geom::rad(45.f);
|
||||
camera.near_clip = 0.01f;
|
||||
camera.near_clip = 0.1f;
|
||||
camera.far_clip = 1000.f;
|
||||
camera.pos = {0.5f, 0.5f, 1.5f};
|
||||
camera.elevation_angle = geom::rad(15.f);
|
||||
|
|
@ -143,6 +186,7 @@ struct grass_app
|
|||
|
||||
init_ground();
|
||||
init_grass();
|
||||
init_grass_slices();
|
||||
|
||||
pcg::generator rng;
|
||||
pcg::uniform_sphere_vector_distribution<float, 2> d;
|
||||
|
|
@ -240,7 +284,6 @@ struct grass_app
|
|||
for (std::size_t i = 0; i < pm.width(); ++i)
|
||||
{
|
||||
pm(i) = gfx::to_coloru8(g((i + 0.5f) / pm.width()));
|
||||
// pm(i) = gfx::to_coloru8(gfx::color_4f{(i + 0.5f) / pm.width(), 0.f, 0.f, 1.f});
|
||||
}
|
||||
|
||||
grass_texture.load(pm);
|
||||
|
|
@ -255,15 +298,14 @@ struct grass_app
|
|||
grass_mesh.setup<gfx::normalized<geom::point<std::uint16_t, 3>>, gfx::normalized<std::uint8_t>, gfx::normalized<std::uint8_t>>();
|
||||
|
||||
std::vector<vertex> vertices;
|
||||
std::vector<geom::triangle<std::uint16_t>> triangles;
|
||||
pcg::uniform_ball_vector_distribution<float, 2> d_offset;
|
||||
std::vector<geom::triangle<std::uint32_t>> triangles;
|
||||
pcg::uniform_box_point_distribution<float, 2> d_origin({{{0.f, 1.f}, {0.f, 1.f}}});
|
||||
pcg::uniform_sphere_vector_distribution<float, 2> d_orientation;
|
||||
pcg::uniform_real_distribution<float> d_width{1.f / 64.f, 1.f / 128.f};
|
||||
pcg::uniform_real_distribution<float> d_height{0.25f, 1.f};
|
||||
pcg::uniform_real_distribution<float> d_density{0.f, 1.f};
|
||||
|
||||
for (int blade = 0; blade < 2048; ++blade)
|
||||
for (int blade = 0; blade < 4096; ++blade)
|
||||
{
|
||||
int const segments = 8;
|
||||
float const max_lean = 0.2f;
|
||||
|
|
@ -275,8 +317,6 @@ struct grass_app
|
|||
o[0] = o[0] / 8.f + tx / 8.f;
|
||||
o[1] = o[1] / 8.f + ty / 8.f;
|
||||
|
||||
// geom::point<float, 2> o{(blade % 256) / 256.f, std::fmod(blade * phi, 1.f)};
|
||||
// o += d_offset(rng) * 0.f;
|
||||
auto r = d_orientation(rng);
|
||||
auto s = d_width(rng) * 0.5f;
|
||||
auto h = d_height(rng);
|
||||
|
|
@ -334,6 +374,66 @@ struct grass_app
|
|||
log::info() << frame_clock.count();
|
||||
}
|
||||
|
||||
void init_grass_slices()
|
||||
{
|
||||
struct vertex
|
||||
{
|
||||
geom::vector<float, 3> position;
|
||||
geom::vector<float, 2> texcoord;
|
||||
};
|
||||
|
||||
int const slice_count = 4;
|
||||
float slice_width = 1.f / slice_count;
|
||||
|
||||
std::vector<vertex> vertices;
|
||||
vertices.push_back({{0.f, 0.f, slice_width}, {0.f, 0.f}});
|
||||
vertices.push_back({{1.f, 0.f, slice_width}, {1.f, 0.f}});
|
||||
vertices.push_back({{0.f, 1.f, slice_width}, {0.f, 1.f}});
|
||||
vertices.push_back({{0.f, 1.f, slice_width}, {0.f, 1.f}});
|
||||
vertices.push_back({{1.f, 0.f, slice_width}, {1.f, 0.f}});
|
||||
vertices.push_back({{1.f, 1.f, slice_width}, {1.f, 1.f}});
|
||||
|
||||
grass_slice_z_mesh.setup<geom::vector<float, 3>, geom::vector<float, 2>>();
|
||||
grass_slice_z_mesh.load(vertices, gl::TRIANGLES, gl::STATIC_DRAW);
|
||||
|
||||
std::size_t slice_resolution = 256;
|
||||
|
||||
grass_slice_z_texture.load<gfx::color_rgba>(slice_resolution, slice_resolution);
|
||||
grass_slice_renderbuffer.storage(gl::DEPTH24_STENCIL8, slice_resolution, slice_resolution);
|
||||
grass_slice_framebuffer.color(grass_slice_z_texture);
|
||||
grass_slice_framebuffer.depth(grass_slice_renderbuffer);
|
||||
grass_slice_framebuffer.assert_complete();
|
||||
gl::Viewport(0, 0, slice_resolution, slice_resolution);
|
||||
gl::ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
|
||||
gl::Disable(gl::DEPTH_TEST);
|
||||
gl::DepthFunc(gl::LEQUAL);
|
||||
grass_program.bind();
|
||||
grass_program["u_tile_transform"] = geom::matrix<float, 4, 4>::identity();
|
||||
grass_program["u_height00"] = 1.f;
|
||||
grass_program["u_height01"] = 1.f;
|
||||
grass_program["u_height10"] = 1.f;
|
||||
grass_program["u_height11"] = 1.f;
|
||||
grass_program["u_texture"] = 0;
|
||||
grass_texture.bind();
|
||||
for (int x = -1; x <= 1; ++x)
|
||||
{
|
||||
for (int y = -1; y <= 1; ++y)
|
||||
{
|
||||
grass_program["u_transform"] = geom::translation<float, 3>({-1.f + 2.f * x, -1.f + 2.f * y, 0.f}).homogeneous_matrix() * geom::scale<float, 3>({2.f, 2.f, 1.f}).homogeneous_matrix();
|
||||
grass_mesh.draw();
|
||||
}
|
||||
}
|
||||
gfx::framebuffer::null().bind();
|
||||
|
||||
grass_slice_z_texture.linear_filter();
|
||||
grass_slice_z_texture.anisotropy();
|
||||
grass_slice_z_texture.generate_mipmap();
|
||||
// grass_slice_z_texture.bind();
|
||||
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);
|
||||
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR);
|
||||
}
|
||||
|
||||
void on_resize(int width, int height) override
|
||||
{
|
||||
app::on_resize(width, height);
|
||||
|
|
@ -402,16 +502,19 @@ struct grass_app
|
|||
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
gl::DepthFunc(gl::LEQUAL);
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::Enable(gl::BLEND);
|
||||
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
auto camera_transform = camera.transform();
|
||||
|
||||
ground_program.bind();
|
||||
ground_program["u_transform"] = camera.transform();
|
||||
ground_program["u_transform"] = camera_transform;
|
||||
ground_mesh.draw();
|
||||
|
||||
grass_program.bind();
|
||||
grass_program["u_texture"] = 0;
|
||||
grass_texture.bind();
|
||||
grass_program["u_transform"] = camera.transform();
|
||||
grass_program["u_transform"] = camera_transform;
|
||||
|
||||
std::size_t triangles = 0;
|
||||
|
||||
|
|
@ -419,6 +522,8 @@ struct grass_app
|
|||
{
|
||||
for (int y = 0; y < size; ++y)
|
||||
{
|
||||
if (x < size / 2) continue;
|
||||
|
||||
grass_program["u_tile_transform"] = geom::translation<float, 3>(geom::vector{x, y, 0.f}).homogeneous_matrix()
|
||||
* random_transform[random_transform_index(x, y)];
|
||||
|
||||
|
|
@ -446,6 +551,24 @@ struct grass_app
|
|||
}
|
||||
}
|
||||
|
||||
grass_slice_program.bind();;
|
||||
grass_slice_program["u_texture"] = 0;
|
||||
grass_slice_z_texture.bind();
|
||||
|
||||
for (int x = 0; x < size; ++x)
|
||||
{
|
||||
for (int y = 0; y < size; ++y)
|
||||
{
|
||||
if (x >= size / 2) continue;
|
||||
|
||||
grass_slice_program["u_transform"] = camera_transform
|
||||
* geom::translation<float, 3>(geom::vector{x, y, 0.f}).homogeneous_matrix()
|
||||
* random_transform[random_transform_index(x, y)];
|
||||
|
||||
grass_slice_z_mesh.draw();
|
||||
}
|
||||
}
|
||||
|
||||
frame_time.push(frame_clock.restart().count());
|
||||
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue