diff --git a/examples/grass.cpp b/examples/grass.cpp index 09788181..c30804ee 100644 --- a/examples/grass.cpp +++ b/examples/grass.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 random_transform[8]; util::array 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 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, gfx::normalized>(); std::vector vertices; - std::vector> triangles; - pcg::uniform_ball_vector_distribution d_offset; + std::vector> triangles; pcg::uniform_box_point_distribution d_origin({{{0.f, 1.f}, {0.f, 1.f}}}); pcg::uniform_sphere_vector_distribution d_orientation; pcg::uniform_real_distribution d_width{1.f / 64.f, 1.f / 128.f}; pcg::uniform_real_distribution d_height{0.25f, 1.f}; pcg::uniform_real_distribution 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 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 position; + geom::vector texcoord; + }; + + int const slice_count = 4; + float slice_width = 1.f / slice_count; + + std::vector 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>(); + grass_slice_z_mesh.load(vertices, gl::TRIANGLES, gl::STATIC_DRAW); + + std::size_t slice_resolution = 256; + + grass_slice_z_texture.load(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::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({-1.f + 2.f * x, -1.f + 2.f * y, 0.f}).homogeneous_matrix() * geom::scale({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(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(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()); {