Make subdivision parameterised

This commit is contained in:
2025-07-11 15:24:17 +01:00
parent fcac31e796
commit 1bbac92645
8 changed files with 144 additions and 48 deletions
+17 -1
View File
@@ -4,7 +4,10 @@ use egui::{Color32, Frame, Id};
use egui_plot::{Line, Plot, PlotPoints}; use egui_plot::{Line, Plot, PlotPoints};
use egui_winit_vulkano::Gui; use egui_winit_vulkano::Gui;
use crate::objects::{CSG, Light, Mesh}; use crate::{
MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION,
objects::{CSG, Light, Mesh},
};
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) { fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
ui.label(egui::RichText::new(text).size(size)); ui.label(egui::RichText::new(text).size(size));
@@ -145,6 +148,19 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState, new_csg_needed: &mut boo
ui.add(egui::Slider::new(&mut csg.scale.x, 0.0..=2.0).text("Scale.x")); ui.add(egui::Slider::new(&mut csg.scale.x, 0.0..=2.0).text("Scale.x"));
ui.add(egui::Slider::new(&mut csg.scale.y, 0.0..=2.0).text("Scale.y")); ui.add(egui::Slider::new(&mut csg.scale.y, 0.0..=2.0).text("Scale.y"));
ui.add(egui::Slider::new(&mut csg.scale.z, 0.0..=2.0).text("Scale.z")); ui.add(egui::Slider::new(&mut csg.scale.z, 0.0..=2.0).text("Scale.z"));
ui.horizontal(|ui| {
ui.label("Subdivision");
for x in MINUMUM_SUBDIVISION.ilog2()..=MAXIMUM_SUBDIVISION.ilog2() {
let subdivision = 1 << x;
csg.new_pipelines_needed |= ui
.selectable_value(
&mut csg.subdivision,
subdivision,
format!("{}", subdivision),
)
.clicked();
}
});
} }
for i in csgdel for i in csgdel
.into_iter() .into_iter()
+6 -1
View File
@@ -1,11 +1,16 @@
#ifndef implicit_include #ifndef implicit_include
#define implicit_include #define implicit_include
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
layout(set = 1, binding = 0) uniform Object { layout(set = 1, binding = 0) uniform Object {
uvec4 enable[(16*16*16)/(4*32)]; uvec4 enable[(SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION) / (4 * 32)];
vec3 dimensions; vec3 dimensions;
vec3 lowest_corner; vec3 lowest_corner;
uint material; uint material;
uint subdivision_log2;
float farplane;
} object_uniforms; } object_uniforms;
float scene(vec4 p) { float scene(vec4 p) {
+12 -9
View File
@@ -1,6 +1,18 @@
#ifndef glsl_include #ifndef glsl_include
#define glsl_include #define glsl_include
layout(constant_id = 0) const bool SPEC_BOUNDING_BOXES = false;
layout(constant_id = 1) const bool SPEC_BRUTE_FORCE = false;
layout(constant_id = 2) const bool SPEC_SHOW_AO = false;
layout(constant_id = 3) const bool SPEC_SHOW_NORMALS = false;
layout(constant_id = 4) const bool SPEC_SHOW_DEPTH = false;
layout(constant_id = 5) const bool SPEC_SHOW_ALBEDO = false;
layout(constant_id = 6) const bool SPEC_SHOW_ALL = false;
layout(constant_id = 7) const bool SPEC_DISABLE_AO = false;
//layout(constant_id = 30) const uint SPEC_MAXIMUM_SUBDIVISION = 64;
const uint SPEC_MAXIMUM_SUBDIVISION = 64;
layout(push_constant) uniform PushConstantData { layout(push_constant) uniform PushConstantData {
mat4 world; mat4 world;
mat4 inv_world; mat4 inv_world;
@@ -18,13 +30,4 @@ layout(set = 0, binding = 1) uniform Camera {
vec4 campos_and_time; vec4 campos_and_time;
} camera_uniforms; } camera_uniforms;
layout(constant_id = 0) const bool SPEC_BOUNDING_BOXES = false;
layout(constant_id = 1) const bool SPEC_BRUTE_FORCE = false;
layout(constant_id = 2) const bool SPEC_SHOW_AO = false;
layout(constant_id = 3) const bool SPEC_SHOW_NORMALS = false;
layout(constant_id = 4) const bool SPEC_SHOW_DEPTH = false;
layout(constant_id = 5) const bool SPEC_SHOW_ALBEDO = false;
layout(constant_id = 6) const bool SPEC_SHOW_ALL = false;
layout(constant_id = 7) const bool SPEC_DISABLE_AO = false;
#endif #endif
+51 -1
View File
@@ -8,6 +8,10 @@ const PIPELINE_CACHING: bool = false;
const BYTECODE_IMITATES_GLSL: bool = false; const BYTECODE_IMITATES_GLSL: bool = false;
const DEFAULT_SUBDIVISION: u32 = 16;
const MAXIMUM_SUBDIVISION: u32 = 64;
const MINUMUM_SUBDIVISION: u32 = 8;
use std::{ use std::{
error::Error, error::Error,
fs::{File, remove_file, rename}, fs::{File, remove_file, rename},
@@ -877,6 +881,7 @@ impl ApplicationHandler for App {
self.block_enable_allocator.clone(), self.block_enable_allocator.clone(),
self.descriptor_set_allocator.clone(), self.descriptor_set_allocator.clone(),
rcx.swapchain.image_count(), rcx.swapchain.image_count(),
DEFAULT_SUBDIVISION,
0, 0,
)) ))
.unwrap(); .unwrap();
@@ -1175,7 +1180,15 @@ impl App {
.push_constants(csg.trace_pipeline.layout().clone(), 0, push_constants[i]) .push_constants(csg.trace_pipeline.layout().clone(), 0, push_constants[i])
.unwrap(); .unwrap();
unsafe { builder.draw(VERTEX_COUNT as u32, 16 * 16 * 16, 0, 0) }.unwrap(); unsafe {
builder.draw(
VERTEX_COUNT as u32,
csg.subdivision * csg.subdivision * csg.subdivision,
0,
0,
)
}
.unwrap();
} }
} }
@@ -1297,6 +1310,7 @@ impl App {
self.block_enable_allocator.clone(), self.block_enable_allocator.clone(),
self.descriptor_set_allocator.clone(), self.descriptor_set_allocator.clone(),
rcx.swapchain.image_count(), rcx.swapchain.image_count(),
DEFAULT_SUBDIVISION,
-1, -1,
)) ))
.unwrap(); .unwrap();
@@ -1385,6 +1399,37 @@ impl App {
rcx.recreate_pipelines = false; rcx.recreate_pipelines = false;
} }
{
let mut csg_left = 0;
for (i, csg) in self.gstate.csg.iter().enumerate() {
let rcsg = csg.read().unwrap();
if rcsg.new_pipelines_needed {
self.thread_work_creation
.send(WorkItem::RecompilePipelines(
csg.clone(),
self.device.clone(),
rcx.render_pass.clone(),
self.pipeline_cache.clone(),
rcx.shader_modules.clone(),
self.previous_debug.clone(),
i,
))
.unwrap();
csg_left += 1;
}
}
while csg_left > 0 {
for work in self.thread_work_completion.try_iter() {
match work {
WorkComplete::RecompilePipelines(index) => {
csg_left -= 1;
},
other => work_for_later.push(other),
}
}
}
}
self.move_camera(); self.move_camera();
let (image_index, suboptimal, acquire_future) = let (image_index, suboptimal, acquire_future) =
@@ -1701,6 +1746,7 @@ fn get_spec_constants(debug: &PreviousDebug) -> HashMap<u32, SpecializationConst
const SPEC_SHOW_ALBEDO: u32 = 5; const SPEC_SHOW_ALBEDO: u32 = 5;
const SPEC_SHOW_ALL: u32 = 6; const SPEC_SHOW_ALL: u32 = 6;
const SPEC_DISABLE_AO: u32 = 7; const SPEC_DISABLE_AO: u32 = 7;
const SPEC_MAXIMUM_SUBDISIVION: u32 = 30;
let mut spec_constants = HashMap::with_capacity(6); let mut spec_constants = HashMap::with_capacity(6);
spec_constants.insert( spec_constants.insert(
@@ -1729,6 +1775,10 @@ fn get_spec_constants(debug: &PreviousDebug) -> HashMap<u32, SpecializationConst
SPEC_DISABLE_AO, SPEC_DISABLE_AO,
SpecializationConstant::Bool(debug.disable_ao), SpecializationConstant::Bool(debug.disable_ao),
); );
spec_constants.insert(
SPEC_MAXIMUM_SUBDISIVION,
SpecializationConstant::U32(MAXIMUM_SUBDIVISION),
);
trace!("Specs: {:?}", spec_constants); trace!("Specs: {:?}", spec_constants);
+4 -1
View File
@@ -9,7 +9,8 @@ use vulkano::{
memory::allocator::{ memory::allocator::{
AllocationCreateInfo, MemoryAllocatePreference, MemoryTypeFilter, StandardMemoryAllocator, AllocationCreateInfo, MemoryAllocatePreference, MemoryTypeFilter, StandardMemoryAllocator,
}, },
pipeline::{graphics::vertex_input::Vertex, GraphicsPipeline}, shader::ShaderModule, pipeline::{GraphicsPipeline, graphics::vertex_input::Vertex},
shader::ShaderModule,
}; };
use crate::{ssa::SSATape, trace_vs::Object}; use crate::{ssa::SSATape, trace_vs::Object};
@@ -42,10 +43,12 @@ pub(crate) struct CSG {
pub(crate) pos: Vec3, pub(crate) pos: Vec3,
pub(crate) rot: Vec3, pub(crate) rot: Vec3,
pub(crate) scale: Vec3, pub(crate) scale: Vec3,
pub(crate) new_pipelines_needed: bool,
pub(crate) trace_shader_module: Arc<ShaderModule>, pub(crate) trace_shader_module: Arc<ShaderModule>,
pub(crate) normals_shader_module: Arc<ShaderModule>, pub(crate) normals_shader_module: Arc<ShaderModule>,
pub(crate) trace_pipeline: Arc<GraphicsPipeline>, pub(crate) trace_pipeline: Arc<GraphicsPipeline>,
pub(crate) normals_pipeline: Arc<GraphicsPipeline>, pub(crate) normals_pipeline: Arc<GraphicsPipeline>,
pub(crate) subdivision: u32,
pub(crate) enable_buffer: Vec<Subbuffer<Object>>, pub(crate) enable_buffer: Vec<Subbuffer<Object>>,
pub(crate) trace_descriptor_set: Vec<Arc<DescriptorSet>>, pub(crate) trace_descriptor_set: Vec<Arc<DescriptorSet>>,
pub(crate) normals_descriptor_set: Vec<Arc<DescriptorSet>>, pub(crate) normals_descriptor_set: Vec<Arc<DescriptorSet>>,
+43 -29
View File
@@ -36,7 +36,8 @@ use vulkano::{
}; };
use crate::{ use crate::{
DUMP_SPV_TO_FILE, IVertex, ShaderModules, get_spec_constants, DUMP_SPV_TO_FILE, IVertex, MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION, ShaderModules,
get_spec_constants,
gui::PreviousDebug, gui::PreviousDebug,
interpreter::{self, IntervalInterpreter, PointInterpreter, VALUE_0}, interpreter::{self, IntervalInterpreter, PointInterpreter, VALUE_0},
objects::CSG, objects::CSG,
@@ -58,6 +59,7 @@ pub enum WorkItem {
Arc<Mutex<SubbufferAllocator>>, Arc<Mutex<SubbufferAllocator>>,
Arc<StandardDescriptorSetAllocator>, Arc<StandardDescriptorSetAllocator>,
u32, u32,
u32,
isize, isize,
), ),
GetPushConstants(Arc<RwLock<CSG>>, f32, usize, usize), GetPushConstants(Arc<RwLock<CSG>>, f32, usize, usize),
@@ -93,6 +95,7 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
block_enable_allocator, block_enable_allocator,
descriptor_set_allocator, descriptor_set_allocator,
frames, frames,
subdivision,
index, index,
) => { ) => {
let csg_start = Instant::now(); let csg_start = Instant::now();
@@ -168,10 +171,12 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
pos: Vec3::ZERO, pos: Vec3::ZERO,
rot: Vec3::ZERO, rot: Vec3::ZERO,
scale: Vec3::ONE, scale: Vec3::ONE,
new_pipelines_needed: false,
trace_shader_module, trace_shader_module,
normals_shader_module, normals_shader_module,
trace_pipeline, trace_pipeline,
normals_pipeline, normals_pipeline,
subdivision,
enable_buffer, enable_buffer,
trace_descriptor_set, trace_descriptor_set,
normals_descriptor_set, normals_descriptor_set,
@@ -226,6 +231,7 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
csg.normals_shader_module.clone(), csg.normals_shader_module.clone(),
debug, debug,
); );
csg.new_pipelines_needed = false;
send.send(WorkComplete::RecompilePipelines(index)).unwrap(); send.send(WorkComplete::RecompilePipelines(index)).unwrap();
}, },
} }
@@ -466,70 +472,78 @@ fn interval_check(csg: &CSG, material: u32, time: f32, frame_index: usize) {
let lowest_corner = let lowest_corner =
Vec3::new(interpreter_out[3], interpreter_out[4], interpreter_out[5]) - EPSILON; Vec3::new(interpreter_out[3], interpreter_out[4], interpreter_out[5]) - EPSILON;
const XDIM: usize = 16; // csg.subdivision must be a power of 2
const YDIM: usize = 16; assert_eq!(csg.subdivision.count_ones(), 1);
const ZDIM: usize = 16; assert!(csg.subdivision <= MAXIMUM_SUBDIVISION);
assert!(csg.subdivision >= MINUMUM_SUBDIVISION);
let xdim = csg.subdivision as usize;
let ydim = csg.subdivision as usize;
let zdim = csg.subdivision as usize;
let mut obj = Object { let mut obj = Object {
dimensions: (highest_corner - lowest_corner).to_array().into(), dimensions: (highest_corner - lowest_corner).to_array().into(),
lowest_corner: lowest_corner.into(), lowest_corner: lowest_corner.into(),
enable: [[0; 4]; (XDIM * YDIM * ZDIM) / (32 * 4)], enable: [[0; 4];
(MAXIMUM_SUBDIVISION * MAXIMUM_SUBDIVISION * MAXIMUM_SUBDIVISION) as usize / (32 * 4)],
material, material,
subdivision_log2: csg.subdivision.ilog2(),
farplane: (highest_corner - lowest_corner).length() / csg.subdivision as f32,
}; };
for x in 0..XDIM { for x in 0..xdim {
for y in 0..YDIM { for y in 0..ydim {
for z in 0..(ZDIM / 8) { for z in 0..(zdim / 8) {
let interval_input_z: Interval = Interval::new_unchecked( let interval_input_z: Interval = Interval::new_unchecked(
interpreter::Value::from_array([ interpreter::Value::from_array([
((((8.0 / (ZDIM as f32)) * z as f32) + (0.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (0.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (1.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (2.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (2.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (3.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (3.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (4.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (4.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (5.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (5.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (6.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (6.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (7.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (7.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
]), ]),
interpreter::Value::from_array([ interpreter::Value::from_array([
((((8.0 / (ZDIM as f32)) * z as f32) + (1.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (2.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (2.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (3.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (3.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (4.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (4.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (5.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (5.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (6.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (6.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (7.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (7.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
((((8.0 / (ZDIM as f32)) * z as f32) + (8.0 / (ZDIM as f32))) ((((8.0 / (zdim as f32)) * z as f32) + (8.0 / (zdim as f32)))
* obj.dimensions[2]) * obj.dimensions[2])
+ obj.lowest_corner[2], + obj.lowest_corner[2],
]), ]),
@@ -538,18 +552,18 @@ fn interval_check(csg: &CSG, material: u32, time: f32, frame_index: usize) {
let mut interpreter = IntervalInterpreter::new(csg); let mut interpreter = IntervalInterpreter::new(csg);
let output = interpreter.scene( let output = interpreter.scene(
Interval::const_splat2( Interval::const_splat2(
(x as f32 / (XDIM as f32)) * obj.dimensions[0] + obj.lowest_corner[0], (x as f32 / (xdim as f32)) * obj.dimensions[0] + obj.lowest_corner[0],
((x + 1) as f32 / (XDIM as f32)) * obj.dimensions[0] + obj.lowest_corner[0], ((x + 1) as f32 / (xdim as f32)) * obj.dimensions[0] + obj.lowest_corner[0],
), ),
Interval::const_splat2( Interval::const_splat2(
(y as f32 / (YDIM as f32)) * obj.dimensions[1] + obj.lowest_corner[1], (y as f32 / (ydim as f32)) * obj.dimensions[1] + obj.lowest_corner[1],
((y + 1) as f32 / (YDIM as f32)) * obj.dimensions[1] + obj.lowest_corner[1], ((y + 1) as f32 / (ydim as f32)) * obj.dimensions[1] + obj.lowest_corner[1],
), ),
interval_input_z, interval_input_z,
Interval::const_splat(time), Interval::const_splat(time),
); );
let total_index = (x * ZDIM * YDIM) + (y * ZDIM) + (z * 8); let total_index = (x * zdim * ydim) + (y * zdim) + (z * 8);
let output = ((output.lower().simd_le(VALUE_0) & output.upper().simd_ge(VALUE_0)) let output = ((output.lower().simd_le(VALUE_0) & output.upper().simd_ge(VALUE_0))
.to_bitmask() as u32) .to_bitmask() as u32)
<< (total_index & 31); << (total_index & 31);
+3 -2
View File
@@ -10,7 +10,6 @@ layout(depth_greater) out float gl_FragDepth;
layout(location = 0) out uint material; layout(location = 0) out uint material;
const float EPSILON = .001; const float EPSILON = .001;
float FARPLANE = SPEC_BRUTE_FORCE ? length(object_uniforms.dimensions) : length(object_uniforms.dimensions / 16.);
void main() { void main() {
if (SPEC_BOUNDING_BOXES) { if (SPEC_BOUNDING_BOXES) {
@@ -21,6 +20,8 @@ void main() {
vec3 raypos = pos.xyz; vec3 raypos = pos.xyz;
vec3 raydir = normalize(raypos - (pc.inv_world * vec4(camera_uniforms.campos_and_time.xyz, 1)).xyz); vec3 raydir = normalize(raypos - (pc.inv_world * vec4(camera_uniforms.campos_and_time.xyz, 1)).xyz);
float farplane = SPEC_BRUTE_FORCE ? length(object_uniforms.dimensions) : object_uniforms.farplane;
vec3 p = raypos; vec3 p = raypos;
float total_dist = 0.; float total_dist = 0.;
do { do {
@@ -32,7 +33,7 @@ void main() {
gl_FragDepth = (tpoint.z / tpoint.w); gl_FragDepth = (tpoint.z / tpoint.w);
material = object_uniforms.material; material = object_uniforms.material;
return; return;
} else if (total_dist > FARPLANE) { } else if (total_dist > farplane) {
discard; discard;
} }
} while (true); } while (true);
+8 -4
View File
@@ -17,9 +17,12 @@ void main() {
pos = vec4((position * object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.); pos = vec4((position * object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.);
} else { } else {
vec3 internal_pos = vec3( vec3 internal_pos = vec3(
float((base_index >> 8) & 15) / 16.0, float((base_index >> (object_uniforms.subdivision_log2 * 2)) & ((1 << object_uniforms.subdivision_log2) - 1))
float((base_index >> 4) & 15) / 16.0, / float(1 << object_uniforms.subdivision_log2),
float((base_index >> 0) & 15) / 16.0 float((base_index >> (object_uniforms.subdivision_log2 * 1)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2),
float((base_index >> (object_uniforms.subdivision_log2 * 0)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2)
); );
bool enable; bool enable;
@@ -43,7 +46,8 @@ void main() {
gl_Position = vec4(0.0 / 0.0); gl_Position = vec4(0.0 / 0.0);
return; return;
} }
pos = vec4((((position / 16.0) + internal_pos) * object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.); pos = vec4((((position / float(1 << object_uniforms.subdivision_log2)) + internal_pos)
* object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.);
} }
gl_Position = camera_uniforms.proj_view * pc.world * pos; gl_Position = camera_uniforms.proj_view * pc.world * pos;