Refactor: tray to solidify rendering API thing in preparation for extra renderers/drawers
parent
d9ae0c1f8e
commit
5651c58fcc
|
@ -171,7 +171,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "golem"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/flukejones/golem/#64f44879e06a33e836e737caee564e29315d554e"
|
||||
source = "git+https://github.com/flukejones/golem/#be66ac90add9739a71af2fe37967201e12e99ce6"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"glow",
|
||||
|
@ -407,6 +407,7 @@ name = "render-traits"
|
|||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"gameplay",
|
||||
"golem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -438,7 +439,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/Rust-SDL2/rust-sdl2#8613c502a6081ef1a218ad1d6aecf7c6bd7cf65c"
|
||||
source = "git+https://github.com/Rust-SDL2/rust-sdl2#9b167586bd3938da9187fc1e84b96afe71742ad5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static",
|
||||
|
@ -449,7 +450,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sdl2-sys"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/Rust-SDL2/rust-sdl2#8613c502a6081ef1a218ad1d6aecf7c6bd7cf65c"
|
||||
source = "git+https://github.com/Rust-SDL2/rust-sdl2#9b167586bd3938da9187fc1e84b96afe71742ad5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cmake",
|
||||
|
@ -459,18 +460,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.175"
|
||||
version = "1.0.176"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b"
|
||||
checksum = "76dc28c9523c5d70816e393136b86d48909cfb27cecaa902d338c19ed47164dc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.175"
|
||||
version = "1.0.176"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4"
|
||||
checksum = "a4e7b8c5dc823e3b90651ff1d3808419cd14e5ad76de04feaf37da114e7a306f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -2,7 +2,7 @@ mod text;
|
|||
|
||||
use crate::text::*;
|
||||
use gamestate_traits::{
|
||||
GameMode, GameTraits, MachinationTrait, MusTrack, PixelBuf, Scancode, TICRATE,
|
||||
GameMode, GameTraits, MachinationTrait, MusTrack, PixelBuffer, RenderTarget, Scancode, TICRATE,
|
||||
};
|
||||
use hud_util::{load_char_patches, HUDString, HUD_STRING};
|
||||
use wad::{
|
||||
|
@ -40,6 +40,25 @@ impl Finale {
|
|||
count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_pixels(&mut self, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
self.screen_width = pixels.width() as i32;
|
||||
self.screen_height = pixels.height() as i32;
|
||||
|
||||
let pal = &self.palette;
|
||||
for sx in (0..self.screen_width).step_by(64) {
|
||||
for sy in (0..self.screen_height).step_by(64) {
|
||||
for (y, col) in self.bg_flat.data.chunks(64).enumerate() {
|
||||
for (x, c) in col.iter().enumerate() {
|
||||
let c = &pal.0[*c as usize];
|
||||
pixels.set_pixel(sx as usize + x, sy as usize + y, (c.r, c.g, c.b, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.text.draw_pixels(6 * f, 6 * f, self, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
impl MachinationTrait for Finale {
|
||||
|
@ -134,22 +153,18 @@ impl MachinationTrait for Finale {
|
|||
&self.palette
|
||||
}
|
||||
|
||||
fn draw(&mut self, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
self.screen_width = buffer.width() as i32;
|
||||
self.screen_height = buffer.height() as i32;
|
||||
|
||||
let pal = &self.palette;
|
||||
for sx in (0..self.screen_width).step_by(64) {
|
||||
for sy in (0..self.screen_height).step_by(64) {
|
||||
for (y, col) in self.bg_flat.data.chunks(64).enumerate() {
|
||||
for (x, c) in col.iter().enumerate() {
|
||||
let c = &pal.0[*c as usize];
|
||||
buffer.set_pixel(sx as usize + x, sy as usize + y, c.r, c.g, c.b, 255);
|
||||
}
|
||||
}
|
||||
fn draw(&mut self, buffer: &mut RenderTarget) {
|
||||
match buffer.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { buffer.software_unchecked() };
|
||||
self.draw_pixels(pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
self.draw_pixels(pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
self.text.draw(6 * f, 6 * f, self, buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ use gamestate_traits::{
|
|||
surface,
|
||||
video::{Window, WindowContext},
|
||||
},
|
||||
PixelBuf,
|
||||
RenderTarget,
|
||||
};
|
||||
use render_traits::{PixelBuffer, RenderType};
|
||||
|
||||
use crate::shaders::{
|
||||
self, basic::Basic, cgwg_crt::Cgwgcrt, lottes_crt::LottesCRT, Drawer, Shaders,
|
||||
|
@ -68,7 +69,7 @@ impl<'c> Blitter<'c> {
|
|||
|
||||
if let Some(post_process) = post_process {
|
||||
info!("Using a post-process shader");
|
||||
post_process.set_tex_filter().unwrap();
|
||||
// post_process.set_tex_filter().unwrap();
|
||||
shader = Some(Shader {
|
||||
window,
|
||||
shader: post_process,
|
||||
|
@ -91,30 +92,33 @@ impl<'c> Blitter<'c> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn blit(&mut self, render_buffer: &mut PixelBuf) {
|
||||
pub fn blit(&mut self, render_buffer: &mut RenderTarget) {
|
||||
if let Some(shader) = &mut self.shader {
|
||||
// shader.shader.clear();
|
||||
let size = (render_buffer.width(), render_buffer.height());
|
||||
shader
|
||||
.shader
|
||||
.set_image_data(render_buffer.read_pixels_mut(), size);
|
||||
shader.shader.draw().unwrap();
|
||||
shader.window.gl_swap_window();
|
||||
if matches!(render_buffer.render_type(), RenderType::SoftOpenGL) {
|
||||
let render_buffer = unsafe { render_buffer.soft_opengl_unchecked() };
|
||||
// shader.shader.clear();
|
||||
render_buffer.copy_softbuf_to_gl_texture();
|
||||
shader.shader.draw(render_buffer.gl_texture()).unwrap();
|
||||
shader.window.gl_swap_window();
|
||||
}
|
||||
} else if let Some(soft) = &mut self.soft {
|
||||
let w = render_buffer.width();
|
||||
let h = render_buffer.height();
|
||||
let surf = surface::Surface::from_data(
|
||||
render_buffer.read_pixels_mut(),
|
||||
w,
|
||||
h,
|
||||
3 * w,
|
||||
pixels::PixelFormatEnum::RGB24,
|
||||
)
|
||||
.unwrap()
|
||||
.as_texture(&soft.tex_creator)
|
||||
.unwrap();
|
||||
soft.canvas.copy(&surf, None, Some(self.crop_rect)).unwrap();
|
||||
soft.canvas.present();
|
||||
let w = render_buffer.width() as u32;
|
||||
let h = render_buffer.height() as u32;
|
||||
if matches!(render_buffer.render_type(), RenderType::Software) {
|
||||
let render_buffer = unsafe { render_buffer.software_unchecked() };
|
||||
let surf = surface::Surface::from_data(
|
||||
render_buffer.read_softbuf_pixels(),
|
||||
w,
|
||||
h,
|
||||
4 * w,
|
||||
pixels::PixelFormatEnum::RGBA32,
|
||||
)
|
||||
.unwrap()
|
||||
.as_texture(&soft.tex_creator)
|
||||
.unwrap();
|
||||
soft.canvas.copy(&surf, None, Some(self.crop_rect)).unwrap();
|
||||
soft.canvas.present();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ use input::Input;
|
|||
use intermission_doom::Intermission;
|
||||
use menu_doom::MenuDoom;
|
||||
use render_soft::SoftwareRenderer;
|
||||
use render_traits::{PixelBuf, PlayRenderer};
|
||||
use render_traits::{PixelBuffer, PlayRenderer, RenderTarget, RenderType};
|
||||
use sound_traits::SoundAction;
|
||||
use statusbar_doom::Statusbar;
|
||||
use wad::lumps::{WadFlat, WadPatch};
|
||||
|
||||
use crate::{
|
||||
blit::Blitter, cheats::Cheats, test_funcs::*, timestep::TimeStep, wipe::Wipe, CLIOptions,
|
||||
blit::Blitter, cheats::Cheats, shaders::Shaders, timestep::TimeStep, wipe::Wipe, CLIOptions,
|
||||
};
|
||||
|
||||
/// Never returns until `game.running` is set to false
|
||||
|
@ -55,9 +55,24 @@ pub fn d_doom_loop(
|
|||
matches!(options.verbose, log::LevelFilter::Debug),
|
||||
);
|
||||
|
||||
let mut render_type = RenderType::Software;
|
||||
if let Some(shader) = options.shader {
|
||||
if !matches!(shader, Shaders::None) {
|
||||
render_type = RenderType::SoftOpenGL;
|
||||
}
|
||||
};
|
||||
info!("Using {render_type:?}");
|
||||
|
||||
let mut timestep = TimeStep::new();
|
||||
let mut render_buffer = PixelBuf::new(screen_width as u32, screen_height as u32, true);
|
||||
let mut render_buffer2 = PixelBuf::new(screen_width as u32, screen_height as u32, true);
|
||||
let mut render_buffer = RenderTarget::new(screen_width, screen_height, &gl_ctx, render_type);
|
||||
let mut render_buffer2 = RenderTarget::new(screen_width, screen_height, &gl_ctx, render_type);
|
||||
|
||||
if matches!(render_type, RenderType::SoftOpenGL) {
|
||||
let buf = unsafe { render_buffer.soft_opengl_unchecked() };
|
||||
buf.set_gl_filter().unwrap();
|
||||
let buf = unsafe { render_buffer.soft_opengl_unchecked() };
|
||||
buf.set_gl_filter().unwrap();
|
||||
}
|
||||
|
||||
let mut blitter = Blitter::new(options.shader, &gl_ctx, window);
|
||||
|
||||
|
@ -140,29 +155,29 @@ pub fn d_doom_loop(
|
|||
&mut timestep,
|
||||
);
|
||||
|
||||
if options.palette_test {
|
||||
palette_test(pal_num, &mut game, &mut render_buffer);
|
||||
}
|
||||
// if options.palette_test {
|
||||
// palette_test(pal_num, &mut game, &mut render_buffer);
|
||||
// }
|
||||
|
||||
if let Some(name) = options.image_test.clone() {
|
||||
image_test(&name.to_ascii_uppercase(), &game, &mut render_buffer);
|
||||
}
|
||||
if let Some(images) = &images {
|
||||
patch_select_test(&images[image_num], &game, &mut render_buffer);
|
||||
}
|
||||
if let Some(flats) = &flats {
|
||||
flat_select_test(&flats[flat_num], &game, &mut render_buffer);
|
||||
}
|
||||
if let Some(sprites) = &sprites {
|
||||
patch_select_test(&sprites[sprite_num], &game, &mut render_buffer);
|
||||
}
|
||||
if options.texture_test {
|
||||
texture_select_test(
|
||||
game.pic_data.borrow_mut().get_texture(tex_num),
|
||||
&game,
|
||||
&mut render_buffer,
|
||||
);
|
||||
}
|
||||
// if let Some(name) = options.image_test.clone() {
|
||||
// image_test(&name.to_ascii_uppercase(), &game, &mut render_buffer);
|
||||
// }
|
||||
// if let Some(images) = &images {
|
||||
// patch_select_test(&images[image_num], &game, &mut render_buffer);
|
||||
// }
|
||||
// if let Some(flats) = &flats {
|
||||
// flat_select_test(&flats[flat_num], &game, &mut render_buffer);
|
||||
// }
|
||||
// if let Some(sprites) = &sprites {
|
||||
// patch_select_test(&sprites[sprite_num], &game, &mut render_buffer);
|
||||
// }
|
||||
// if options.texture_test {
|
||||
// texture_select_test(
|
||||
// game.pic_data.borrow_mut().get_texture(tex_num),
|
||||
// &game,
|
||||
// &mut render_buffer,
|
||||
// );
|
||||
// }
|
||||
|
||||
blitter.blit(&mut render_buffer);
|
||||
|
||||
|
@ -215,7 +230,7 @@ pub fn d_doom_loop(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_title(game: &mut Game, draw_buf: &mut PixelBuf) {
|
||||
fn draw_title_pixels(game: &mut Game, draw_buf: &mut impl PixelBuffer) {
|
||||
let mut xtmp = 0;
|
||||
let mut ytmp = 0;
|
||||
let f = draw_buf.height() / 200;
|
||||
|
@ -227,10 +242,7 @@ fn draw_title(game: &mut Game, draw_buf: &mut PixelBuf) {
|
|||
draw_buf.set_pixel(
|
||||
(xtmp - n as i32) as usize, // - (image.left_offset as i32),
|
||||
(ytmp + c.y_offset * f as i32) as usize, // - image.top_offset as i32 - 30,
|
||||
colour.r,
|
||||
colour.g,
|
||||
colour.b,
|
||||
255,
|
||||
(colour.r, colour.g, colour.b, 255),
|
||||
);
|
||||
ytmp += 1;
|
||||
}
|
||||
|
@ -244,6 +256,21 @@ fn draw_title(game: &mut Game, draw_buf: &mut PixelBuf) {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_title(game: &mut Game, draw_buf: &mut RenderTarget) {
|
||||
match draw_buf.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { draw_buf.software_unchecked() };
|
||||
draw_title_pixels(game, pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { draw_buf.soft_opengl_unchecked() };
|
||||
draw_title_pixels(game, pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Does a bunch of stuff in Doom...
|
||||
/// `pixels` is the buffer that is always drawn, so drawing in to `pixels2` then flipping
|
||||
/// ensures the buffer is drawn. But if we draw in to `pixels2` and don't flip, we can
|
||||
|
@ -261,8 +288,8 @@ fn d_display(
|
|||
impl MachinationTrait,
|
||||
>,
|
||||
game: &mut Game,
|
||||
disp_buf: &mut PixelBuf, // Display from this buffer
|
||||
draw_buf: &mut PixelBuf, // Draw to this buffer
|
||||
disp_buf: &mut RenderTarget, // Display from this buffer
|
||||
draw_buf: &mut RenderTarget, // Draw to this buffer
|
||||
blitter: &mut Blitter,
|
||||
timestep: &mut TimeStep,
|
||||
) {
|
||||
|
@ -288,16 +315,27 @@ fn d_display(
|
|||
}
|
||||
}
|
||||
}
|
||||
// TODO: HU_Drawer();
|
||||
// Fake crosshair
|
||||
draw_buf.set_pixel(
|
||||
disp_buf.width() as usize / 2,
|
||||
disp_buf.height() as usize / 2,
|
||||
200,
|
||||
14,
|
||||
14,
|
||||
255,
|
||||
);
|
||||
match draw_buf.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { draw_buf.software_unchecked() };
|
||||
pixels.set_pixel(
|
||||
disp_buf.width() / 2,
|
||||
disp_buf.height() / 2,
|
||||
(200, 14, 14, 255),
|
||||
);
|
||||
}
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { draw_buf.soft_opengl_unchecked() };
|
||||
pixels.set_pixel(
|
||||
disp_buf.width() / 2,
|
||||
disp_buf.height() / 2,
|
||||
(200, 14, 14, 255),
|
||||
);
|
||||
}
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
match game.gamestate {
|
||||
|
@ -317,6 +355,7 @@ fn d_display(
|
|||
}
|
||||
|
||||
// // menus go directly to the screen
|
||||
// draw_buf.clear();
|
||||
menu.draw(draw_buf); // menu is drawn even on top of everything
|
||||
// net update does i/o and buildcmds...
|
||||
// TODO: NetUpdate(); // send out any new accumulation
|
||||
|
|
|
@ -3,7 +3,7 @@ mod cheats;
|
|||
mod config;
|
||||
mod d_main;
|
||||
mod shaders;
|
||||
mod test_funcs;
|
||||
// mod test_funcs;
|
||||
mod timestep;
|
||||
mod wipe;
|
||||
|
||||
|
|
|
@ -9,9 +9,8 @@ pub struct Basic {
|
|||
_quad: [f32; 16],
|
||||
indices: [u32; 6],
|
||||
shader: ShaderProgram,
|
||||
projection: Mat4,
|
||||
look_at: Mat4,
|
||||
texture: Texture,
|
||||
_projection: Mat4,
|
||||
_look_at: Mat4,
|
||||
vb: VertexBuffer,
|
||||
eb: ElementBuffer,
|
||||
}
|
||||
|
@ -73,9 +72,8 @@ impl Basic {
|
|||
_quad: GL_QUAD,
|
||||
indices: GL_QUAD_INDICES,
|
||||
shader,
|
||||
projection,
|
||||
look_at,
|
||||
texture: Texture::new(ctx).unwrap(),
|
||||
_projection: projection,
|
||||
_look_at: look_at,
|
||||
vb,
|
||||
eb,
|
||||
}
|
||||
|
@ -83,19 +81,9 @@ impl Basic {
|
|||
}
|
||||
|
||||
impl Drawer for Basic {
|
||||
fn set_tex_filter(&self) -> Result<(), GolemError> {
|
||||
self.texture.set_minification(TextureFilter::Nearest)?;
|
||||
self.texture.set_magnification(TextureFilter::Nearest)
|
||||
}
|
||||
|
||||
fn set_image_data(&mut self, input: &[u8], input_size: (u32, u32)) {
|
||||
self.texture
|
||||
.set_image(Some(input), input_size.0, input_size.1, ColorFormat::RGB);
|
||||
}
|
||||
|
||||
fn draw(&mut self) -> Result<(), GolemError> {
|
||||
fn draw(&mut self, texture: &Texture) -> Result<(), GolemError> {
|
||||
let bind_point = std::num::NonZeroU32::new(1).unwrap();
|
||||
self.texture.set_active(bind_point);
|
||||
texture.set_active(bind_point);
|
||||
// self.ctx.clear();
|
||||
unsafe {
|
||||
self.shader.draw(
|
||||
|
|
|
@ -25,7 +25,6 @@ pub struct Cgwgcrt {
|
|||
crt_height: u32,
|
||||
projection: Mat4,
|
||||
look_at: Mat4,
|
||||
texture: Texture,
|
||||
vb: VertexBuffer,
|
||||
eb: ElementBuffer,
|
||||
}
|
||||
|
@ -97,7 +96,6 @@ impl Cgwgcrt {
|
|||
crt_height,
|
||||
projection,
|
||||
look_at,
|
||||
texture: Texture::new(ctx).unwrap(),
|
||||
vb,
|
||||
eb,
|
||||
}
|
||||
|
@ -105,20 +103,10 @@ impl Cgwgcrt {
|
|||
}
|
||||
|
||||
impl Drawer for Cgwgcrt {
|
||||
fn set_tex_filter(&self) -> Result<(), GolemError> {
|
||||
self.texture.set_minification(TextureFilter::Nearest)?;
|
||||
self.texture.set_magnification(TextureFilter::Nearest)
|
||||
}
|
||||
|
||||
fn set_image_data(&mut self, input: &[u8], input_size: (u32, u32)) {
|
||||
self.texture
|
||||
.set_image(Some(input), input_size.0, input_size.1, ColorFormat::RGB);
|
||||
}
|
||||
|
||||
fn draw(&mut self) -> Result<(), GolemError> {
|
||||
fn draw(&mut self, texture: &Texture) -> Result<(), GolemError> {
|
||||
// Set the image to use
|
||||
let bind_point = std::num::NonZeroU32::new(1).unwrap();
|
||||
self.texture.set_active(bind_point);
|
||||
texture.set_active(bind_point);
|
||||
|
||||
self.crt_shader.bind();
|
||||
self.crt_shader.prepare_draw(&self.vb, &self.eb)?;
|
||||
|
@ -140,7 +128,7 @@ impl Drawer for Cgwgcrt {
|
|||
|
||||
self.crt_shader.set_uniform(
|
||||
"inputSize",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)?;
|
||||
|
||||
self.crt_shader.set_uniform(
|
||||
|
@ -149,7 +137,7 @@ impl Drawer for Cgwgcrt {
|
|||
)?;
|
||||
self.crt_shader.set_uniform(
|
||||
"textureSize",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)?;
|
||||
|
||||
self.crt_shader
|
||||
|
|
|
@ -11,7 +11,6 @@ pub struct LottesCRT {
|
|||
crt_shader: ShaderProgram,
|
||||
projection: Mat4,
|
||||
look_at: Mat4,
|
||||
texture: Texture,
|
||||
vb: VertexBuffer,
|
||||
eb: ElementBuffer,
|
||||
}
|
||||
|
@ -77,7 +76,6 @@ impl LottesCRT {
|
|||
crt_shader: shader,
|
||||
projection,
|
||||
look_at,
|
||||
texture: Texture::new(ctx).unwrap(),
|
||||
vb,
|
||||
eb,
|
||||
}
|
||||
|
@ -85,17 +83,7 @@ impl LottesCRT {
|
|||
}
|
||||
|
||||
impl Drawer for LottesCRT {
|
||||
fn set_tex_filter(&self) -> Result<(), GolemError> {
|
||||
self.texture.set_minification(TextureFilter::Nearest)?;
|
||||
self.texture.set_magnification(TextureFilter::Linear)
|
||||
}
|
||||
|
||||
fn set_image_data(&mut self, input: &[u8], input_size: (u32, u32)) {
|
||||
self.texture
|
||||
.set_image(Some(input), input_size.0, input_size.1, ColorFormat::RGB);
|
||||
}
|
||||
|
||||
fn draw(&mut self) -> Result<(), GolemError> {
|
||||
fn draw(&mut self, texture: &Texture) -> Result<(), GolemError> {
|
||||
self.crt_shader.bind();
|
||||
self.crt_shader.prepare_draw(&self.vb, &self.eb)?;
|
||||
|
||||
|
@ -117,13 +105,13 @@ impl Drawer for LottesCRT {
|
|||
// CRT settings
|
||||
self.crt_shader.set_uniform(
|
||||
"color_texture_sz",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)?;
|
||||
|
||||
// size of color texture rounded up to power of 2
|
||||
self.crt_shader.set_uniform(
|
||||
"color_texture_pow2_sz",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)?;
|
||||
|
||||
// Hardness of scanline.
|
||||
|
@ -162,7 +150,7 @@ impl Drawer for LottesCRT {
|
|||
.set_uniform("cornersmooth", UniformValue::Float(70.0))?; // 70.0 to 170.0
|
||||
|
||||
let bind_point = std::num::NonZeroU32::new(1).unwrap();
|
||||
self.texture.set_active(bind_point);
|
||||
texture.set_active(bind_point);
|
||||
|
||||
unsafe {
|
||||
self.crt_shader
|
||||
|
|
|
@ -11,7 +11,6 @@ pub struct LottesCRT {
|
|||
crt_shader: ShaderProgram,
|
||||
_projection: Mat4,
|
||||
_look_at: Mat4,
|
||||
texture: Texture,
|
||||
vb: VertexBuffer,
|
||||
eb: ElementBuffer,
|
||||
}
|
||||
|
@ -115,17 +114,12 @@ impl LottesCRT {
|
|||
vb.set_data(&GL_QUAD);
|
||||
eb.set_data(&GL_QUAD_INDICES);
|
||||
|
||||
let texture = Texture::new(ctx).unwrap();
|
||||
let bind_point = std::num::NonZeroU32::new(1).unwrap();
|
||||
texture.set_active(bind_point);
|
||||
|
||||
Self {
|
||||
_quad: GL_QUAD,
|
||||
indices: GL_QUAD_INDICES,
|
||||
crt_shader: shader,
|
||||
_projection: projection,
|
||||
_look_at: look_at,
|
||||
texture,
|
||||
vb,
|
||||
eb,
|
||||
}
|
||||
|
@ -133,24 +127,16 @@ impl LottesCRT {
|
|||
}
|
||||
|
||||
impl Drawer for LottesCRT {
|
||||
fn set_tex_filter(&self) -> Result<(), GolemError> {
|
||||
self.texture.set_minification(TextureFilter::Linear)?;
|
||||
self.texture.set_magnification(TextureFilter::Linear)
|
||||
}
|
||||
|
||||
fn set_image_data(&mut self, input: &[u8], input_size: (u32, u32)) {
|
||||
self.texture
|
||||
.set_image(Some(input), input_size.0, input_size.1, ColorFormat::RGB);
|
||||
}
|
||||
|
||||
fn draw(&mut self) -> Result<(), GolemError> {
|
||||
self.crt_shader.bind();
|
||||
fn draw(&mut self, texture: &Texture) -> Result<(), GolemError> {
|
||||
// Set the image to use
|
||||
let bind_point = std::num::NonZeroU32::new(1).unwrap();
|
||||
texture.set_active(bind_point);
|
||||
|
||||
// CRT settings
|
||||
self.crt_shader
|
||||
.set_uniform(
|
||||
"color_texture_sz",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -158,7 +144,7 @@ impl Drawer for LottesCRT {
|
|||
self.crt_shader
|
||||
.set_uniform(
|
||||
"color_texture_pow2_sz",
|
||||
UniformValue::Vector2([self.texture.width() as f32, self.texture.height() as f32]),
|
||||
UniformValue::Vector2([texture.width() as f32, texture.height() as f32]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use golem::GolemError;
|
||||
use golem::{GolemError, Texture};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -48,15 +48,5 @@ const GL_QUAD: [f32; 16] = [
|
|||
const GL_QUAD_INDICES: [u32; 6] = [0, 1, 2, 2, 3, 0];
|
||||
|
||||
pub trait Drawer {
|
||||
fn clear(&self, ctx: &golem::Context) {
|
||||
ctx.set_clear_color(0.0, 0.0, 0.0, 1.0);
|
||||
ctx.clear();
|
||||
}
|
||||
|
||||
fn set_tex_filter(&self) -> Result<(), GolemError>;
|
||||
|
||||
/// The input buffer/image of Doom
|
||||
fn set_image_data(&mut self, input: &[u8], input_size: (u32, u32));
|
||||
|
||||
fn draw(&mut self) -> Result<(), GolemError>;
|
||||
fn draw(&mut self, texture: &Texture) -> Result<(), GolemError>;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
use gameplay::WallPic;
|
||||
use gamestate::Game;
|
||||
|
||||
use render_traits::PixelBuf;
|
||||
use render_traits::RenderTarget;
|
||||
use wad::lumps::{WadFlat, WadPalette, WadPatch};
|
||||
|
||||
pub(crate) fn palette_test(pal_num: usize, game: &mut Game, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn palette_test(pal_num: usize, game: &mut Game, pixels: &mut RenderTarget) {
|
||||
let height = pixels.height();
|
||||
|
||||
let row_count: i32 = 16;
|
||||
|
@ -18,7 +18,7 @@ pub(crate) fn palette_test(pal_num: usize, game: &mut Game, pixels: &mut PixelBu
|
|||
let pals: Vec<WadPalette> = game.wad_data.playpal_iter().collect();
|
||||
|
||||
for (i, c) in pals[pal_num].0.iter().enumerate() {
|
||||
pixels.set_pixel(
|
||||
pixels.set_softbuf_pixel(
|
||||
(i as i32 % row_count * block_size + x_start) as usize,
|
||||
(i as i32 / row_count * block_size + y_start) as usize,
|
||||
c.r,
|
||||
|
@ -29,7 +29,7 @@ pub(crate) fn palette_test(pal_num: usize, game: &mut Game, pixels: &mut PixelBu
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn image_test(name: &str, game: &Game, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn image_test(name: &str, game: &Game, pixels: &mut RenderTarget) {
|
||||
let lump = game.wad_data.get_lump(name).unwrap();
|
||||
let image = WadPatch::from_lump(lump);
|
||||
let pals: Vec<WadPalette> = game.wad_data.playpal_iter().collect();
|
||||
|
@ -42,7 +42,7 @@ pub(crate) fn image_test(name: &str, game: &Game, pixels: &mut PixelBuf) {
|
|||
for (y, p) in c.pixels.iter().enumerate() {
|
||||
let colour = pals[0].0[*p];
|
||||
|
||||
pixels.set_pixel(
|
||||
pixels.set_softbuf_pixel(
|
||||
(xs + x) as usize, // - (image.left_offset as i32),
|
||||
(ys + y as i32 + c.y_offset) as usize, // - image.top_offset as i32 - 30,
|
||||
colour.r,
|
||||
|
@ -57,7 +57,7 @@ pub(crate) fn image_test(name: &str, game: &Game, pixels: &mut PixelBuf) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn patch_select_test(image: &WadPatch, game: &Game, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn patch_select_test(image: &WadPatch, game: &Game, pixels: &mut RenderTarget) {
|
||||
let pals: Vec<WadPalette> = game.wad_data.playpal_iter().collect();
|
||||
|
||||
let xs = ((pixels.width() - image.width as u32) / 2) as i32;
|
||||
|
@ -67,7 +67,7 @@ pub(crate) fn patch_select_test(image: &WadPatch, game: &Game, pixels: &mut Pixe
|
|||
for c in image.columns.iter() {
|
||||
for (y, p) in c.pixels.iter().enumerate() {
|
||||
let colour = pals[0].0[*p];
|
||||
pixels.set_pixel(
|
||||
pixels.set_softbuf_pixel(
|
||||
(xs + x) as usize, // - (image.left_offset as i32),
|
||||
(ys + y as i32 + c.y_offset) as usize, // - image.top_offset as i32 - 30,
|
||||
colour.r,
|
||||
|
@ -82,7 +82,7 @@ pub(crate) fn patch_select_test(image: &WadPatch, game: &Game, pixels: &mut Pixe
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn texture_select_test(texture: &WallPic, game: &Game, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn texture_select_test(texture: &WallPic, game: &Game, pixels: &mut RenderTarget) {
|
||||
let width = texture.data.len() as u32;
|
||||
let height = texture.data[0].len() as u32;
|
||||
let pals: Vec<WadPalette> = game.wad_data.playpal_iter().collect();
|
||||
|
@ -97,7 +97,7 @@ pub(crate) fn texture_select_test(texture: &WallPic, game: &Game, pixels: &mut P
|
|||
continue;
|
||||
}
|
||||
let colour = pal[*idx];
|
||||
pixels.set_pixel(
|
||||
pixels.set_softbuf_pixel(
|
||||
(xs + x_pos as i32) as usize,
|
||||
(ys + y_pos as i32) as usize,
|
||||
colour.r,
|
||||
|
@ -109,7 +109,7 @@ pub(crate) fn texture_select_test(texture: &WallPic, game: &Game, pixels: &mut P
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn flat_select_test(flat: &WadFlat, game: &Game, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn flat_select_test(flat: &WadFlat, game: &Game, pixels: &mut RenderTarget) {
|
||||
let pals: Vec<WadPalette> = game.wad_data.playpal_iter().collect();
|
||||
|
||||
let xs = ((pixels.width() - 64) / 2) as i32;
|
||||
|
@ -122,7 +122,7 @@ pub(crate) fn flat_select_test(flat: &WadFlat, game: &Game, pixels: &mut PixelBu
|
|||
continue;
|
||||
}
|
||||
let colour = pal[*px as usize];
|
||||
pixels.set_pixel(
|
||||
pixels.set_softbuf_pixel(
|
||||
(xs + x as i32) as usize,
|
||||
(ys + y as i32) as usize,
|
||||
colour.r,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use gameplay::m_random;
|
||||
use gamestate_traits::PixelBuf;
|
||||
use gamestate_traits::RenderTarget;
|
||||
use render_traits::PixelBuffer;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Wipe {
|
||||
|
@ -26,10 +27,10 @@ impl Wipe {
|
|||
Self { y, height, width }
|
||||
}
|
||||
|
||||
pub(crate) fn do_melt(
|
||||
fn do_melt_pixels(
|
||||
&mut self,
|
||||
disp_buf: &mut PixelBuf, // Display from this buffer
|
||||
draw_buf: &mut PixelBuf, // Draw to this buffer
|
||||
disp_buf: &mut impl PixelBuffer, // Display from this buffer
|
||||
draw_buf: &mut impl PixelBuffer, // Draw to this buffer
|
||||
) -> bool {
|
||||
let mut done = true;
|
||||
let f = (disp_buf.height() / 200) as i32;
|
||||
|
@ -50,20 +51,41 @@ impl Wipe {
|
|||
|
||||
let mut y = self.y[x] as usize;
|
||||
for _ in (0..dy).rev() {
|
||||
let px = draw_buf.read_pixel(x, y);
|
||||
disp_buf.set_pixel(x, y, px.0, px.1, px.2, px.3);
|
||||
let px = draw_buf.read_softbuf_pixel(x, y);
|
||||
disp_buf.set_pixel(x, y, (px.0, px.1, px.2, px.3));
|
||||
y += 1;
|
||||
}
|
||||
self.y[x] += dy;
|
||||
|
||||
for c in 0..=self.height - self.y[x] - dy {
|
||||
let y = self.height - c - dy;
|
||||
let px = disp_buf.read_pixel(x, y as usize);
|
||||
disp_buf.set_pixel(x, (self.height - c) as usize, px.0, px.1, px.2, px.3);
|
||||
let px = disp_buf.read_softbuf_pixel(x, y as usize);
|
||||
disp_buf.set_pixel(x, (self.height - c) as usize, (px.0, px.1, px.2, px.3));
|
||||
}
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
pub(crate) fn do_melt(
|
||||
&mut self,
|
||||
disp_buf: &mut RenderTarget, // Display from this buffer
|
||||
draw_buf: &mut RenderTarget, // Draw to this buffer
|
||||
) -> bool {
|
||||
match disp_buf.render_type() {
|
||||
render_traits::RenderType::Software => {
|
||||
let disp_buf = unsafe { disp_buf.software_unchecked() };
|
||||
let draw_buf = unsafe { draw_buf.software_unchecked() };
|
||||
self.do_melt_pixels(disp_buf, draw_buf)
|
||||
}
|
||||
render_traits::RenderType::SoftOpenGL => {
|
||||
let disp_buf = unsafe { disp_buf.soft_opengl_unchecked() };
|
||||
let draw_buf = unsafe { draw_buf.soft_opengl_unchecked() };
|
||||
self.do_melt_pixels(disp_buf, draw_buf)
|
||||
}
|
||||
render_traits::RenderType::OpenGL => todo!(),
|
||||
render_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pub use gameplay::{
|
|||
m_random, AmmoType, Card, GameMode, PlayerStatus, Skill, WBPlayerStruct, WBStartStruct,
|
||||
WeaponType, TICRATE, WEAPON_INFO,
|
||||
};
|
||||
pub use render_traits::PixelBuf;
|
||||
pub use render_traits::{PixelBuffer, RenderTarget, RenderType};
|
||||
pub use sdl2::{self, keyboard::Scancode};
|
||||
pub use sound_traits::{MusTrack, SfxName};
|
||||
|
||||
|
@ -96,12 +96,13 @@ pub trait MachinationTrait {
|
|||
fn get_palette(&self) -> &WadPalette;
|
||||
|
||||
/// Draw this Machination to the `PixelBuf`.
|
||||
fn draw(&mut self, buffer: &mut PixelBuf);
|
||||
fn draw(&mut self, buffer: &mut RenderTarget);
|
||||
|
||||
/// Free method, requires `get_palette()` to be implemented
|
||||
fn draw_patch(&self, patch: &WadPatch, x: i32, y: i32, pixels: &mut PixelBuf) {
|
||||
fn draw_patch_pixels(&self, patch: &WadPatch, x: i32, y: i32, pixels: &mut impl PixelBuffer) {
|
||||
let mut xtmp = 0;
|
||||
let mut ytmp = 0;
|
||||
|
||||
let f = pixels.height() / 200;
|
||||
for c in patch.columns.iter() {
|
||||
for n in 0..f {
|
||||
|
@ -111,10 +112,7 @@ pub trait MachinationTrait {
|
|||
pixels.set_pixel(
|
||||
(x + xtmp - n as i32) as usize, // - (image.left_offset as i32),
|
||||
(y + ytmp + c.y_offset * f as i32) as usize, // - image.top_offset as i32 - 30,
|
||||
colour.r,
|
||||
colour.g,
|
||||
colour.b,
|
||||
255,
|
||||
(colour.r, colour.g, colour.b, 255),
|
||||
);
|
||||
ytmp += 1;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::MachinationTrait;
|
||||
use render_traits::PixelBuf;
|
||||
use render_traits::{PixelBuffer, RenderTarget};
|
||||
use std::mem::MaybeUninit;
|
||||
use wad::{
|
||||
lumps::{WadPatch, WAD_PATCH},
|
||||
|
@ -33,16 +33,16 @@ pub fn get_st_key_sprites(wad: &WadData) -> [WadPatch; 6] {
|
|||
unsafe { keys.map(|n| n.assume_init()) }
|
||||
}
|
||||
|
||||
pub fn draw_num(
|
||||
pub fn draw_num_pixels(
|
||||
p: u32,
|
||||
mut x: i32,
|
||||
y: i32,
|
||||
pad: usize,
|
||||
nums: &[WadPatch],
|
||||
drawer: &impl MachinationTrait,
|
||||
buffer: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) -> i32 {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
let width = nums[0].width as i32 * f;
|
||||
let digits: Vec<u32> = p
|
||||
.to_string()
|
||||
|
@ -53,14 +53,38 @@ pub fn draw_num(
|
|||
for n in digits.iter().rev() {
|
||||
x -= width;
|
||||
let num = &nums[*n as usize];
|
||||
drawer.draw_patch(num, x, y, buffer);
|
||||
drawer.draw_patch_pixels(num, x, y, pixels);
|
||||
}
|
||||
if digits.len() <= pad {
|
||||
for _ in 0..=pad - digits.len() {
|
||||
x -= width;
|
||||
drawer.draw_patch(&nums[0], x, y, buffer);
|
||||
drawer.draw_patch_pixels(&nums[0], x, y, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
pub fn draw_num(
|
||||
p: u32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
pad: usize,
|
||||
nums: &[WadPatch],
|
||||
drawer: &impl MachinationTrait,
|
||||
buffer: &mut RenderTarget,
|
||||
) -> i32 {
|
||||
// TODO: remove duplicated functionality
|
||||
match buffer.render_type() {
|
||||
render_traits::RenderType::Software => {
|
||||
let pixels = unsafe { buffer.software_unchecked() };
|
||||
draw_num_pixels(p, x, y, pad, nums, drawer, pixels)
|
||||
}
|
||||
render_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
draw_num_pixels(p, x, y, pad, nums, drawer, pixels)
|
||||
}
|
||||
render_traits::RenderType::OpenGL => todo!(),
|
||||
render_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use gamestate_traits::{GameTraits, MachinationTrait, PixelBuf, Scancode, TICRATE};
|
||||
use gamestate_traits::{GameTraits, MachinationTrait, RenderTarget, Scancode, TICRATE};
|
||||
use hud_util::{load_char_patches, HUDString, HUD_STRING};
|
||||
use wad::{lumps::WadPalette, WadData};
|
||||
|
||||
|
@ -62,8 +62,8 @@ impl Messages {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_wrapped(&self, machination: &impl MachinationTrait, pixels: &mut PixelBuf) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
pub fn draw_wrapped(&self, machination: &impl MachinationTrait, buffer: &mut RenderTarget) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
|
||||
let x = 10;
|
||||
let mut y = 2;
|
||||
|
@ -80,7 +80,7 @@ impl Messages {
|
|||
continue;
|
||||
}
|
||||
|
||||
self.lines[pos].draw(x, y, machination, pixels);
|
||||
self.lines[pos].draw(x, y, machination, buffer);
|
||||
y += self.lines[pos].line_height() * f + 1;
|
||||
|
||||
if pos == self.current {
|
||||
|
@ -127,7 +127,7 @@ impl MachinationTrait for Messages {
|
|||
&self.palette
|
||||
}
|
||||
|
||||
fn draw(&mut self, buffer: &mut PixelBuf) {
|
||||
fn draw(&mut self, buffer: &mut RenderTarget) {
|
||||
self.screen_width = buffer.width() as i32;
|
||||
self.screen_height = buffer.height() as i32;
|
||||
self.draw_wrapped(self, buffer);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use gamestate_traits::{MachinationTrait, PixelBuf};
|
||||
use gamestate_traits::{MachinationTrait, PixelBuffer, RenderTarget, RenderType};
|
||||
use log::warn;
|
||||
use wad::{
|
||||
lumps::{WadPatch, WAD_PATCH},
|
||||
|
@ -112,12 +112,12 @@ impl HUDString {
|
|||
self.data.clear();
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
pub fn draw_pixels(
|
||||
&self,
|
||||
mut x: i32,
|
||||
mut y: i32,
|
||||
machination: &impl MachinationTrait,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) -> Option<()> {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
let width = pixels.width() as i32;
|
||||
|
@ -160,7 +160,7 @@ impl HUDString {
|
|||
return None;
|
||||
}
|
||||
|
||||
machination.draw_patch(
|
||||
machination.draw_patch_pixels(
|
||||
patch,
|
||||
x,
|
||||
y + self.line_height * f - patch.height as i32 * f,
|
||||
|
@ -170,6 +170,28 @@ impl HUDString {
|
|||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
x: i32,
|
||||
y: i32,
|
||||
machination: &impl MachinationTrait,
|
||||
pixels: &mut RenderTarget,
|
||||
) -> Option<()> {
|
||||
match pixels.render_type() {
|
||||
RenderType::Software => {
|
||||
let pixels = unsafe { pixels.software_unchecked() };
|
||||
self.draw_pixels(x, y, machination, pixels);
|
||||
}
|
||||
RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { pixels.soft_opengl_unchecked() };
|
||||
self.draw_pixels(x, y, machination, pixels);
|
||||
}
|
||||
RenderType::OpenGL => todo!(),
|
||||
RenderType::Vulkan => todo!(),
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -5,8 +5,8 @@ use crate::defs::{
|
|||
};
|
||||
use gameplay::{m_random, TICRATE};
|
||||
use gamestate_traits::{
|
||||
GameMode, GameTraits, MachinationTrait, MusTrack, PixelBuf, Scancode, WBPlayerStruct,
|
||||
WBStartStruct,
|
||||
GameMode, GameTraits, MachinationTrait, MusTrack, PixelBuffer, RenderTarget, Scancode,
|
||||
WBPlayerStruct, WBStartStruct,
|
||||
};
|
||||
use log::warn;
|
||||
use wad::{
|
||||
|
@ -241,22 +241,41 @@ impl Intermission {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_animated_bg(&self, scale: i32, buffer: &mut PixelBuf) {
|
||||
fn draw_animated_bg_pixels(&self, scale: i32, pixels: &mut impl PixelBuffer) {
|
||||
if self.mode == GameMode::Commercial || self.level_info.epsd > 2 {
|
||||
return;
|
||||
}
|
||||
|
||||
for anim in self.animations[self.level_info.epsd as usize].iter() {
|
||||
if anim.counter >= 0 {
|
||||
self.draw_patch(
|
||||
self.draw_patch_pixels(
|
||||
&anim.patches[anim.counter as usize],
|
||||
anim.location.0 * scale,
|
||||
anim.location.1 * scale,
|
||||
buffer,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fn draw_animated_bg(&self, scale: i32, buffer: &mut RenderTarget) {
|
||||
// if self.mode == GameMode::Commercial || self.level_info.epsd > 2 {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// match buffer.render_type() {
|
||||
// gamestate_traits::RenderType::Software => {
|
||||
// let pixels = unsafe { buffer.software_unchecked() };
|
||||
// self.draw_animated_bg_pixels(scale, pixels);
|
||||
// }
|
||||
// gamestate_traits::RenderType::SoftOpenGL => {
|
||||
// let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
// self.draw_animated_bg_pixels(scale, pixels);
|
||||
// }
|
||||
// gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
// gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
impl MachinationTrait for Intermission {
|
||||
|
@ -329,20 +348,41 @@ impl MachinationTrait for Intermission {
|
|||
&self.palette
|
||||
}
|
||||
|
||||
fn draw(&mut self, buffer: &mut PixelBuf) {
|
||||
fn draw(&mut self, buffer: &mut RenderTarget) {
|
||||
let scale = (buffer.height() / 200) as i32;
|
||||
|
||||
// TODO: stats and next are two different screens.
|
||||
match self.state {
|
||||
State::StatCount => {
|
||||
self.draw_stats(scale, buffer);
|
||||
match buffer.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { buffer.software_unchecked() };
|
||||
match self.state {
|
||||
State::StatCount => {
|
||||
self.draw_stats_pixels(scale, pixels);
|
||||
}
|
||||
State::NextLoc => {
|
||||
self.draw_next_loc_pixels(scale, pixels);
|
||||
}
|
||||
State::None => {
|
||||
self.draw_no_state(scale, pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
State::NextLoc => {
|
||||
self.draw_next_loc(scale, buffer);
|
||||
}
|
||||
State::None => {
|
||||
self.draw_no_state(scale, buffer);
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
match self.state {
|
||||
State::StatCount => {
|
||||
self.draw_stats_pixels(scale, pixels);
|
||||
}
|
||||
State::NextLoc => {
|
||||
self.draw_next_loc_pixels(scale, pixels);
|
||||
}
|
||||
State::None => {
|
||||
self.draw_no_state(scale, pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{Intermission, State, MAP_POINTS, SHOW_NEXT_LOC_DELAY, TICRATE, TITLE_Y};
|
||||
use gamestate_traits::{GameMode, MachinationTrait, PixelBuf};
|
||||
use gamestate_traits::{GameMode, MachinationTrait, PixelBuffer};
|
||||
use wad::lumps::WadPatch;
|
||||
|
||||
impl Intermission {
|
||||
|
@ -26,7 +26,7 @@ impl Intermission {
|
|||
lv: usize,
|
||||
patch: &WadPatch,
|
||||
scale: i32,
|
||||
buffer: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let ep = self.level_info.epsd as usize;
|
||||
let point = MAP_POINTS[ep][lv];
|
||||
|
@ -34,13 +34,13 @@ impl Intermission {
|
|||
let x = point.0 - patch.left_offset as i32;
|
||||
let y = point.1 - patch.top_offset as i32;
|
||||
|
||||
self.draw_patch(patch, x * scale, y * scale, buffer);
|
||||
self.draw_patch_pixels(patch, x * scale, y * scale, pixels);
|
||||
}
|
||||
|
||||
pub(super) fn draw_enter_level(&self, scale: i32, buffer: &mut PixelBuf) {
|
||||
pub(super) fn draw_enter_level_pixels(&self, scale: i32, buffer: &mut impl PixelBuffer) {
|
||||
let half = buffer.width() as i32 / 2;
|
||||
let mut y = TITLE_Y * scale;
|
||||
self.draw_patch(
|
||||
self.draw_patch_pixels(
|
||||
&self.patches.enter,
|
||||
half - self.patches.enter.width as i32 * scale / 2,
|
||||
y,
|
||||
|
@ -48,13 +48,13 @@ impl Intermission {
|
|||
);
|
||||
y += (5 * self.patches.enter.height as i32 * scale) / 4;
|
||||
let patch = self.get_enter_level_name();
|
||||
self.draw_patch(patch, half - patch.width as i32 * scale / 2, y, buffer);
|
||||
self.draw_patch_pixels(patch, half - patch.width as i32 * scale / 2, y, buffer);
|
||||
}
|
||||
|
||||
pub(super) fn draw_next_loc(&self, scale: i32, buffer: &mut PixelBuf) {
|
||||
pub(super) fn draw_next_loc_pixels(&self, scale: i32, buffer: &mut impl PixelBuffer) {
|
||||
// Background
|
||||
self.draw_patch(self.get_bg(), 0, 0, buffer);
|
||||
self.draw_animated_bg(scale, buffer);
|
||||
self.draw_patch_pixels(self.get_bg(), 0, 0, buffer);
|
||||
self.draw_animated_bg_pixels(scale, buffer);
|
||||
|
||||
// Location stuff only for episodes 1-3
|
||||
if self.mode != GameMode::Commercial && self.level_info.epsd <= 2 {
|
||||
|
@ -79,7 +79,7 @@ impl Intermission {
|
|||
}
|
||||
|
||||
if self.mode != GameMode::Commercial || self.level_info.next != 30 {
|
||||
self.draw_enter_level(scale, buffer);
|
||||
self.draw_enter_level_pixels(scale, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::{Intermission, State};
|
||||
use gamestate_traits::{GameTraits, PixelBuf};
|
||||
use gamestate_traits::{GameTraits, PixelBuffer};
|
||||
use log::info;
|
||||
|
||||
impl Intermission {
|
||||
pub(super) fn draw_no_state(&mut self, scale: i32, buffer: &mut PixelBuf) {
|
||||
pub(super) fn draw_no_state(&mut self, scale: i32, pixels: &mut impl PixelBuffer) {
|
||||
self.pointer_on = true;
|
||||
self.draw_next_loc(scale, buffer);
|
||||
self.draw_next_loc_pixels(scale, pixels);
|
||||
}
|
||||
|
||||
pub(super) fn init_no_state(&mut self) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{Intermission, State, SHOW_NEXT_LOC_DELAY, TICRATE, TITLE_Y};
|
||||
use gamestate_traits::{util::draw_num, GameMode, MachinationTrait, PixelBuf};
|
||||
use gamestate_traits::{util::draw_num_pixels, GameMode, MachinationTrait, PixelBuffer};
|
||||
|
||||
const SCREEN_HEIGHT: i32 = 200;
|
||||
|
||||
|
@ -30,36 +30,36 @@ impl Intermission {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn draw_level_finish(&self, scale: i32, buffer: &mut PixelBuf) {
|
||||
let half = buffer.width() as i32 / 2;
|
||||
pub(super) fn draw_level_finish_pixels(&self, scale: i32, pixels: &mut impl PixelBuffer) {
|
||||
let half = pixels.width() as i32 / 2;
|
||||
let mut y = TITLE_Y * scale;
|
||||
self.draw_patch(
|
||||
self.draw_patch_pixels(
|
||||
&self.patches.finish,
|
||||
half - self.patches.enter.width as i32 * scale / 2,
|
||||
y,
|
||||
buffer,
|
||||
pixels,
|
||||
);
|
||||
y += (5 * self.patches.finish.height as i32) / 4 * scale;
|
||||
let patch = self.get_this_level_name();
|
||||
self.draw_patch(patch, half - patch.width as i32 * scale / 2, y, buffer);
|
||||
self.draw_patch_pixels(patch, half - patch.width as i32 * scale / 2, y, pixels);
|
||||
}
|
||||
|
||||
fn draw_percent(&self, p: u32, x: i32, y: i32, buffer: &mut PixelBuf) {
|
||||
self.draw_patch(&self.patches.percent, x, y, buffer);
|
||||
draw_num(p, x, y, 0, &self.patches.nums, self, buffer);
|
||||
fn draw_percent(&self, p: u32, x: i32, y: i32, pixels: &mut impl PixelBuffer) {
|
||||
self.draw_patch_pixels(&self.patches.percent, x, y, pixels);
|
||||
draw_num_pixels(p, x, y, 0, &self.patches.nums, self, pixels);
|
||||
}
|
||||
|
||||
fn draw_time(&self, t: u32, mut x: i32, y: i32, scale: i32, buffer: &mut PixelBuf) {
|
||||
fn draw_time(&self, t: u32, mut x: i32, y: i32, scale: i32, buffer: &mut impl PixelBuffer) {
|
||||
let mut div = 1;
|
||||
if t <= 61 * 59 {
|
||||
loop {
|
||||
let n = (t / div) % 60;
|
||||
x = draw_num(n, x, y, 1, &self.patches.nums, self, buffer)
|
||||
x = draw_num_pixels(n, x, y, 1, &self.patches.nums, self, buffer)
|
||||
- self.patches.colon.width as i32 * scale;
|
||||
div *= 60;
|
||||
|
||||
if div == 60 || t / div != 0 {
|
||||
self.draw_patch(&self.patches.colon, x, y, buffer);
|
||||
self.draw_patch_pixels(&self.patches.colon, x, y, buffer);
|
||||
}
|
||||
|
||||
if t / div == 0 {
|
||||
|
@ -69,7 +69,7 @@ impl Intermission {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn draw_stats(&mut self, scale: i32, buffer: &mut PixelBuf) {
|
||||
pub(super) fn draw_stats_pixels(&mut self, scale: i32, buffer: &mut impl PixelBuffer) {
|
||||
let width = buffer.width() as i32;
|
||||
let stats_x = SP_STATSX * scale;
|
||||
let stats_y = SP_STATSY * scale;
|
||||
|
@ -77,12 +77,12 @@ impl Intermission {
|
|||
let time_y = SP_TIMEY * scale;
|
||||
|
||||
// Background
|
||||
self.draw_patch(self.get_bg(), 0, 0, buffer);
|
||||
self.draw_animated_bg(scale, buffer);
|
||||
self.draw_level_finish(scale, buffer);
|
||||
self.draw_patch_pixels(self.get_bg(), 0, 0, buffer);
|
||||
self.draw_animated_bg_pixels(scale, buffer);
|
||||
self.draw_level_finish_pixels(scale, buffer);
|
||||
|
||||
let mut lh = (3 * self.patches.nums[0].height / 2) as i32;
|
||||
self.draw_patch(&self.patches.kills, stats_x, stats_y, buffer);
|
||||
self.draw_patch_pixels(&self.patches.kills, stats_x, stats_y, buffer);
|
||||
self.draw_percent(
|
||||
self.player_info.skills as u32,
|
||||
width - stats_x,
|
||||
|
@ -91,7 +91,7 @@ impl Intermission {
|
|||
);
|
||||
|
||||
lh += lh;
|
||||
self.draw_patch(&self.patches.items, stats_x, stats_y + lh, buffer);
|
||||
self.draw_patch_pixels(&self.patches.items, stats_x, stats_y + lh, buffer);
|
||||
self.draw_percent(
|
||||
self.player_info.sitems as u32,
|
||||
width - stats_x,
|
||||
|
@ -100,7 +100,7 @@ impl Intermission {
|
|||
);
|
||||
|
||||
lh += lh;
|
||||
self.draw_patch(&self.patches.sp_secret, stats_x, stats_y + lh, buffer);
|
||||
self.draw_patch_pixels(&self.patches.sp_secret, stats_x, stats_y + lh, buffer);
|
||||
self.draw_percent(
|
||||
self.player_info.ssecret as u32,
|
||||
width - stats_x,
|
||||
|
@ -108,7 +108,7 @@ impl Intermission {
|
|||
buffer,
|
||||
);
|
||||
|
||||
self.draw_patch(&self.patches.time, time_x, time_y, buffer);
|
||||
self.draw_patch_pixels(&self.patches.time, time_x, time_y, buffer);
|
||||
self.draw_time(
|
||||
self.player_info.stime / TICRATE as u32,
|
||||
width / 2 - time_x,
|
||||
|
@ -118,7 +118,7 @@ impl Intermission {
|
|||
);
|
||||
|
||||
if self.level_info.epsd < 3 {
|
||||
self.draw_patch(&self.patches.par, width / 2 + time_x, time_y, buffer);
|
||||
self.draw_patch_pixels(&self.patches.par, width / 2 + time_x, time_y, buffer);
|
||||
self.draw_time(
|
||||
self.level_info.partime as u32,
|
||||
width - time_x,
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
//! with the rest of the game it ends up being fairly generic - you could make this
|
||||
//! fully generic with a little work, or use it as the basis for a different menu.
|
||||
|
||||
use gamestate_traits::{GameMode, GameTraits, MachinationTrait, PixelBuf, Scancode, Skill};
|
||||
use gamestate_traits::{
|
||||
GameMode, GameTraits, MachinationTrait, PixelBuffer, RenderTarget, Scancode, Skill,
|
||||
};
|
||||
use sound_traits::SfxName;
|
||||
use std::collections::HashMap;
|
||||
use wad::{
|
||||
|
@ -331,6 +333,34 @@ impl MenuDoom {
|
|||
.get(name)
|
||||
.unwrap_or_else(|| panic!("{name} not in cache"))
|
||||
}
|
||||
|
||||
fn draw_pixels(&mut self, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
|
||||
if self.active || self.in_help {
|
||||
let active = &self.menus[self.current_menu as usize];
|
||||
// Titles
|
||||
for item in active.titles.iter() {
|
||||
self.draw_patch_pixels(self.get_patch(&item.patch), item.x * f, item.y * f, pixels);
|
||||
}
|
||||
// sub-items
|
||||
let x = active.x * f;
|
||||
let mut y = active.y * f;
|
||||
for item in active.items.iter() {
|
||||
self.draw_patch_pixels(self.get_patch(&item.patch), x, y, pixels);
|
||||
y += LINEHEIGHT * f;
|
||||
}
|
||||
|
||||
// SKULL
|
||||
let y = active.y * f - 5 + active.last_on as i32 * LINEHEIGHT * f;
|
||||
self.draw_patch_pixels(
|
||||
self.get_patch(SKULLS[self.which_skull]),
|
||||
x + -(32 * f),
|
||||
y,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sel_new_game(menu: &mut MenuDoom, _: i32, game: &mut dyn GameTraits) {
|
||||
|
@ -498,31 +528,18 @@ impl MachinationTrait for MenuDoom {
|
|||
&self.palette
|
||||
}
|
||||
|
||||
fn draw(&mut self, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
|
||||
if self.active || self.in_help {
|
||||
let active = &self.menus[self.current_menu as usize];
|
||||
// Titles
|
||||
for item in active.titles.iter() {
|
||||
self.draw_patch(self.get_patch(&item.patch), item.x * f, item.y * f, buffer);
|
||||
fn draw(&mut self, buffer: &mut RenderTarget) {
|
||||
match buffer.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { buffer.software_unchecked() };
|
||||
self.draw_pixels(pixels)
|
||||
}
|
||||
// sub-items
|
||||
let x = active.x * f;
|
||||
let mut y = active.y * f;
|
||||
for item in active.items.iter() {
|
||||
self.draw_patch(self.get_patch(&item.patch), x, y, buffer);
|
||||
y += LINEHEIGHT * f;
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
self.draw_pixels(pixels)
|
||||
}
|
||||
|
||||
// SKULL
|
||||
let y = active.y * f - 5 + active.last_on as i32 * LINEHEIGHT * f;
|
||||
self.draw_patch(
|
||||
self.get_patch(SKULLS[self.which_skull]),
|
||||
x + -(32 * f),
|
||||
y,
|
||||
buffer,
|
||||
);
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use gameplay::{
|
|||
SubSector, IS_SSECTOR_MASK,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use render_traits::{PixelBuf, PlayRenderer};
|
||||
use render_traits::{PixelBuffer, PlayRenderer, RenderTarget};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
f32::consts::{FRAC_PI_2, FRAC_PI_4, PI},
|
||||
|
@ -69,26 +69,55 @@ pub struct SoftwareRenderer {
|
|||
}
|
||||
|
||||
impl PlayRenderer for SoftwareRenderer {
|
||||
fn render_player_view(&mut self, player: &Player, level: &Level, pixels: &mut PixelBuf) {
|
||||
fn render_player_view(&mut self, player: &Player, level: &Level, pixels: &mut RenderTarget) {
|
||||
let map = &level.map_data;
|
||||
|
||||
self.clear(player, pixels.width() as f32);
|
||||
// TODO: netupdate
|
||||
let mut count = 0;
|
||||
self.checked_sectors.clear();
|
||||
// TODO: pull duplicate functionality out to a function
|
||||
match pixels.render_type() {
|
||||
render_traits::RenderType::Software => {
|
||||
let pixels = unsafe { pixels.software_unchecked() };
|
||||
self.clear(player, pixels.width() as f32);
|
||||
// TODO: netupdate
|
||||
let mut count = 0;
|
||||
self.checked_sectors.clear();
|
||||
|
||||
self.texture_data
|
||||
.borrow_mut()
|
||||
.set_fixed_lightscale(player.fixedcolormap as usize);
|
||||
self.texture_data.borrow_mut().set_player_palette(player);
|
||||
self.texture_data
|
||||
.borrow_mut()
|
||||
.set_fixed_lightscale(player.fixedcolormap as usize);
|
||||
self.texture_data.borrow_mut().set_player_palette(player);
|
||||
|
||||
self.render_bsp_node(map, player, map.start_node(), pixels, &mut count);
|
||||
trace!("BSP traversals for render: {count}");
|
||||
// TODO: netupdate again
|
||||
self.draw_planes(player, pixels);
|
||||
// TODO: netupdate again
|
||||
self.draw_masked(player, pixels);
|
||||
// TODO: netupdate again
|
||||
self.render_bsp_node(map, player, map.start_node(), pixels, &mut count);
|
||||
trace!("BSP traversals for render: {count}");
|
||||
// TODO: netupdate again
|
||||
self.draw_planes(player, pixels);
|
||||
// TODO: netupdate again
|
||||
self.draw_masked(player, pixels);
|
||||
// TODO: netupdate again
|
||||
}
|
||||
render_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { pixels.soft_opengl_unchecked() };
|
||||
self.clear(player, pixels.width() as f32);
|
||||
// TODO: netupdate
|
||||
let mut count = 0;
|
||||
self.checked_sectors.clear();
|
||||
|
||||
self.texture_data
|
||||
.borrow_mut()
|
||||
.set_fixed_lightscale(player.fixedcolormap as usize);
|
||||
self.texture_data.borrow_mut().set_player_palette(player);
|
||||
|
||||
self.render_bsp_node(map, player, map.start_node(), pixels, &mut count);
|
||||
trace!("BSP traversals for render: {count}");
|
||||
// TODO: netupdate again
|
||||
self.draw_planes(player, pixels);
|
||||
// TODO: netupdate again
|
||||
self.draw_masked(player, pixels);
|
||||
// TODO: netupdate again
|
||||
}
|
||||
_ => {
|
||||
panic!("Not a valid renderer for software mode")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +154,7 @@ impl SoftwareRenderer {
|
|||
}
|
||||
|
||||
/// Doom function name `R_DrawPlanes`
|
||||
fn draw_planes(&mut self, player: &Player, pixels: &mut PixelBuf) {
|
||||
fn draw_planes(&mut self, player: &Player, pixels: &mut impl PixelBuffer) {
|
||||
let mobj = unsafe { player.mobj_unchecked() };
|
||||
let view_angle = mobj.angle;
|
||||
|
||||
|
@ -179,7 +208,7 @@ impl SoftwareRenderer {
|
|||
plane.baseyscale = baseyscale;
|
||||
plane.view_angle = view_angle;
|
||||
|
||||
let mut span_start = vec![0.0; pixels.width() as usize];
|
||||
let mut span_start = vec![0.0; pixels.width()];
|
||||
for x in plane.minx as i32..=plane.maxx as i32 {
|
||||
let mut step = x - 1;
|
||||
if step < 0 {
|
||||
|
@ -209,7 +238,7 @@ impl SoftwareRenderer {
|
|||
player: &Player,
|
||||
seg: &'a Segment,
|
||||
front_sector: &'a Sector,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let mobj = unsafe { player.mobj_unchecked() };
|
||||
// reject orthogonal back sides
|
||||
|
@ -308,7 +337,7 @@ impl SoftwareRenderer {
|
|||
map: &MapData,
|
||||
player: &Player,
|
||||
subsect: &SubSector,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let skynum = self.texture_data.borrow().sky_num();
|
||||
// TODO: planes for floor & ceiling
|
||||
|
@ -335,7 +364,7 @@ impl SoftwareRenderer {
|
|||
|
||||
let front_sector = &subsect.sector;
|
||||
|
||||
self.add_sprites(player, front_sector, pixels.width());
|
||||
self.add_sprites(player, front_sector, pixels.width() as u32);
|
||||
|
||||
for i in subsect.start_seg..subsect.start_seg + subsect.seg_count {
|
||||
let seg = &map.segments()[i as usize];
|
||||
|
@ -366,7 +395,7 @@ impl SoftwareRenderer {
|
|||
last: f32,
|
||||
seg: &Segment,
|
||||
object: &Player,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let mut next;
|
||||
|
||||
|
@ -469,7 +498,7 @@ impl SoftwareRenderer {
|
|||
last: f32,
|
||||
seg: &Segment,
|
||||
object: &Player,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
// Find the first range that touches the range
|
||||
// (adjacent pixels are touching).
|
||||
|
@ -555,7 +584,7 @@ impl SoftwareRenderer {
|
|||
map: &MapData,
|
||||
player: &Player,
|
||||
node_id: u16,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
count: &mut usize,
|
||||
) {
|
||||
*count += 1;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::f32::consts::FRAC_PI_2;
|
|||
use crate::utilities::screen_to_x_view;
|
||||
use gameplay::{Angle, FlatPic, PicData};
|
||||
use glam::Vec2;
|
||||
use render_traits::PixelBuf;
|
||||
use render_traits::PixelBuffer;
|
||||
|
||||
use super::defs::Visplane;
|
||||
|
||||
|
@ -203,7 +203,7 @@ pub fn make_spans(
|
|||
plane: &Visplane,
|
||||
span_start: &mut [f32],
|
||||
texture_data: &PicData,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
// TODO: t1, y, is causing a glitch
|
||||
while t1 < t2 && t1 <= b1 {
|
||||
|
@ -257,7 +257,7 @@ fn map_plane(
|
|||
extra_light: i32,
|
||||
plane: &Visplane,
|
||||
texture_data: &PicData,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let planeheight = (plane.height - viewz).abs();
|
||||
// TODO: maybe cache?
|
||||
|
@ -324,7 +324,7 @@ impl<'a> DrawSpan<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw(&mut self, textures: &PicData, pixels: &mut PixelBuf) {
|
||||
fn draw(&mut self, textures: &PicData, pixels: &mut impl PixelBuffer) {
|
||||
let pal = textures.palette();
|
||||
// for s in self.ds_x1.round() as i32..=self.ds_x2.round() as i32 {
|
||||
for s in self.ds_x1 as i32..=self.ds_x2 as i32 {
|
||||
|
@ -341,7 +341,7 @@ impl<'a> DrawSpan<'a> {
|
|||
|
||||
let px = self.colourmap[self.texture.data[x][y] as usize];
|
||||
let c = pal[px];
|
||||
pixels.set_pixel(s as usize, self.ds_y as usize, c.r, c.g, c.b, 255);
|
||||
pixels.set_pixel(s as usize, self.ds_y as usize, (c.r, c.g, c.b, 255));
|
||||
|
||||
self.ds_xfrac += self.ds_xstep;
|
||||
self.ds_yfrac += self.ds_ystep;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::utilities::screen_to_x_view;
|
||||
use gameplay::{Angle, LineDefFlags, PicData, Player, Segment};
|
||||
use render_traits::PixelBuf;
|
||||
use render_traits::PixelBuffer;
|
||||
use std::{cell::RefCell, f32::consts::FRAC_PI_2, ptr::NonNull, rc::Rc};
|
||||
|
||||
use crate::utilities::{point_to_dist, scale_from_view_angle};
|
||||
|
@ -120,7 +120,7 @@ impl SegRender {
|
|||
seg: &Segment,
|
||||
player: &Player,
|
||||
rdata: &mut RenderData,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
// Keep original Doom behaviour here
|
||||
if rdata.drawsegs.len() >= MAXDRAWSEGS {
|
||||
|
@ -470,7 +470,7 @@ impl SegRender {
|
|||
seg: &Segment,
|
||||
view_height: f32,
|
||||
rdata: &mut RenderData,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
// R_RenderSegLoop
|
||||
let mut yl: f32;
|
||||
|
@ -687,7 +687,12 @@ impl<'a> DrawColumn<'a> {
|
|||
/// will always have constant z depth.
|
||||
/// Thus a special case loop for very fast rendering can
|
||||
/// be used. It has also been used with Wolfenstein 3D.
|
||||
pub fn draw_column(&mut self, textures: &PicData, doubled: bool, pixels: &mut PixelBuf) {
|
||||
pub fn draw_column(
|
||||
&mut self,
|
||||
textures: &PicData,
|
||||
doubled: bool,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let pal = textures.palette();
|
||||
let mut frac =
|
||||
self.dc_texturemid + (self.yl - pixels.height() as f32 / 2.0) * self.fracstep + 0.1;
|
||||
|
@ -708,7 +713,7 @@ impl<'a> DrawColumn<'a> {
|
|||
|
||||
let px = self.colourmap[self.texture_column[select as usize]];
|
||||
let c = pal[px];
|
||||
pixels.set_pixel(self.dc_x as usize, n as usize, c.r, c.g, c.b, 255);
|
||||
pixels.set_pixel(self.dc_x as usize, n as usize, (c.r, c.g, c.b, 255));
|
||||
|
||||
frac += self.fracstep;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use gameplay::{
|
|||
PspDef, Sector,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use render_traits::PixelBuf;
|
||||
use render_traits::PixelBuffer;
|
||||
|
||||
use super::{bsp::SoftwareRenderer, defs::DrawSeg};
|
||||
|
||||
|
@ -255,7 +255,7 @@ impl SoftwareRenderer {
|
|||
vis: &VisSprite,
|
||||
clip_bottom: &[i32],
|
||||
clip_top: &[i32],
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let naff = self.texture_data.clone(); // Need to separate lifetimes
|
||||
let texture_data = naff.borrow();
|
||||
|
@ -311,9 +311,9 @@ impl SoftwareRenderer {
|
|||
}
|
||||
|
||||
/// Doom function name `R_DrawSprite`
|
||||
fn draw_sprite(&mut self, player: &Player, vis: &VisSprite, pixels: &mut PixelBuf) {
|
||||
let mut clip_bottom = vec![-2i32; pixels.width() as usize];
|
||||
let mut clip_top = vec![-2i32; pixels.width() as usize];
|
||||
fn draw_sprite(&mut self, player: &Player, vis: &VisSprite, pixels: &mut impl PixelBuffer) {
|
||||
let mut clip_bottom = vec![-2i32; pixels.width()];
|
||||
let mut clip_top = vec![-2i32; pixels.width()];
|
||||
|
||||
// Breaking liftime to enable this loop
|
||||
let segs = unsafe { &*(&self.r_data.drawsegs as *const Vec<DrawSeg>) };
|
||||
|
@ -391,7 +391,7 @@ impl SoftwareRenderer {
|
|||
self.draw_vissprite(vis, &clip_bottom, &clip_top, pixels);
|
||||
}
|
||||
|
||||
fn draw_player_sprites(&mut self, player: &Player, pixels: &mut PixelBuf) {
|
||||
fn draw_player_sprites(&mut self, player: &Player, pixels: &mut impl PixelBuffer) {
|
||||
if let Some(mobj) = player.mobj() {
|
||||
let light = unsafe { (*mobj.subsector).sector.lightlevel };
|
||||
let light = (light >> 4) + player.extralight;
|
||||
|
@ -409,7 +409,7 @@ impl SoftwareRenderer {
|
|||
sprite: &PspDef,
|
||||
light: usize,
|
||||
flags: u32,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let f = pixels.height() / 200;
|
||||
let pspriteiscale = 0.99 / f as f32;
|
||||
|
@ -463,12 +463,12 @@ impl SoftwareRenderer {
|
|||
vis.start_frac += vis.x_iscale * (vis.x1 - x1) as f32;
|
||||
}
|
||||
|
||||
let clip_bottom = vec![0i32; pixels.width() as usize];
|
||||
let clip_top = vec![pixels.height() as i32; pixels.width() as usize];
|
||||
let clip_bottom = vec![0i32; pixels.width()];
|
||||
let clip_top = vec![pixels.height() as i32; pixels.width()];
|
||||
self.draw_vissprite(&vis, &clip_top, &clip_bottom, pixels)
|
||||
}
|
||||
|
||||
pub(crate) fn draw_masked(&mut self, player: &Player, pixels: &mut PixelBuf) {
|
||||
pub(crate) fn draw_masked(&mut self, player: &Player, pixels: &mut impl PixelBuffer) {
|
||||
// Sort only the vissprites used
|
||||
self.vissprites[..self.next_vissprite].sort();
|
||||
// Need to break lifetime as a chain function call needs &mut on a separate item
|
||||
|
@ -494,7 +494,7 @@ impl SoftwareRenderer {
|
|||
ds: &DrawSeg,
|
||||
x1: i32,
|
||||
x2: i32,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let seg = unsafe { ds.curline.as_ref() };
|
||||
let frontsector = seg.frontsector.clone();
|
||||
|
@ -608,7 +608,7 @@ fn draw_masked_column(
|
|||
yl: i32,
|
||||
yh: i32,
|
||||
textures: &PicData,
|
||||
pixels: &mut PixelBuf,
|
||||
pixels: &mut impl PixelBuffer,
|
||||
) {
|
||||
let pal = &textures.palette();
|
||||
let mut frac = dc_texturemid + 0.5 + (yl as f32 - (pixels.height() / 2) as f32) * fracstep;
|
||||
|
@ -627,7 +627,7 @@ fn draw_masked_column(
|
|||
|
||||
let px = colourmap[texture_column[select]];
|
||||
let c = pal[px];
|
||||
pixels.set_pixel(dc_x as usize, n as usize, c.r, c.g, c.b, 255);
|
||||
pixels.set_pixel(dc_x as usize, n as usize, (c.r, c.g, c.b, 255));
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,3 +7,4 @@ build = "../../build.rs"
|
|||
|
||||
[dependencies]
|
||||
gameplay.workspace = true
|
||||
golem.workspace = true
|
||||
|
|
|
@ -2,108 +2,278 @@
|
|||
//! and a generic `PlayRenderer` for rendering the players view of the level.
|
||||
|
||||
use gameplay::{Level, Player};
|
||||
use golem::{ColorFormat, Context, GolemError, Texture, TextureFilter};
|
||||
|
||||
const CHANNELS: usize = 3;
|
||||
const CHANNELS: usize = 4;
|
||||
|
||||
/// A structure holding display data
|
||||
pub struct PixelBuf {
|
||||
width: u32,
|
||||
height: u32,
|
||||
is_software: bool,
|
||||
/// Total length is width * height * CHANNELS, where CHANNELS is RGB bytes
|
||||
software_buffer: Vec<u8>,
|
||||
#[derive(Debug, Default, PartialEq, PartialOrd, Clone, Copy)]
|
||||
pub enum RenderType {
|
||||
/// Purely software. Typically used with blitting a framebuffer maintained in memory
|
||||
/// directly to screen using SDL2
|
||||
#[default]
|
||||
Software,
|
||||
/// Software framebuffer blitted to screen using OpenGL (and can use shaders)
|
||||
SoftOpenGL,
|
||||
/// OpenGL
|
||||
OpenGL,
|
||||
/// Vulkan
|
||||
Vulkan,
|
||||
}
|
||||
|
||||
impl PixelBuf {
|
||||
pub fn new(width: u32, height: u32, is_software: bool) -> Self {
|
||||
pub trait PixelBuffer {
|
||||
fn width(&self) -> usize;
|
||||
fn height(&self) -> usize;
|
||||
fn clear(&mut self);
|
||||
fn set_pixel(&mut self, x: usize, y: usize, rgba: (u8, u8, u8, u8));
|
||||
fn read_softbuf_pixel(&self, x: usize, y: usize) -> (u8, u8, u8, u8);
|
||||
fn read_softbuf_pixels(&mut self) -> &mut [u8];
|
||||
}
|
||||
|
||||
/// A structure holding display data
|
||||
pub struct SoftFramebuffer {
|
||||
width: usize,
|
||||
height: usize,
|
||||
/// Total length is width * height * CHANNELS, where CHANNELS is RGB bytes
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl SoftFramebuffer {
|
||||
fn new(width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
is_software,
|
||||
software_buffer: if is_software {
|
||||
vec![0; (width * height) as usize * CHANNELS]
|
||||
} else {
|
||||
Vec::default()
|
||||
},
|
||||
buffer: vec![0; (width * height) * CHANNELS],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// pub fn clear(&mut self) {
|
||||
// self.data = vec![0; (self.width * self.height) as usize * CHANNELS]
|
||||
// }
|
||||
|
||||
impl PixelBuffer for SoftFramebuffer {
|
||||
#[inline]
|
||||
pub const fn width(&self) -> u32 {
|
||||
fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn height(&self) -> u32 {
|
||||
fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
|
||||
/// Set this pixel at X|Y to RGBA colour
|
||||
#[inline]
|
||||
pub fn set_pixel(&mut self, x: usize, y: usize, r: u8, g: u8, b: u8, _a: u8) {
|
||||
fn clear(&mut self) {
|
||||
self.buffer.iter_mut().for_each(|n| *n = 0);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_pixel(&mut self, x: usize, y: usize, rgba: (u8, u8, u8, u8)) {
|
||||
// Shitty safeguard. Need to find actual cause of fail
|
||||
if x >= self.width as usize || y >= self.height as usize {
|
||||
if x >= self.width || y >= self.height {
|
||||
return;
|
||||
}
|
||||
|
||||
let pos = y * (self.width as usize * CHANNELS) + x * CHANNELS;
|
||||
self.software_buffer[pos] = r;
|
||||
self.software_buffer[pos + 1] = g;
|
||||
self.software_buffer[pos + 2] = b;
|
||||
let pos = y * (self.width * CHANNELS) + x * CHANNELS;
|
||||
self.buffer[pos] = rgba.0;
|
||||
self.buffer[pos + 1] = rgba.1;
|
||||
self.buffer[pos + 2] = rgba.2;
|
||||
self.buffer[pos + 3] = rgba.3;
|
||||
}
|
||||
|
||||
/// Read the colour of a single pixel at X|Y
|
||||
pub fn read_pixel(&self, x: usize, y: usize) -> (u8, u8, u8, u8) {
|
||||
let pos = y * (self.width as usize * CHANNELS) + x * CHANNELS;
|
||||
#[inline]
|
||||
fn read_softbuf_pixel(&self, x: usize, y: usize) -> (u8, u8, u8, u8) {
|
||||
let pos = y * (self.width * CHANNELS) + x * CHANNELS;
|
||||
(
|
||||
self.software_buffer[pos],
|
||||
self.software_buffer[pos + 1],
|
||||
self.software_buffer[pos + 2],
|
||||
0,
|
||||
self.buffer[pos],
|
||||
self.buffer[pos + 1],
|
||||
self.buffer[pos + 2],
|
||||
self.buffer[pos + 3],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_software(&self) -> bool {
|
||||
self.is_software
|
||||
/// Read the full buffer
|
||||
#[inline]
|
||||
fn read_softbuf_pixels(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure holding display data
|
||||
pub struct SoftOpenGL {
|
||||
width: usize,
|
||||
height: usize,
|
||||
frame_buffer: SoftFramebuffer,
|
||||
gl_texture: Texture,
|
||||
}
|
||||
|
||||
impl SoftOpenGL {
|
||||
fn new(width: usize, height: usize, ctx: &Context) -> Self {
|
||||
let mut gl_texture = Texture::new(ctx).unwrap();
|
||||
gl_texture.set_image(None, width as u32, height as u32, golem::ColorFormat::RGB);
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
frame_buffer: SoftFramebuffer::new(width, height),
|
||||
gl_texture,
|
||||
}
|
||||
}
|
||||
|
||||
// /// Get the array of pixels. The layout of which is [Row<RGBA>]
|
||||
pub fn read_pixels(&self) -> &[u8] {
|
||||
&self.software_buffer
|
||||
#[inline]
|
||||
pub fn frame_buffer(&mut self) -> &mut SoftFramebuffer {
|
||||
&mut self.frame_buffer
|
||||
}
|
||||
|
||||
pub fn read_pixels_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.software_buffer
|
||||
#[inline]
|
||||
pub const fn gl_texture(&self) -> &Texture {
|
||||
&self.gl_texture
|
||||
}
|
||||
|
||||
pub fn set_gl_filter(&self) -> Result<(), GolemError> {
|
||||
self.gl_texture.set_minification(TextureFilter::Linear)?;
|
||||
self.gl_texture.set_magnification(TextureFilter::Linear)
|
||||
}
|
||||
|
||||
pub fn copy_softbuf_to_gl_texture(&mut self) {
|
||||
self.gl_texture.set_image(
|
||||
Some(&self.frame_buffer.buffer),
|
||||
self.width as u32,
|
||||
self.height as u32,
|
||||
ColorFormat::RGBA,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelBuffer for SoftOpenGL {
|
||||
#[inline]
|
||||
fn width(&self) -> usize {
|
||||
self.frame_buffer.width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn height(&self) -> usize {
|
||||
self.frame_buffer.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clear(&mut self) {
|
||||
self.frame_buffer.clear();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_pixel(&mut self, x: usize, y: usize, rgba: (u8, u8, u8, u8)) {
|
||||
self.frame_buffer.set_pixel(x, y, rgba);
|
||||
}
|
||||
|
||||
/// Read the colour of a single pixel at X|Y
|
||||
#[inline]
|
||||
fn read_softbuf_pixel(&self, x: usize, y: usize) -> (u8, u8, u8, u8) {
|
||||
self.frame_buffer.read_softbuf_pixel(x, y)
|
||||
}
|
||||
|
||||
/// Read the full buffer
|
||||
#[inline]
|
||||
fn read_softbuf_pixels(&mut self) -> &mut [u8] {
|
||||
&mut self.frame_buffer.buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure holding display data
|
||||
pub struct RenderTarget {
|
||||
width: usize,
|
||||
height: usize,
|
||||
render_type: RenderType,
|
||||
/// Total length is width * height * CHANNELS, where CHANNELS is RGB bytes
|
||||
software: Option<SoftFramebuffer>,
|
||||
soft_opengl: Option<SoftOpenGL>,
|
||||
}
|
||||
|
||||
impl RenderTarget {
|
||||
pub fn new(width: usize, height: usize, ctx: &Context, render_type: RenderType) -> Self {
|
||||
let mut software = None;
|
||||
let mut soft_opengl = None;
|
||||
|
||||
match render_type {
|
||||
RenderType::Software => software = Some(SoftFramebuffer::new(width, height)),
|
||||
RenderType::SoftOpenGL => soft_opengl = Some(SoftOpenGL::new(width, height, ctx)),
|
||||
RenderType::OpenGL => todo!(),
|
||||
RenderType::Vulkan => todo!(),
|
||||
}
|
||||
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
render_type,
|
||||
software,
|
||||
soft_opengl,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn render_type(&self) -> RenderType {
|
||||
self.render_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn software(&mut self) -> Option<&mut SoftFramebuffer> {
|
||||
self.software.as_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn software_unchecked(&mut self) -> &mut SoftFramebuffer {
|
||||
self.software.as_mut().unwrap_unchecked()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn soft_opengl(&mut self) -> Option<&mut SoftOpenGL> {
|
||||
self.soft_opengl.as_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn soft_opengl_unchecked(&mut self) -> &mut SoftOpenGL {
|
||||
self.soft_opengl.as_mut().unwrap_unchecked()
|
||||
}
|
||||
|
||||
// // /// Get the array of pixels. The layout of which is [Row<RGBA>]
|
||||
// pub fn softbuf_pixels(&self) -> &[u8] {
|
||||
// &self.software
|
||||
// }
|
||||
|
||||
// pub fn softbuf_pixels_mut(&mut self) -> &mut [u8] {
|
||||
// &mut self.software
|
||||
// }
|
||||
}
|
||||
|
||||
pub trait PlayRenderer {
|
||||
/// Drawing the full player view to the `PixelBuf`.
|
||||
///
|
||||
/// Doom function name `R_RenderPlayerView`
|
||||
fn render_player_view(&mut self, player: &Player, level: &Level, buf: &mut PixelBuf);
|
||||
fn render_player_view(&mut self, player: &Player, level: &Level, buf: &mut RenderTarget);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::PixelBuf;
|
||||
// TODO: somehow test with gl context
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::PixelBuf;
|
||||
|
||||
#[test]
|
||||
fn write_read_pixel() {
|
||||
let mut pixels = PixelBuf::new(320, 200, true);
|
||||
// #[test]
|
||||
// fn write_read_pixel() {
|
||||
// let mut pixels = PixelBuf::new(320, 200, true);
|
||||
|
||||
pixels.set_pixel(10, 10, 255, 10, 3, 255);
|
||||
pixels.set_pixel(319, 199, 25, 10, 3, 255);
|
||||
// pixels.set_pixel(10, 10, 255, 10, 3, 255);
|
||||
// pixels.set_pixel(319, 199, 25, 10, 3, 255);
|
||||
|
||||
let px = pixels.read_pixel(10, 10);
|
||||
assert_eq!(px, (255, 10, 3, 0));
|
||||
// let px = pixels.read_pixel(10, 10);
|
||||
// assert_eq!(px, (255, 10, 3, 0));
|
||||
|
||||
let px = pixels.read_pixel(319, 199);
|
||||
assert_eq!(px, (25, 10, 3, 0));
|
||||
}
|
||||
}
|
||||
// let px = pixels.read_pixel(319, 199);
|
||||
// assert_eq!(px, (25, 10, 3, 0));
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -8,10 +8,8 @@ build = "../../build.rs"
|
|||
[features]
|
||||
|
||||
[dependencies]
|
||||
wad = { path = "../../wad" }
|
||||
sound-traits = { path = "../traits" }
|
||||
# versions are set by game-exe crate
|
||||
log = "*"
|
||||
glam = "*"
|
||||
# Required for config options
|
||||
serde = { version = "*", features = ["serde_derive"] }
|
||||
wad.workspace = true
|
||||
sound-traits.workspace = true
|
||||
log.workspace = true
|
||||
glam.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
use faces::DoomguyFace;
|
||||
use gamestate_traits::{
|
||||
util::{draw_num, get_num_sprites, get_st_key_sprites},
|
||||
AmmoType, GameMode, GameTraits, MachinationTrait, PixelBuf, PlayerStatus, Scancode, WeaponType,
|
||||
WEAPON_INFO,
|
||||
util::{draw_num_pixels, get_num_sprites, get_st_key_sprites},
|
||||
AmmoType, GameMode, GameTraits, MachinationTrait, PixelBuffer, PlayerStatus, RenderTarget,
|
||||
Scancode, WeaponType, WEAPON_INFO,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use wad::{
|
||||
|
@ -64,8 +64,8 @@ impl Statusbar {
|
|||
.unwrap_or_else(|| panic!("{name} not in cache"))
|
||||
}
|
||||
|
||||
fn draw_health(&self, big: bool, face: bool, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
fn draw_health_pixels(&self, big: bool, face: bool, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
|
||||
let nums = if big { &self.big_nums } else { &self.lil_nums };
|
||||
|
||||
|
@ -94,14 +94,14 @@ impl Statusbar {
|
|||
if h < 10 {
|
||||
x -= nums[0].width as i32;
|
||||
}
|
||||
draw_num(h, x, self.screen_height - 2 - y, 0, nums, self, buffer);
|
||||
draw_num_pixels(h, x, self.screen_height - 2 - y, 0, nums, self, pixels);
|
||||
}
|
||||
|
||||
fn draw_armour(&self, face: bool, buffer: &mut PixelBuf) {
|
||||
fn draw_armour_pixels(&self, face: bool, pixels: &mut impl PixelBuffer) {
|
||||
if self.status.armorpoints <= 0 {
|
||||
return;
|
||||
}
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
|
||||
let nums = &self.lil_nums;
|
||||
|
||||
|
@ -120,10 +120,10 @@ impl Statusbar {
|
|||
if h < 10 {
|
||||
x -= nums[0].width as i32;
|
||||
}
|
||||
draw_num(h, x, self.screen_height - 2 - y, 0, nums, self, buffer);
|
||||
draw_num_pixels(h, x, self.screen_height - 2 - y, 0, nums, self, pixels);
|
||||
}
|
||||
|
||||
fn draw_ammo_big(&self, buffer: &mut PixelBuf) {
|
||||
fn draw_ammo_big_pixels(&self, pixels: &mut impl PixelBuffer) {
|
||||
if matches!(self.status.readyweapon, WeaponType::NoChange) {
|
||||
return;
|
||||
}
|
||||
|
@ -137,24 +137,24 @@ impl Statusbar {
|
|||
if ammo == AmmoType::NoAmmo {
|
||||
return;
|
||||
}
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
|
||||
let height = self.big_nums[0].height as i32 * f;
|
||||
let start_x = self.big_nums[0].width as i32 * f + self.keys[0].width as i32 * f + 2;
|
||||
let ammo = self.status.ammo[ammo as usize];
|
||||
draw_num(
|
||||
draw_num_pixels(
|
||||
ammo,
|
||||
self.screen_width - start_x,
|
||||
self.screen_height - 2 - height - self.grey_nums[0].height as i32 * f,
|
||||
0,
|
||||
&self.big_nums,
|
||||
self,
|
||||
buffer,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_keys(&self, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
fn draw_keys_pixels(&self, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
let height = self.keys[3].height as i32 * f;
|
||||
let width = self.keys[0].width as i32 * f;
|
||||
|
||||
|
@ -176,17 +176,17 @@ impl Statusbar {
|
|||
} else {
|
||||
pad = -3;
|
||||
}
|
||||
self.draw_patch(
|
||||
self.draw_patch_pixels(
|
||||
patch,
|
||||
x,
|
||||
start_y - pad - height * i as i32 - i as i32,
|
||||
buffer,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_weapons(&self, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
fn draw_weapons_pixels(&self, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
let y = self.grey_nums[0].height as i32 * f;
|
||||
let x = self.grey_nums[0].width as i32 * f;
|
||||
let mult = if self.mode == GameMode::Commercial {
|
||||
|
@ -209,20 +209,20 @@ impl Statusbar {
|
|||
} else {
|
||||
&self.grey_nums
|
||||
};
|
||||
draw_num(
|
||||
draw_num_pixels(
|
||||
i as u32 + 1,
|
||||
start_x + x * i as i32 + i as i32,
|
||||
start_y,
|
||||
0,
|
||||
nums,
|
||||
self,
|
||||
buffer,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_face(&self, mut big: bool, upper: bool, buffer: &mut PixelBuf) {
|
||||
let f = (buffer.height() / 200) as i32;
|
||||
fn draw_face_pixels(&self, mut big: bool, upper: bool, pixels: &mut impl PixelBuffer) {
|
||||
let f = (pixels.height() / 200) as i32;
|
||||
if upper {
|
||||
big = true;
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ impl Statusbar {
|
|||
self.screen_height - patch.height as i32
|
||||
};
|
||||
x = self.screen_width / 2 - patch.width as i32 / 2;
|
||||
self.draw_patch(patch, x, y, buffer);
|
||||
self.draw_patch_pixels(patch, x, y, pixels);
|
||||
};
|
||||
|
||||
let patch = self.faces.get_face();
|
||||
|
@ -255,7 +255,7 @@ impl Statusbar {
|
|||
x = offset_x;
|
||||
y = self.screen_height - offset_y
|
||||
};
|
||||
self.draw_patch(patch, x, y, buffer);
|
||||
self.draw_patch_pixels(patch, x, y, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,18 +276,36 @@ impl MachinationTrait for Statusbar {
|
|||
&self.palette
|
||||
}
|
||||
|
||||
fn draw(&mut self, buffer: &mut PixelBuf) {
|
||||
fn draw(&mut self, buffer: &mut RenderTarget) {
|
||||
self.screen_width = buffer.width() as i32;
|
||||
self.screen_height = buffer.height() as i32;
|
||||
|
||||
let face = true;
|
||||
if face {
|
||||
self.draw_face(false, false, buffer);
|
||||
match buffer.render_type() {
|
||||
gamestate_traits::RenderType::Software => {
|
||||
let pixels = unsafe { buffer.software_unchecked() };
|
||||
if face {
|
||||
self.draw_face_pixels(false, false, pixels);
|
||||
}
|
||||
self.draw_health_pixels(true, face, pixels);
|
||||
self.draw_armour_pixels(face, pixels);
|
||||
self.draw_ammo_big_pixels(pixels);
|
||||
self.draw_weapons_pixels(pixels);
|
||||
self.draw_keys_pixels(pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::SoftOpenGL => {
|
||||
let pixels = unsafe { buffer.soft_opengl_unchecked() };
|
||||
if face {
|
||||
self.draw_face_pixels(false, false, pixels);
|
||||
}
|
||||
self.draw_health_pixels(true, face, pixels);
|
||||
self.draw_armour_pixels(face, pixels);
|
||||
self.draw_ammo_big_pixels(pixels);
|
||||
self.draw_weapons_pixels(pixels);
|
||||
self.draw_keys_pixels(pixels);
|
||||
}
|
||||
gamestate_traits::RenderType::OpenGL => todo!(),
|
||||
gamestate_traits::RenderType::Vulkan => todo!(),
|
||||
}
|
||||
self.draw_health(true, face, buffer);
|
||||
self.draw_armour(face, buffer);
|
||||
self.draw_ammo_big(buffer);
|
||||
self.draw_weapons(buffer);
|
||||
self.draw_keys(buffer);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue