use super::{SelectedFormats, VkAllocator};
use crate::client_state::settings::Supersampling;
use crate::vulkan::{Texture2DHolder, VulkanContext};
use anyhow::Result;
use cgmath::{Matrix4, Vector3};
use std::sync::Arc;
use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter};
pub(crate) mod cube_geometry;
pub(crate) mod egui_adapter;
pub(crate) mod entity_geometry;
pub(crate) mod far_mesh;
pub(crate) mod flat_texture;
pub(crate) mod raytracer;
pub(crate) mod text_pipeline;
pub(crate) mod vert_3d {
vulkano_shaders::shader! {
shaders: {
cube_geometry: {
ty: "vertex",
path: "src/vulkan/shaders/cube_geometry.vert"
},
entity_tentative: {
ty: "vertex",
path: "src/vulkan/shaders/entity.vert"
},
}
}
}
pub(crate) mod frag_lighting_basic_color {
vulkano_shaders::shader! {
ty: "fragment",
path: "src/vulkan/shaders/raster_frag_lighting.glsl",
define: [("ENABLE_BASIC_COLOR", "2")]
}
}
pub(crate) mod frag_lighting_unified_specular {
vulkano_shaders::shader! {
ty: "fragment",
path: "src/vulkan/shaders/raster_frag_lighting.glsl",
define: [("ENABLE_UNIFIED_SPECULAR", "1")]
}
}
pub(crate) mod frag_specular_only {
vulkano_shaders::shader! {
ty: "fragment",
path: "src/vulkan/shaders/raster_frag_lighting.glsl",
define: [("ENABLE_SPECULAR_ONLY", "1")]
}
}
pub(crate) mod vert_2d {
vulkano_shaders::shader! {
shaders: {
flat_tex: {
ty: "vertex",
src: r"
#version 460
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 uv_texcoord;
layout(set = 1, binding = 0) uniform UniformData {
vec2 device_w_h;
};
layout(location = 0) out vec2 uv_texcoord_out;
void main() {
// pixel -> normalized device coordinates
vec2 ndc = (2.0 * position + 1) / device_w_h - 1.0;
// Z shouldn't matter (no depth test)
gl_Position = vec4(ndc, 0.5, 1.0);
uv_texcoord_out = uv_texcoord;
}
"
}
}
}
}
pub(crate) mod post_process;
pub(crate) mod sky;
pub(crate) mod frag_simple {
vulkano_shaders::shader! {
ty: "fragment",
src: r"
#version 460
layout(location = 0) in vec2 uv_texcoord;
layout(location = 0) out vec4 f_color;
layout(set = 0, binding = 0) uniform sampler2D tex;
void main() {
f_color = texture(tex, uv_texcoord);
}
"
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct LiveRenderConfig {
pub(crate) supersampling: Supersampling,
pub(crate) hdr: bool,
pub(crate) raytracing: bool,
pub(crate) hybrid_rt: bool,
pub(crate) render_distance: u32,
pub(crate) raytracer_debug: bool,
pub(crate) raytracing_specular_downsampling: u32,
pub(crate) blur_steps: usize,
pub(crate) bloom_strength: f32,
pub(crate) lens_flare_strength: f32,
pub(crate) approx_gaussian_blit: bool,
pub(crate) clamp_global_brightness_to_zero_debug: bool,
pub(crate) formats: SelectedFormats,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct SceneState {
pub(crate) vp_matrix: Matrix4<f32>,
pub(crate) global_light_color: [f32; 3],
pub(crate) sun_direction: Vector3<f32>,
pub(crate) player_pos_block: u32,
pub(crate) alt_diffuse_enabled: bool,
pub(crate) player_position: Vector3<f64>,
}
#[derive(Clone, PartialEq)]
pub(crate) struct VkBufferCpu<T: BufferContents + Copy> {
pub(crate) vtx: Vec<T>,
pub(crate) idx: Vec<u32>,
}
impl<T: BufferContents + Copy> VkBufferCpu<T> {
pub(crate) fn to_gpu(&self, allocator: Arc<VkAllocator>) -> Result<Option<VkDrawBufferGpu<T>>> {
VkDrawBufferGpu::from_buffers(&self.vtx, &self.idx, allocator)
}
}
#[derive(Clone)]
pub(crate) struct VkDrawBufferGpu<T: BufferContents + Copy> {
pub(crate) vtx: Subbuffer<[T]>,
pub(crate) idx: Subbuffer<[u32]>,
pub(crate) num_indices: u32,
}
impl<T: BufferContents + Copy> VkDrawBufferGpu<T> {
pub(crate) fn from_buffers(
vtx: &[T],
idx: &[u32],
allocator: Arc<VkAllocator>,
) -> Result<Option<VkDrawBufferGpu<T>>> {
if vtx.is_empty() {
Ok(None)
} else {
Ok(Some(VkDrawBufferGpu {
num_indices: idx.len() as u32,
vtx: Buffer::from_iter(
allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::HOST_SEQUENTIAL_WRITE
| MemoryTypeFilter::PREFER_DEVICE,
..Default::default()
},
vtx.iter().copied(),
)?,
idx: Buffer::from_iter(
allocator,
BufferCreateInfo {
usage: BufferUsage::INDEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::HOST_SEQUENTIAL_WRITE
| MemoryTypeFilter::PREFER_DEVICE,
..Default::default()
},
idx.iter().copied(),
)?,
}))
}
}
}
pub(crate) const fn x5y5z5_pack16(x: i8, y: i8, z: i8) -> u16 {
const fn encode(i: i8) -> u16 {
(i & 0x1f) as u16
}
(encode(x) << 10) | (encode(y) << 5) | (encode(z))
}
pub(crate) fn x5y5z5_pack_vec(v: Vector3<f32>) -> u16 {
let max_component = v.x.abs().max(v.y.abs()).max(v.z.abs());
let v = v * 15.0 / max_component;
x5y5z5_pack16(v.x as i8, v.y as i8, v.z as i8)
}
#[test]
fn test_x5y5z5_pack_vec() {
assert_eq!(x5y5z5_pack_vec(Vector3::new(1.0, 0.0, 0.0)), 0xf << 10);
assert_eq!(
x5y5z5_pack_vec(Vector3::new(1.0, -1.0, 0.0)),
0xf << 10 | 0x11 << 5
);
}
const _BLUE_NOISE_PNG_BYTES: &[u8] = include_bytes!("blue_noise.png");
fn make_blue_noise_image(ctx: &VulkanContext) -> Result<Texture2DHolder> {
let image = image::load_from_memory(_BLUE_NOISE_PNG_BYTES)?.to_luma8();
Ok(Texture2DHolder::from_image(
ctx,
image,
vulkano::format::Format::R8_UNORM,
vulkano::image::sampler::SamplerCreateInfo {
mag_filter: vulkano::image::sampler::Filter::Nearest,
min_filter: vulkano::image::sampler::Filter::Linear,
..Default::default()
},
None,
)?)
}