diff --git a/examples/grass.cpp b/examples/grass.cpp index c30804ee..97673658 100644 --- a/examples/grass.cpp +++ b/examples/grass.cpp @@ -110,31 +110,53 @@ static char const grass_slice_vs[] = R"(#version 330 uniform mat4 u_transform; +uniform mat4 u_tile_transform; + +uniform float u_density00; +uniform float u_density01; +uniform float u_density10; +uniform float u_density11; layout (location = 0) in vec4 in_position; layout (location = 1) in vec2 in_texcoord; -out vec2 texcoord; +out vec3 texcoord; void main() { - gl_Position = u_transform * in_position; - texcoord = in_texcoord; + vec2 p = (u_tile_transform * vec4(in_position.xy, 0.0, 1.0)).xy; + + vec2 o = (u_tile_transform * vec4(0.5, 0.5, 0.0, 1.0)).xy; + + o = vec2(floor(o.x), floor(o.y)); + + vec2 d = p - o; + + float level = mix(mix(u_density00, u_density01, d.x), mix(u_density10, u_density11, d.x), d.y); + + gl_Position = u_transform * vec4(p, in_position.z, 1.0); + texcoord = vec3(in_texcoord, level); } )"; static char const grass_slice_fs[] = R"(#version 330 -uniform sampler2D u_texture; +uniform sampler2DArray u_texture; -in vec2 texcoord; +in vec3 texcoord; out vec4 out_color; void main() { - vec4 c = texture(u_texture, texcoord); + float l0 = floor(texcoord.z); + float l1 = l0 + 1; + float t = texcoord.z - l0; + vec4 c0 = texture(u_texture, vec3(texcoord.xy, l0)); + vec4 c1 = texture(u_texture, vec3(texcoord.xy, l1)); + vec4 c = mix(c0, c1, t); +// vec4 c = c0; out_color = vec4(c.rgb / c.a, c.a); } )"; @@ -146,6 +168,8 @@ struct grass_app int size = 64; + int const density_level_count = 8; + pcg::perlin density; gfx::program ground_program{ground_vs, ground_fs}; @@ -156,7 +180,7 @@ struct grass_app gfx::texture_1d grass_texture; gfx::program grass_slice_program{grass_slice_vs, grass_slice_fs}; - gfx::texture_2d grass_slice_z_texture; + gfx::texture_2d_array grass_slice_z_texture; gfx::mesh grass_slice_z_mesh; gfx::framebuffer grass_slice_framebuffer; @@ -378,7 +402,7 @@ struct grass_app { struct vertex { - geom::vector position; + geom::point position; geom::vector texcoord; }; @@ -393,35 +417,38 @@ struct grass_app 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.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_z_texture.load(slice_resolution, slice_resolution, density_level_count); 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 d = 0; d < density_level_count; ++d) { - for (int y = -1; y <= 1; ++y) + grass_slice_framebuffer.color(grass_slice_z_texture, d); + 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::Enable(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) { - 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(); + 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(0, (grass_mesh.index_count() * (d + 1)) / density_level_count); + } } } gfx::framebuffer::null().bind(); @@ -429,6 +456,7 @@ struct grass_app grass_slice_z_texture.linear_filter(); grass_slice_z_texture.anisotropy(); grass_slice_z_texture.generate_mipmap(); + grass_slice_z_texture.clamp(); // 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); @@ -529,10 +557,8 @@ struct grass_app float d = density({(x + 0.5f) / size, (y + 0.5f) / size}); - int const N = 8; - - int i = std::floor(d * N); - if (i > N - 1) i = N - 1; + int i = std::floor(d * density_level_count); + if (i > density_level_count - 1) i = density_level_count - 1; { float h00 = density({(x + 0.f) / size, (y + 0.f) / size}); @@ -544,14 +570,15 @@ struct grass_app grass_program["u_height01"] = h01; grass_program["u_height10"] = h10; grass_program["u_height11"] = h11; - grass_mesh.draw(0, ((i + 1) * grass_mesh.index_count()) / N); + grass_mesh.draw(0, ((i + 1) * grass_mesh.index_count()) / density_level_count); - triangles += (((i + 1) * grass_mesh.index_count()) / N) / 3; + triangles += (((i + 1) * grass_mesh.index_count()) / density_level_count) / 3; } } } grass_slice_program.bind();; + grass_slice_program["u_transform"] = camera_transform; grass_slice_program["u_texture"] = 0; grass_slice_z_texture.bind(); @@ -561,10 +588,19 @@ struct grass_app { if (x >= size / 2) continue; - grass_slice_program["u_transform"] = camera_transform - * geom::translation(geom::vector{x, y, 0.f}).homogeneous_matrix() + grass_slice_program["u_tile_transform"] = geom::translation(geom::vector{x, y, 0.f}).homogeneous_matrix() * random_transform[random_transform_index(x, y)]; + float d00 = density({(x + 0.f) / size, (y + 0.f) / size}) * density_level_count; + float d01 = density({(x + 1.f) / size, (y + 0.f) / size}) * density_level_count; + float d10 = density({(x + 0.f) / size, (y + 1.f) / size}) * density_level_count; + float d11 = density({(x + 1.f) / size, (y + 1.f) / size}) * density_level_count; + + grass_slice_program["u_density00"] = d00; + grass_slice_program["u_density01"] = d01; + grass_slice_program["u_density10"] = d10; + grass_slice_program["u_density11"] = d11; + grass_slice_z_mesh.draw(); } }