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 loader;
|
||||
mod renderer;
|
||||
mod ui;
|
||||
|
||||
use crate::renderer::Renderer;
|
||||
use crate::ui::DebugUI;
|
||||
use camera::FirstPerson;
|
||||
use itertools::Either;
|
||||
|
|
@ -56,13 +58,12 @@ fn main() -> Result<(), Error> {
|
|||
setup();
|
||||
|
||||
let mut args = args();
|
||||
let _bin = args.next().unwrap();
|
||||
let bin = args.next().unwrap();
|
||||
let file = match args.next() {
|
||||
Some(file) => file,
|
||||
None => {
|
||||
"koth_bagel_rc2a.bsp".into()
|
||||
// eprintln!("usage: {} <file.bsp>", bin);
|
||||
// return Ok(());
|
||||
eprintln!("usage: {} <file.bsp>", bin);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -72,24 +73,9 @@ fn main() -> Result<(), Error> {
|
|||
..Default::default()
|
||||
})?;
|
||||
|
||||
let context = window.gl().unwrap();
|
||||
let mut renderer = Renderer::new(&window)?;
|
||||
|
||||
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 {
|
||||
albedo: Color {
|
||||
r: 128,
|
||||
|
|
@ -101,132 +87,16 @@ fn main() -> Result<(), Error> {
|
|||
};
|
||||
|
||||
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
|
||||
.static_props()
|
||||
.map(|prop| load_prop(&loader, prop))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
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 {
|
||||
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()
|
||||
})?;
|
||||
window.render_loop(move |frame_input| renderer.render(frame_input).unwrap())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -250,8 +120,8 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
|
|||
.flat_map(|face| {
|
||||
face.displacement()
|
||||
.map(|displacement| displacement.triangulated_displaced_vertices())
|
||||
.map(|verts| Either::Left(verts))
|
||||
.unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts)))
|
||||
.map(Either::Left)
|
||||
.unwrap_or_else(|| Either::Right(face.triangulate().flatten()))
|
||||
})
|
||||
.flat_map(map_coords)
|
||||
.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