compute shader 1 with sized vertice render and pipeline barrier

This commit is contained in:
zomseffen 2025-04-04 20:40:48 +02:00
parent c02522b6c2
commit 680039cdfa
11 changed files with 814 additions and 313 deletions

View file

@ -47,6 +47,12 @@ pub struct AppData {
pub compute_out_storage_buffers: Vec<vk::Buffer>,
pub compute_out_storage_buffers_memory: Vec<vk::DeviceMemory>,
pub compute_out_cuboid_buffers: Vec<vk::Buffer>,
pub compute_out_cuboid_buffers_memory: Vec<vk::DeviceMemory>,
pub compute_out_cuboid_index_buffers: Vec<vk::Buffer>,
pub compute_out_cuboid_index_buffers_memory: Vec<vk::DeviceMemory>,
pub descriptor_pool: vk::DescriptorPool,
pub descriptor_sets: Vec<vk::DescriptorSet>,
@ -71,6 +77,8 @@ pub struct AppData {
pub scene_rt_memory_size: u64,
pub scene_rt_volumetric_size: u64,
pub compute_task_one_size: usize,
pub compute_task_one_out_buffer_size: u64,
pub compute_task_one_out_size: u64,
// values passed to shader
pub num_lights_per_volume: u32,
pub min_light_weight: f32,

View file

@ -10,6 +10,8 @@ pub type Mat4 = cgmath::Matrix4<f32>;
use crate::app_data;
use crate::command_buffer;
use crate::primitives;
use crate::vertex;
use crate::vertex::VertexContainer;
use crate::scene;
@ -218,7 +220,19 @@ pub unsafe fn create_descriptor_set_layout(
.descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE);
let bindings = &[ubo_binding, sampler_binding, storage_binding_render, storage_binding_compute_in, storage_binding_compute_out];
let storage_binding_compute_cuboid_out = vk::DescriptorSetLayoutBinding::builder()
.binding(5)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::COMPUTE);
let storage_binding_compute_cuboid_index_out = vk::DescriptorSetLayoutBinding::builder()
.binding(6)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::COMPUTE);
let bindings = &[ubo_binding, sampler_binding, storage_binding_render, storage_binding_compute_in, storage_binding_compute_out, storage_binding_compute_cuboid_out, storage_binding_compute_cuboid_index_out];
let info = vk::DescriptorSetLayoutCreateInfo::builder()
.bindings(bindings);
@ -265,6 +279,12 @@ pub unsafe fn create_storage_buffers(
data.compute_out_storage_buffers.clear();
data.compute_out_storage_buffers_memory.clear();
data.compute_out_cuboid_buffers.clear();
data.compute_out_cuboid_buffers_memory.clear();
data.compute_out_cuboid_index_buffers.clear();
data.compute_out_cuboid_index_buffers_memory.clear();
for _ in 0..data.swapchain_images.len() {
let (storage_buffer, storage_buffer_memory) = create_buffer(
instance,
@ -293,13 +313,37 @@ pub unsafe fn create_storage_buffers(
instance,
device,
data,
data.scene_rt_memory_size.max(1),
vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::STORAGE_BUFFER,
data.compute_task_one_out_buffer_size.max(1),
vk::BufferUsageFlags::STORAGE_BUFFER,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
data.compute_out_storage_buffers.push(storage_buffer);
data.compute_out_storage_buffers_memory.push(storage_buffer_memory);
let (storage_buffer, storage_buffer_memory) = create_buffer(
instance,
device,
data,
(size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size,
vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::VERTEX_BUFFER,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
data.compute_out_cuboid_buffers.push(storage_buffer);
data.compute_out_cuboid_buffers_memory.push(storage_buffer_memory);
let (storage_buffer, storage_buffer_memory) = create_buffer(
instance,
device,
data,
(size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size,
vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::INDEX_BUFFER,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
data.compute_out_cuboid_index_buffers.push(storage_buffer);
data.compute_out_cuboid_index_buffers_memory.push(storage_buffer_memory);
}
Ok(())
@ -368,6 +412,43 @@ pub unsafe fn update_render_storage_buffer(
Ok(())
}
pub unsafe fn update_compute_storage_buffer(
instance: &Instance,
device: &Device,
data: &app_data::AppData,
image_index: usize,
scene_handler: &scene::Scene,
) -> Result<()> {
// rt compute buffer
if scene_handler.volumetrics.len() > 0 {
let (staging_buffer, staging_buffer_memory) = create_buffer(
instance,
device,
data,
data.scene_rt_volumetric_size,
vk::BufferUsageFlags::TRANSFER_SRC,
vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE,
)?;
let memory = device.map_memory(
staging_buffer_memory,
0,
data.scene_rt_volumetric_size,
vk::MemoryMapFlags::empty(),
)?;
memcpy(scene_handler.volumetrics_memory.as_ptr(), memory.cast(), scene_handler.volumetrics_memory.len());
device.unmap_memory(staging_buffer_memory);
copy_buffer(device, data, staging_buffer, data.compute_in_storage_buffers[image_index], data.scene_rt_volumetric_size)?;
device.destroy_buffer(staging_buffer, None);
device.free_memory(staging_buffer_memory, None);
}
Ok(())
}
pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppData) -> Result<()> {
let ubo_size = vk::DescriptorPoolSize::builder()
.type_(vk::DescriptorType::UNIFORM_BUFFER)
@ -388,8 +469,16 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa
let compute_out_storage_size = vk::DescriptorPoolSize::builder()
.type_(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(data.swapchain_images.len() as u32);
let compute_out_cuboid_size = vk::DescriptorPoolSize::builder()
.type_(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(data.swapchain_images.len() as u32);
let compute_out_cuboid_index_size = vk::DescriptorPoolSize::builder()
.type_(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(data.swapchain_images.len() as u32);
let pool_sizes = &[ubo_size, sampler_size, render_storage_size, compute_in_storage_size, compute_out_storage_size];
let pool_sizes = &[ubo_size, sampler_size, render_storage_size, compute_in_storage_size, compute_out_storage_size, compute_out_cuboid_size, compute_out_cuboid_index_size];
let info = vk::DescriptorPoolCreateInfo::builder()
.pool_sizes(pool_sizes)
.max_sets(data.swapchain_images.len() as u32);
@ -462,7 +551,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa
let info = vk::DescriptorBufferInfo::builder()
.buffer(data.compute_out_storage_buffers[i])
.offset(0)
.range(data.scene_rt_memory_size);
.range(data.compute_task_one_out_buffer_size);
let storage_info = &[info];
let storage_write_compute_out = vk::WriteDescriptorSet::builder()
@ -471,10 +560,36 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa
.dst_array_element(0)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.buffer_info(storage_info);
let info = vk::DescriptorBufferInfo::builder()
.buffer(data.compute_out_cuboid_buffers[i])
.offset(0)
.range((size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size);
let storage_info = &[info];
let storage_write_compute_cuboid_out = vk::WriteDescriptorSet::builder()
.dst_set(data.descriptor_sets[i])
.dst_binding(5)
.dst_array_element(0)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.buffer_info(storage_info);
let info = vk::DescriptorBufferInfo::builder()
.buffer(data.compute_out_cuboid_index_buffers[i])
.offset(0)
.range((size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size);
let storage_info = &[info];
let storage_write_compute_cuboid_index_out = vk::WriteDescriptorSet::builder()
.dst_set(data.descriptor_sets[i])
.dst_binding(6)
.dst_array_element(0)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.buffer_info(storage_info);
device.update_descriptor_sets(
&[ubo_write, sampler_write, storage_write_render, storage_write_compute_in, storage_write_compute_out],
&[ubo_write, sampler_write, storage_write_render, storage_write_compute_in, storage_write_compute_out, storage_write_compute_cuboid_out, storage_write_compute_cuboid_index_out],
&[] as &[vk::CopyDescriptorSet],
);
}

View file

@ -69,8 +69,29 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa
0,
&[data.descriptor_sets[i]],
&[]);
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 256.0).ceil() as u32, 1, 1);
let buffer_memory_barrier_vertex = vk::BufferMemoryBarrier::builder()
.buffer(data.compute_out_cuboid_buffers[i])
.src_access_mask(vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE)
.dst_access_mask(vk::AccessFlags::VERTEX_ATTRIBUTE_READ)
.size(vk::WHOLE_SIZE as u64)
.build();
let buffer_memory_barrier_index = vk::BufferMemoryBarrier::builder()
.buffer(data.compute_out_cuboid_index_buffers[i])
.src_access_mask(vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE)
.dst_access_mask(vk::AccessFlags::INDEX_READ)
.size(vk::WHOLE_SIZE as u64)
.build();
device.cmd_pipeline_barrier(*command_buffer,
vk::PipelineStageFlags::COMPUTE_SHADER,
vk::PipelineStageFlags::VERTEX_INPUT,
vk::DependencyFlags::DEVICE_GROUP,
&[] as &[vk::MemoryBarrier],
&[buffer_memory_barrier_index, buffer_memory_barrier_vertex],
&[] as &[vk::ImageMemoryBarrier]);
}
// start render pass
let clear_values = &[color_clear_value, depth_clear_value];
@ -122,6 +143,26 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa
device.cmd_draw_indexed(*command_buffer, scene_handler.indices_cuboid.len() as u32, 1, 0, 0, 0);
}
// draw sized vertices from compute shader
if scene_handler.volumetrics.len() != 0 {
device.cmd_bind_pipeline(
*command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_cuboid);
device.cmd_bind_vertex_buffers(*command_buffer, 0, &[data.compute_out_cuboid_buffers[i]], &[0]);
device.cmd_bind_index_buffer(*command_buffer, data.compute_out_cuboid_index_buffers[i], 0, vk::IndexType::UINT32);
device.cmd_bind_descriptor_sets(
*command_buffer,
vk::PipelineBindPoint::GRAPHICS,
data.pipeline_layout,
0,
&[data.descriptor_sets[i]],
&[],
);
device.cmd_draw_indexed(*command_buffer, (data.compute_task_one_out_size * 36) as u32, 1, 0, 0, 0);
}
if scene_handler.rt_vertices.len() != 0 {
device.cmd_bind_pipeline(

View file

@ -57,7 +57,8 @@ const VALIDATION_ENABLED: bool =
const VALIDATION_LAYER: vk::ExtensionName =
vk::ExtensionName::from_bytes(b"VK_LAYER_KHRONOS_validation");
const DEVICE_EXTENSIONS: &[vk::ExtensionName] = &[
vk::KHR_SWAPCHAIN_EXTENSION.name
vk::KHR_SWAPCHAIN_EXTENSION.name,
vk::EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION.name,
];
const MAX_FRAMES_IN_FLIGHT: usize = 30;
@ -288,6 +289,7 @@ impl App {
self.scene_handler.update_memory(&mut self.data, true)
}
buffer::update_render_storage_buffer(&self.instance, &self.device, &self.data, image_index, &self.scene_handler)?;
buffer::update_compute_storage_buffer(&self.instance, &self.device, &self.data, image_index, &self.scene_handler)?;
self.synchronized += 1
}
@ -424,6 +426,20 @@ impl App {
self.data.compute_out_storage_buffers_memory
.iter()
.for_each(|m| self.device.free_memory(*m, None));
self.data.compute_out_cuboid_buffers
.iter()
.for_each(|b| self.device.destroy_buffer(*b, None));
self.data.compute_out_cuboid_buffers_memory
.iter()
.for_each(|m| self.device.free_memory(*m, None));
self.data.compute_out_cuboid_index_buffers
.iter()
.for_each(|b| self.device.destroy_buffer(*b, None));
self.data.compute_out_cuboid_index_buffers_memory
.iter()
.for_each(|m| self.device.free_memory(*m, None));
self.data.framebuffers
.iter()

View file

@ -115,7 +115,7 @@ impl EmptyVolume {
// abort if it is already covered
continue;
}
println!("new starting pos: {}, {}, {}", x_index, y_index, z_index);
//println!("new starting pos: {}, {}, {}", x_index, y_index, z_index);
// MARK: Start new Volume
let mut x_size = 0;
let mut y_size = 0;
@ -127,9 +127,9 @@ impl EmptyVolume {
x_size = query_result.1 - 1 - (x_index - query_result.2.0);
y_size = query_result.1 - 1 - (y_index - query_result.2.1);
z_size = query_result.1 - 1 - (z_index - query_result.2.2);
println!("enhanced starting size: {}, {}, {}", x_size+1, y_size+1, z_size+1);
//println!("enhanced starting size: {}, {}, {}", x_size+1, y_size+1, z_size+1);
}
println!("start growing volume x");
//println!("start growing volume x");
let mut grow = true;
while grow {
grow &= (x_index + x_size + 1) < tree.borrow().size;
@ -179,7 +179,7 @@ impl EmptyVolume {
x_size += 1;
}
}
println!("start growing volume y");
//println!("start growing volume y");
grow = true;
while grow {
grow &= (y_index + y_size + 1) < tree.borrow().size;
@ -230,7 +230,7 @@ impl EmptyVolume {
y_size += 1;
}
}
println!("start growing volume z");
//println!("start growing volume z");
grow = true;
while grow {
grow &= (z_index + z_size + 1) < tree.borrow().size;
@ -280,7 +280,7 @@ impl EmptyVolume {
z_size += 1;
}
}
println!("final size: {}, {}, {}", x_size+1, y_size+1, z_size+1);
//println!("final size: {}, {}, {}", x_size+1, y_size+1, z_size+1);
// create new empty volume
let new_volume = EmptyVolume {
memory_start: 0,
@ -311,7 +311,7 @@ impl EmptyVolume {
old_memory_size: 0,
dirty: true,
};
println!("adding neighbor references");
//println!("adding neighbor references");
// MARK: fill in info in the neighbor octtree
let reference = Rc::new(RefCell::new(new_volume));
for x in 0..x_size+1 {
@ -325,7 +325,7 @@ impl EmptyVolume {
}
}
}
println!("add the border information for color and roughness");
//println!("add the border information for color and roughness");
let x_min_pos;
if reference.borrow().grid_position.x == 0 {
// will result in an empty color and roughness map.
@ -514,7 +514,7 @@ impl EmptyVolume {
reference.borrow_mut().roughness_right= vec![];
}
println!("new volume done");
//println!("new volume done");
//push to the list
volumes.push(reference);
}
@ -525,7 +525,7 @@ impl EmptyVolume {
x_index += 1;
}
println!("Did {} oct tree checks!", check_its);
println!("add the neighbor linkage for all the volumes of the oct tree");
//println!("add the neighbor linkage for all the volumes of the oct tree");
// MARK: Neighbor Linkage
for reference in volumes.iter_mut() {
let x_min_pos;

View file

@ -119,7 +119,9 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi
scene.oct_trees = vec![vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]], vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]]];
let mut comp = ShapeComposition::new(64);
comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.5, Vector3 { x: 255, y: 0, z: 0 }, 64))));
comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.0, Vector3 { x: 0, y: 255, z: 0 }, 64, false))));
comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.5, Vector3 { x: 255, y: 0, z: 0 }, 64, false))));
comp.excluded_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 11.5 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 1.5, Vector3 { x: 0, y: 255, z: 0 }, 64, false))));
scene.volumetrics.push(Rc::new(RefCell::new(comp)));
Ok((cgmath::point3(5.0, 5.0, 10.0)))

View file

@ -226,15 +226,18 @@ impl Scene {
let mut volumetrics_memory = vec![0; data_len];
let mut compute_task_one_size = 0;
let mut compute_task_one_out_size = 0;
for compound in &self.volumetrics {
volumetrics_memory = compound.borrow_mut().insert_into_memory(volumetrics_memory, data, &self);
compute_task_one_size += compound.borrow().size.pow(2) as usize;
compute_task_one_out_size += compound.borrow().size.pow(3) as usize;
}
self.volumetrics_memory = volumetrics_memory;
data.scene_rt_volumetric_size = (self.volumetrics_memory.len() * 4) as u64; // size of the needed buffer size in bytes
data.compute_task_one_size = compute_task_one_size;
data.compute_task_one_out_buffer_size = (compute_task_one_out_size * 4) as u64;
data.compute_task_one_out_size = compute_task_one_out_size as u64;
}
pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) {

View file

@ -15,6 +15,9 @@ pub trait Volumetrics: Memorizable {
fn set_rot(&mut self, p: Vector3<f32>);
fn get_bbox(&self) -> (Vector3<f32>,Vector3<f32>);
fn is_transparent(&self) -> bool;
fn set_transparency(&mut self, transparent: bool);
}
enum ShapeTypes {
@ -54,8 +57,8 @@ impl CompoundMemorizable for ShapeComposition {
impl Memorizable for ShapeComposition {
fn get_buffer_mem_size(&self, data: &AppData) -> u32 {
//size, scale, memory_end, num_included, num_excluded, pos, included_address, excluded_address
1 + 1 + 1 + 1 + 1 + 3 + self.included_shapes.len() as u32 + self.excluded_shapes.len() as u32
//size, scale, memory_end, num_included, num_excluded, pos, wrapping address, included_address, excluded_address
1 + 1 + 1 + 1 + 1 + 3 + 1 + self.included_shapes.len() as u32 + self.excluded_shapes.len() as u32
}
fn get_prev_buffer_mem_size(&self) -> u32 {
@ -74,7 +77,7 @@ impl Memorizable for ShapeComposition {
let mut bbox_low = Vector3 {x: f32::INFINITY, y: f32::INFINITY, z: f32::INFINITY};
let mut bbox_high = Vector3 {x: f32::NEG_INFINITY, y: f32::NEG_INFINITY, z: f32::NEG_INFINITY};
let mut element_offset = 8;
let mut element_offset = 9;
for volumetric in &self.included_shapes {
// create bbox for scale calculation. Only the included elements matter for the scale, as exclusion does not need to be fully included in the grid
let (l, h) = volumetric.borrow().get_bbox();
@ -102,13 +105,17 @@ impl Memorizable for ShapeComposition {
element_offset += 1;
}
v[self.memory_start + 1] = u32::from_ne_bytes((bbox_high.x.max(bbox_high.y.max(bbox_high.z)) - bbox_low.x.min(bbox_low.y.min(bbox_low.z)) / (self.size as f32)).to_ne_bytes());
let bbox_high_pos_ind = bbox_high - bbox_low;
let scale = bbox_high_pos_ind.x.max(bbox_high_pos_ind.y.max(bbox_high_pos_ind.z)) / (self.size as f32);
v[self.memory_start + 1] = u32::from_ne_bytes(scale.to_ne_bytes());
v[self.memory_start + 2] = (shapes_index + shapes_memory) as u32;
v[self.memory_start + 3] = self.included_shapes.len() as u32;
v[self.memory_start + 4] = self.excluded_shapes.len() as u32;
v[self.memory_start + 5] = u32::from_ne_bytes(bbox_low.x.to_ne_bytes());
v[self.memory_start + 6] = u32::from_ne_bytes(bbox_low.y.to_ne_bytes());
v[self.memory_start + 7] = u32::from_ne_bytes(bbox_low.z.to_ne_bytes());
v[self.memory_start + 8] = 0; //TODO add wrapping reference
self.prev_memory_size = self.get_compound_buffer_mem_size(data);
self.dirty = false;
@ -128,8 +135,9 @@ impl Memorizable for ShapeComposition {
pub struct Sphere {
pos: Vector3<f32>,
rot: Vector3<f32>, // rotation will only matter once textures are implemented, till then it is a holdover
radius: f32,
color: Vector3<u8>, // color, either as pure color or texture modifier
transparent: bool,
radius: f32,
roughness: u8,
memory_start: usize,
dirty: bool
@ -141,20 +149,21 @@ impl Sphere {
rot: Vector3<f32>,
radius: f32,
color: Vector3<u8>,
roughness: u8) -> Self {
Self { pos: pos, rot: rot, radius: radius, color: color, roughness: roughness, memory_start: 0, dirty: true }
roughness: u8,
transparent: bool) -> Self {
Self { pos: pos, rot: rot, radius: radius, color: color, roughness: roughness, memory_start: 0, dirty: true, transparent: transparent }
}
}
impl Memorizable for Sphere {
fn get_buffer_mem_size(&self, data: &AppData) -> u32 {
// type, pos, rot, radius, (color + roughness)
1 + 3 + 3 + 1 + 1
// type, pos, rot, (color + roughness), transparent, radius
1 + 3 + 3 + 1 + 1 + 1
}
fn get_prev_buffer_mem_size(&self) -> u32 {
// constant memory size
1 + 3 + 3 + 1 + 1
1 + 3 + 3 + 1 + 1 + 1
}
fn is_dirty(&self) -> bool {
self.dirty
@ -169,9 +178,11 @@ impl Memorizable for Sphere {
v[self.memory_start + 5] = u32::from_ne_bytes(self.rot.y.to_ne_bytes());
v[self.memory_start + 6] = u32::from_ne_bytes(self.rot.z.to_ne_bytes());
v[self.memory_start + 7] = u32::from_ne_bytes(self.radius.to_ne_bytes());
v[self.memory_start + 7] = u32::from_ne_bytes([self.color.x, self.color.y, self.color.z, self.roughness]);
v[self.memory_start + 8] = u32::from_ne_bytes([self.color.x, self.color.y, self.color.z, self.roughness]);
v[self.memory_start + 8] = self.transparent as u32;
v[self.memory_start + 9] = u32::from_ne_bytes(self.radius.to_ne_bytes());
v
}
@ -205,4 +216,12 @@ impl Volumetrics for Sphere {
let rad_vec = Vector3 {x: self.radius, y: self.radius, z: self.radius};
(self.pos - rad_vec, self.pos + rad_vec)
}
fn is_transparent(&self) -> bool {
self.transparent
}
fn set_transparency(&mut self, transparent: bool) {
self.transparent = transparent;
}
}