mirror of
https://codeberg.org/icewind/vbspview.git
synced 2026-06-03 18:24:09 +02:00
split out some render logic
This commit is contained in:
parent
3971120204
commit
66a5e302b5
2 changed files with 169 additions and 142 deletions
154
src/main.rs
154
src/main.rs
|
|
@ -1,7 +1,9 @@
|
||||||
mod camera;
|
mod camera;
|
||||||
mod loader;
|
mod loader;
|
||||||
|
mod renderer;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::DebugUI;
|
use crate::ui::DebugUI;
|
||||||
use camera::FirstPerson;
|
use camera::FirstPerson;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
|
|
@ -56,13 +58,12 @@ fn main() -> Result<(), Error> {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let mut args = args();
|
let mut args = args();
|
||||||
let _bin = args.next().unwrap();
|
let bin = args.next().unwrap();
|
||||||
let file = match args.next() {
|
let file = match args.next() {
|
||||||
Some(file) => file,
|
Some(file) => file,
|
||||||
None => {
|
None => {
|
||||||
"koth_bagel_rc2a.bsp".into()
|
eprintln!("usage: {} <file.bsp>", bin);
|
||||||
// eprintln!("usage: {} <file.bsp>", bin);
|
return Ok(());
|
||||||
// return Ok(());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -72,24 +73,9 @@ fn main() -> Result<(), Error> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let context = window.gl().unwrap();
|
let mut renderer = Renderer::new(&window)?;
|
||||||
|
|
||||||
let (cpu_mesh, bsp) = load_world(file.as_ref())?;
|
let (cpu_mesh, bsp) = load_world(file.as_ref())?;
|
||||||
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
|
|
||||||
let mut camera = Camera::new_perspective(
|
|
||||||
&context,
|
|
||||||
window.viewport().unwrap(),
|
|
||||||
vec3(9.0, 4.0, 5.0),
|
|
||||||
vec3(0.0, 0.0, 0.0),
|
|
||||||
vec3(0.0, 1.0, 0.0),
|
|
||||||
degrees(90.0),
|
|
||||||
0.1,
|
|
||||||
30.0,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let mut control = FirstPerson::new(0.1);
|
|
||||||
let mut gui = DebugUI::new(&context)?;
|
|
||||||
|
|
||||||
let material = PhysicalMaterial {
|
let material = PhysicalMaterial {
|
||||||
albedo: Color {
|
albedo: Color {
|
||||||
r: 128,
|
r: 128,
|
||||||
|
|
@ -101,132 +87,16 @@ fn main() -> Result<(), Error> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let loader = Loader::new(bsp.pack.clone())?;
|
let loader = Loader::new(bsp.pack.clone())?;
|
||||||
let model = Model::new_with_material(&context, &cpu_mesh, material.clone())?;
|
let model = Model::new_with_material(&renderer.context, &cpu_mesh, material.clone())?;
|
||||||
let props = bsp
|
let props = bsp
|
||||||
.static_props()
|
.static_props()
|
||||||
.map(|prop| load_prop(&loader, prop))
|
.map(|prop| load_prop(&loader, prop))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let merged_props = merge_meshes(props);
|
let merged_props = merge_meshes(props);
|
||||||
let props_model = Model::new_with_material(&context, &merged_props, material)?;
|
let props_model = Model::new_with_material(&renderer.context, &merged_props, material)?;
|
||||||
|
renderer.models = vec![model, props_model];
|
||||||
|
|
||||||
let mut lights = Lights {
|
window.render_loop(move |frame_input| renderer.render(frame_input).unwrap())?;
|
||||||
ambient: Some(AmbientLight {
|
|
||||||
color: Color::WHITE,
|
|
||||||
intensity: 0.2,
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
directional: vec![
|
|
||||||
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, -1.0, 0.0))?,
|
|
||||||
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, 1.0, 0.0))?,
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
window.render_loop(move |mut frame_input| {
|
|
||||||
let (ui_change, panel_width) = gui.update(&mut frame_input, &camera).unwrap();
|
|
||||||
let mut change = frame_input.first_frame || ui_change;
|
|
||||||
if change {
|
|
||||||
if gui.shadows_enabled {
|
|
||||||
lights.directional[0]
|
|
||||||
.generate_shadow_map(4.0, 1024, 1024, &[&model])
|
|
||||||
.unwrap();
|
|
||||||
lights.directional[1]
|
|
||||||
.generate_shadow_map(4.0, 1024, 1024, &[&model])
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
lights.directional[0].clear_shadow_map();
|
|
||||||
lights.directional[1].clear_shadow_map();
|
|
||||||
}
|
|
||||||
lights.directional[0].set_intensity(gui.directional_intensity);
|
|
||||||
lights.directional[1].set_intensity(gui.directional_intensity);
|
|
||||||
lights.ambient.as_mut().unwrap().intensity = gui.ambient_intensity;
|
|
||||||
camera
|
|
||||||
.set_perspective_projection(degrees(gui.fov), camera.z_near(), camera.z_far())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let viewport = Viewport {
|
|
||||||
x: panel_width as i32,
|
|
||||||
y: 0,
|
|
||||||
width: frame_input.viewport.width - panel_width,
|
|
||||||
height: frame_input.viewport.height,
|
|
||||||
};
|
|
||||||
change |= camera.set_viewport(viewport).unwrap();
|
|
||||||
change |= control
|
|
||||||
.handle_events(&mut camera, &mut frame_input.events)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
{
|
|
||||||
// Light pass
|
|
||||||
Screen::write(&context, ClearState::default(), || {
|
|
||||||
match gui.debug_type {
|
|
||||||
DebugType::NORMAL => {
|
|
||||||
model.render_with_material(
|
|
||||||
&NormalMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
props_model.render_with_material(
|
|
||||||
&NormalMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
DebugType::DEPTH => {
|
|
||||||
let mut depth_material = DepthMaterial::default();
|
|
||||||
depth_material.max_distance = Some(gui.depth_max);
|
|
||||||
model.render_with_material(&depth_material, &camera, &lights)?;
|
|
||||||
props_model.render_with_material(&depth_material, &camera, &lights)?;
|
|
||||||
}
|
|
||||||
DebugType::ORM => {
|
|
||||||
model.render_with_material(
|
|
||||||
&ORMMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
props_model.render_with_material(
|
|
||||||
&ORMMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
DebugType::POSITION => {
|
|
||||||
let position_material = PositionMaterial::default();
|
|
||||||
model.render_with_material(&position_material, &camera, &lights)?;
|
|
||||||
props_model.render_with_material(&position_material, &camera, &lights)?;
|
|
||||||
}
|
|
||||||
DebugType::UV => {
|
|
||||||
let uv_material = UVMaterial::default();
|
|
||||||
model.render_with_material(&uv_material, &camera, &lights)?;
|
|
||||||
props_model.render_with_material(&uv_material, &camera, &lights)?;
|
|
||||||
}
|
|
||||||
DebugType::COLOR => {
|
|
||||||
model.render_with_material(
|
|
||||||
&ColorMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
props_model.render_with_material(
|
|
||||||
&ColorMaterial::from_physical_material(&model.material),
|
|
||||||
&camera,
|
|
||||||
&lights,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
DebugType::NONE => {
|
|
||||||
forward_pipeline.render_pass(&camera, &[&model, &props_model], &lights)?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
gui.render()?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = change;
|
|
||||||
|
|
||||||
FrameOutput::default()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -250,8 +120,8 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
|
||||||
.flat_map(|face| {
|
.flat_map(|face| {
|
||||||
face.displacement()
|
face.displacement()
|
||||||
.map(|displacement| displacement.triangulated_displaced_vertices())
|
.map(|displacement| displacement.triangulated_displaced_vertices())
|
||||||
.map(|verts| Either::Left(verts))
|
.map(Either::Left)
|
||||||
.unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts)))
|
.unwrap_or_else(|| Either::Right(face.triangulate().flatten()))
|
||||||
})
|
})
|
||||||
.flat_map(map_coords)
|
.flat_map(map_coords)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
||||||
157
src/renderer.rs
Normal file
157
src/renderer.rs
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
use crate::{DebugUI, FirstPerson};
|
||||||
|
use three_d::*;
|
||||||
|
|
||||||
|
pub struct Renderer {
|
||||||
|
gui: DebugUI,
|
||||||
|
pub models: Vec<Model<PhysicalMaterial>>,
|
||||||
|
lights: Lights,
|
||||||
|
pub context: Context,
|
||||||
|
pipeline: ForwardPipeline,
|
||||||
|
control: FirstPerson,
|
||||||
|
camera: Camera,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn new(window: &Window) -> ThreeDResult<Self> {
|
||||||
|
let context = window.gl().unwrap();
|
||||||
|
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
|
||||||
|
let camera = Camera::new_perspective(
|
||||||
|
&context,
|
||||||
|
window.viewport().unwrap(),
|
||||||
|
vec3(9.0, 4.0, 5.0),
|
||||||
|
vec3(0.0, 0.0, 0.0),
|
||||||
|
vec3(0.0, 1.0, 0.0),
|
||||||
|
degrees(90.0),
|
||||||
|
0.1,
|
||||||
|
30.0,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let lights = Lights {
|
||||||
|
ambient: Some(AmbientLight {
|
||||||
|
color: Color::WHITE,
|
||||||
|
intensity: 0.2,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
directional: vec![
|
||||||
|
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, -1.0, 0.0))?,
|
||||||
|
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, 1.0, 0.0))?,
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let control = FirstPerson::new(0.1);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
models: Vec::new(),
|
||||||
|
gui: DebugUI::new(&context)?,
|
||||||
|
pipeline: forward_pipeline,
|
||||||
|
lights,
|
||||||
|
context,
|
||||||
|
control,
|
||||||
|
camera,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&mut self, mut frame_input: FrameInput) -> ThreeDResult<FrameOutput> {
|
||||||
|
let (ui_change, panel_width) = self.gui.update(&mut frame_input, &self.camera)?;
|
||||||
|
let change = frame_input.first_frame || ui_change;
|
||||||
|
if change {
|
||||||
|
if self.gui.shadows_enabled {
|
||||||
|
self.lights.directional[0]
|
||||||
|
.generate_shadow_map(4.0, 1024, 1024, &self.models)
|
||||||
|
.unwrap();
|
||||||
|
self.lights.directional[1]
|
||||||
|
.generate_shadow_map(4.0, 1024, 1024, &self.models)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
self.lights.directional[0].clear_shadow_map();
|
||||||
|
self.lights.directional[1].clear_shadow_map();
|
||||||
|
}
|
||||||
|
self.lights.directional[0].set_intensity(self.gui.directional_intensity);
|
||||||
|
self.lights.directional[1].set_intensity(self.gui.directional_intensity);
|
||||||
|
self.lights.ambient.as_mut().unwrap().intensity = self.gui.ambient_intensity;
|
||||||
|
self.camera
|
||||||
|
.set_perspective_projection(
|
||||||
|
degrees(self.gui.fov),
|
||||||
|
self.camera.z_near(),
|
||||||
|
self.camera.z_far(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let viewport = Viewport {
|
||||||
|
x: panel_width as i32,
|
||||||
|
y: 0,
|
||||||
|
width: frame_input.viewport.width - panel_width,
|
||||||
|
height: frame_input.viewport.height,
|
||||||
|
};
|
||||||
|
self.camera.set_viewport(viewport).unwrap();
|
||||||
|
self.control
|
||||||
|
.handle_events(&mut self.camera, &mut frame_input.events)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Light pass
|
||||||
|
Screen::write(&self.context, ClearState::default(), || {
|
||||||
|
match self.gui.debug_type {
|
||||||
|
DebugType::NORMAL => {
|
||||||
|
for model in &self.models {
|
||||||
|
model.render_with_material(
|
||||||
|
&NormalMaterial::from_physical_material(&model.material),
|
||||||
|
&self.camera,
|
||||||
|
&self.lights,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::DEPTH => {
|
||||||
|
let depth_material = DepthMaterial {
|
||||||
|
max_distance: Some(self.gui.depth_max),
|
||||||
|
..DepthMaterial::default()
|
||||||
|
};
|
||||||
|
for model in &self.models {
|
||||||
|
model.render_with_material(&depth_material, &self.camera, &self.lights)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::ORM => {
|
||||||
|
for model in &self.models {
|
||||||
|
model.render_with_material(
|
||||||
|
&ORMMaterial::from_physical_material(&model.material),
|
||||||
|
&self.camera,
|
||||||
|
&self.lights,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::POSITION => {
|
||||||
|
for model in &self.models {
|
||||||
|
let position_material = PositionMaterial::default();
|
||||||
|
model.render_with_material(
|
||||||
|
&position_material,
|
||||||
|
&self.camera,
|
||||||
|
&self.lights,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::UV => {
|
||||||
|
for model in &self.models {
|
||||||
|
let uv_material = UVMaterial::default();
|
||||||
|
model.render_with_material(&uv_material, &self.camera, &self.lights)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::COLOR => {
|
||||||
|
for model in &self.models {
|
||||||
|
model.render_with_material(
|
||||||
|
&ColorMaterial::from_physical_material(&model.material),
|
||||||
|
&self.camera,
|
||||||
|
&self.lights,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugType::NONE => {
|
||||||
|
self.pipeline
|
||||||
|
.render_pass(&self.camera, &self.models, &self.lights)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.gui.render()?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(FrameOutput::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue