Make subdivision parameterised
This commit is contained in:
+17
-1
@@ -4,7 +4,10 @@ use egui::{Color32, Frame, Id};
|
||||
use egui_plot::{Line, Plot, PlotPoints};
|
||||
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) {
|
||||
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.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.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
|
||||
.into_iter()
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#ifndef implicit_include
|
||||
#define implicit_include
|
||||
|
||||
#extension GL_GOOGLE_include_directive:require
|
||||
#include "include.glsl"
|
||||
|
||||
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 lowest_corner;
|
||||
uint material;
|
||||
uint subdivision_log2;
|
||||
float farplane;
|
||||
} object_uniforms;
|
||||
|
||||
float scene(vec4 p) {
|
||||
|
||||
+12
-9
@@ -1,6 +1,18 @@
|
||||
#ifndef 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 {
|
||||
mat4 world;
|
||||
mat4 inv_world;
|
||||
@@ -18,13 +30,4 @@ layout(set = 0, binding = 1) uniform Camera {
|
||||
vec4 campos_and_time;
|
||||
} 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
|
||||
|
||||
+51
-1
@@ -8,6 +8,10 @@ const PIPELINE_CACHING: 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::{
|
||||
error::Error,
|
||||
fs::{File, remove_file, rename},
|
||||
@@ -877,6 +881,7 @@ impl ApplicationHandler for App {
|
||||
self.block_enable_allocator.clone(),
|
||||
self.descriptor_set_allocator.clone(),
|
||||
rcx.swapchain.image_count(),
|
||||
DEFAULT_SUBDIVISION,
|
||||
0,
|
||||
))
|
||||
.unwrap();
|
||||
@@ -1175,7 +1180,15 @@ impl App {
|
||||
.push_constants(csg.trace_pipeline.layout().clone(), 0, push_constants[i])
|
||||
.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.descriptor_set_allocator.clone(),
|
||||
rcx.swapchain.image_count(),
|
||||
DEFAULT_SUBDIVISION,
|
||||
-1,
|
||||
))
|
||||
.unwrap();
|
||||
@@ -1385,6 +1399,37 @@ impl App {
|
||||
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();
|
||||
|
||||
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_ALL: u32 = 6;
|
||||
const SPEC_DISABLE_AO: u32 = 7;
|
||||
const SPEC_MAXIMUM_SUBDISIVION: u32 = 30;
|
||||
|
||||
let mut spec_constants = HashMap::with_capacity(6);
|
||||
spec_constants.insert(
|
||||
@@ -1729,6 +1775,10 @@ fn get_spec_constants(debug: &PreviousDebug) -> HashMap<u32, SpecializationConst
|
||||
SPEC_DISABLE_AO,
|
||||
SpecializationConstant::Bool(debug.disable_ao),
|
||||
);
|
||||
spec_constants.insert(
|
||||
SPEC_MAXIMUM_SUBDISIVION,
|
||||
SpecializationConstant::U32(MAXIMUM_SUBDIVISION),
|
||||
);
|
||||
|
||||
trace!("Specs: {:?}", spec_constants);
|
||||
|
||||
|
||||
+4
-1
@@ -9,7 +9,8 @@ use vulkano::{
|
||||
memory::allocator::{
|
||||
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};
|
||||
@@ -42,10 +43,12 @@ pub(crate) struct CSG {
|
||||
pub(crate) pos: Vec3,
|
||||
pub(crate) rot: Vec3,
|
||||
pub(crate) scale: Vec3,
|
||||
pub(crate) new_pipelines_needed: bool,
|
||||
pub(crate) trace_shader_module: Arc<ShaderModule>,
|
||||
pub(crate) normals_shader_module: Arc<ShaderModule>,
|
||||
pub(crate) trace_pipeline: Arc<GraphicsPipeline>,
|
||||
pub(crate) normals_pipeline: Arc<GraphicsPipeline>,
|
||||
pub(crate) subdivision: u32,
|
||||
pub(crate) enable_buffer: Vec<Subbuffer<Object>>,
|
||||
pub(crate) trace_descriptor_set: Vec<Arc<DescriptorSet>>,
|
||||
pub(crate) normals_descriptor_set: Vec<Arc<DescriptorSet>>,
|
||||
|
||||
+43
-29
@@ -36,7 +36,8 @@ use vulkano::{
|
||||
};
|
||||
|
||||
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,
|
||||
interpreter::{self, IntervalInterpreter, PointInterpreter, VALUE_0},
|
||||
objects::CSG,
|
||||
@@ -58,6 +59,7 @@ pub enum WorkItem {
|
||||
Arc<Mutex<SubbufferAllocator>>,
|
||||
Arc<StandardDescriptorSetAllocator>,
|
||||
u32,
|
||||
u32,
|
||||
isize,
|
||||
),
|
||||
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,
|
||||
descriptor_set_allocator,
|
||||
frames,
|
||||
subdivision,
|
||||
index,
|
||||
) => {
|
||||
let csg_start = Instant::now();
|
||||
@@ -168,10 +171,12 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
|
||||
pos: Vec3::ZERO,
|
||||
rot: Vec3::ZERO,
|
||||
scale: Vec3::ONE,
|
||||
new_pipelines_needed: false,
|
||||
trace_shader_module,
|
||||
normals_shader_module,
|
||||
trace_pipeline,
|
||||
normals_pipeline,
|
||||
subdivision,
|
||||
enable_buffer,
|
||||
trace_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(),
|
||||
debug,
|
||||
);
|
||||
csg.new_pipelines_needed = false;
|
||||
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 =
|
||||
Vec3::new(interpreter_out[3], interpreter_out[4], interpreter_out[5]) - EPSILON;
|
||||
|
||||
const XDIM: usize = 16;
|
||||
const YDIM: usize = 16;
|
||||
const ZDIM: usize = 16;
|
||||
// csg.subdivision must be a power of 2
|
||||
assert_eq!(csg.subdivision.count_ones(), 1);
|
||||
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 {
|
||||
dimensions: (highest_corner - lowest_corner).to_array().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,
|
||||
subdivision_log2: csg.subdivision.ilog2(),
|
||||
farplane: (highest_corner - lowest_corner).length() / csg.subdivision as f32,
|
||||
};
|
||||
|
||||
for x in 0..XDIM {
|
||||
for y in 0..YDIM {
|
||||
for z in 0..(ZDIM / 8) {
|
||||
for x in 0..xdim {
|
||||
for y in 0..ydim {
|
||||
for z in 0..(zdim / 8) {
|
||||
let interval_input_z: Interval = Interval::new_unchecked(
|
||||
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.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.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.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.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.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.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.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.lowest_corner[2],
|
||||
]),
|
||||
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.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.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.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.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.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.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.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.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 output = interpreter.scene(
|
||||
Interval::const_splat2(
|
||||
(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 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(
|
||||
(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 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::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))
|
||||
.to_bitmask() as u32)
|
||||
<< (total_index & 31);
|
||||
|
||||
+3
-2
@@ -10,7 +10,6 @@ layout(depth_greater) out float gl_FragDepth;
|
||||
layout(location = 0) out uint material;
|
||||
|
||||
const float EPSILON = .001;
|
||||
float FARPLANE = SPEC_BRUTE_FORCE ? length(object_uniforms.dimensions) : length(object_uniforms.dimensions / 16.);
|
||||
|
||||
void main() {
|
||||
if (SPEC_BOUNDING_BOXES) {
|
||||
@@ -21,6 +20,8 @@ void main() {
|
||||
vec3 raypos = pos.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;
|
||||
float total_dist = 0.;
|
||||
do {
|
||||
@@ -32,7 +33,7 @@ void main() {
|
||||
gl_FragDepth = (tpoint.z / tpoint.w);
|
||||
material = object_uniforms.material;
|
||||
return;
|
||||
} else if (total_dist > FARPLANE) {
|
||||
} else if (total_dist > farplane) {
|
||||
discard;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
+8
-4
@@ -17,9 +17,12 @@ void main() {
|
||||
pos = vec4((position * object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.);
|
||||
} else {
|
||||
vec3 internal_pos = vec3(
|
||||
float((base_index >> 8) & 15) / 16.0,
|
||||
float((base_index >> 4) & 15) / 16.0,
|
||||
float((base_index >> 0) & 15) / 16.0
|
||||
float((base_index >> (object_uniforms.subdivision_log2 * 2)) & ((1 << object_uniforms.subdivision_log2) - 1))
|
||||
/ float(1 << object_uniforms.subdivision_log2),
|
||||
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;
|
||||
@@ -43,7 +46,8 @@ void main() {
|
||||
gl_Position = vec4(0.0 / 0.0);
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user