Grass example: implement z-slice (no density yet)

This commit is contained in:
Nikita Lisitsa 2020-10-03 18:45:35 +03:00
parent f18fbfdcdb
commit 71e9fdf6ea

View file

@ -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());
{