Tweak light rendering

I think I'll scrap this bad CPU ray tracer and re-do it using shaders
This commit is contained in:
Alula 2023-09-12 05:02:32 +02:00
parent 21221d80e7
commit f0c2101694
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
10 changed files with 83 additions and 61 deletions

View File

@ -243,7 +243,7 @@ impl WaterRenderer {
return Ok(());
}
graphics::set_render_target(ctx, state.lightmap_canvas.as_ref())?;
graphics::set_render_target(ctx, state.water_canvas.as_ref())?;
graphics::clear(ctx, Color::from_rgba(0, 0, 0, 0));
graphics::set_blend_mode(ctx, BlendMode::None)?;
@ -346,7 +346,7 @@ impl WaterRenderer {
graphics::set_render_target(ctx, None)?;
{
let canvas = state.lightmap_canvas.as_mut().unwrap();
let canvas = state.water_canvas.as_mut().unwrap();
let rect = Rect { left: 0.0, top: 0.0, right: state.screen_size.0, bottom: state.screen_size.1 };
canvas.clear();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -53,7 +53,7 @@ pub trait BackendRenderer {
Ok(())
}
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>>;
fn create_texture_mutable(&mut self, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>>;
fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult<Box<dyn BackendTexture>>;

View File

@ -5,20 +5,19 @@ use std::mem;
use std::pin::Pin;
use std::ptr::slice_from_raw_parts_mut;
use deko3d::{
Barrier, BlendFactor, BlendOp, BlendState, CmdBuf, CmdBufMaker, ColorMask, ColorState, ColorWriteState,
CopyBuf, DepthStencilState, DeviceMaker, DK_CMDMEM_ALIGNMENT, DK_MEMBLOCK_ALIGNMENT, DK_SHADER_CODE_ALIGNMENT, DK_SHADER_CODE_UNUSABLE_SIZE, DK_UNIFORM_BUF_ALIGNMENT, Face,
Filter, Image, ImageDescriptor, ImageFlags, ImageFormat, ImageLayout, ImageLayoutMaker, ImageRect,
ImageView, InvalidateFlags, make_texture_handle, MemBlock, MemBlockFlags, MemBlockMaker, MipFilter, Primitive,
QueueFlags, QueueMaker, RasterizerState, ResHandle, Sampler, SamplerDescriptor, Scissor, Shader, ShaderMaker,
Stage, StageFlag, SwapchainMaker, Viewport, VtxAttribSize, VtxAttribState,
VtxAttribType, VtxBufferState, WrapMode,
};
use imgui::{DrawData, TextureId, Ui};
use itertools::all;
use lazy_static::lazy_static;
use deko3d::{
make_texture_handle, Barrier, BlendFactor, BlendOp, BlendState, CmdBuf, CmdBufMaker, ColorMask, ColorState,
ColorWriteState, CopyBuf, DepthStencilState, DeviceMaker, Face, Filter, Image, ImageDescriptor, ImageFlags,
ImageFormat, ImageLayout, ImageLayoutMaker, ImageRect, ImageView, InvalidateFlags, MemBlock, MemBlockFlags,
MemBlockMaker, MipFilter, Primitive, QueueFlags, QueueMaker, RasterizerState, ResHandle, Sampler,
SamplerDescriptor, Scissor, Shader, ShaderMaker, Stage, StageFlag, SwapchainMaker, Viewport, VtxAttribSize,
VtxAttribState, VtxAttribType, VtxBufferState, WrapMode, DK_CMDMEM_ALIGNMENT, DK_MEMBLOCK_ALIGNMENT,
DK_SHADER_CODE_ALIGNMENT, DK_SHADER_CODE_UNUSABLE_SIZE, DK_UNIFORM_BUF_ALIGNMENT,
};
use crate::common::{Color, Rect};
use crate::framework::backend::{
Backend, BackendEventLoop, BackendGamepad, BackendRenderer, BackendShader, BackendTexture, SpriteBatchCommand,
@ -30,8 +29,8 @@ use crate::framework::gamepad;
use crate::framework::gamepad::{Axis, Button, GamepadType};
use crate::framework::graphics::BlendMode;
use crate::framework::util::field_offset;
use crate::game::shared_game_state::SharedGameState;
use crate::game::Game;
use crate::game::shared_game_state::SharedGameState;
mod nx {
type NWindow = std::ffi::c_void;
@ -471,7 +470,8 @@ lazy_static! {
struct Deko3DVertexBuffer {
buffer: deko3d::MemBlock,
capacity: usize, // those two are in bytes
capacity: usize,
// those two are in bytes
allocated: usize,
}
@ -1017,14 +1017,14 @@ impl BackendRenderer for Deko3DRenderer {
Ok(())
}
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
fn create_texture_mutable(&mut self, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>> {
let img_total = width as u32 * height as u32 * 4;
let desc_memory = MemBlockMaker::new(
&self.device,
align(std::mem::size_of::<Deko3DTextureDesc>() as u32, DK_MEMBLOCK_ALIGNMENT),
)
.set_flags(MemBlockFlags::CpuUncached | MemBlockFlags::GpuCached)
.create();
.set_flags(MemBlockFlags::CpuUncached | MemBlockFlags::GpuCached)
.create();
let mut desc_cpu = unsafe { &mut *(desc_memory.get_cpu_addr() as *mut Deko3DTextureDesc) };
desc_cpu.sampler = SamplerDescriptor::new();
@ -1034,22 +1034,22 @@ impl BackendRenderer for Deko3DRenderer {
ImageLayoutMaker::new(&self.device)
.set_flags(ImageFlags::UsageRender | ImageFlags::BlockLinear)
.set_format(ImageFormat::RGBA8Unorm)
.set_dimensions(width as u32, height as u32, 0)
.set_dimensions((width as f32 * scale) as u32, (height as f32 * scale) as u32, 0)
.initialize(&mut layout);
let memory = MemBlockMaker::new(
&self.device,
align(layout.get_size() as u32, DK_MEMBLOCK_ALIGNMENT.max(layout.get_alignment())),
)
.set_flags(MemBlockFlags::Image | MemBlockFlags::GpuCached)
.create();
.set_flags(MemBlockFlags::Image | MemBlockFlags::GpuCached)
.create();
let mut image = Image::new();
image.initialize(&layout, &memory, 0);
desc_cpu.image.initialize(&ImageView::new(&image), false, false);
desc_cpu.sampler.initialize(
&Sampler::new().set_filter(Filter::Nearest, Filter::Nearest, MipFilter::None).set_wrap_mode(
&Sampler::new().set_filter(Filter::Linear, Filter::Linear, MipFilter::None).set_wrap_mode(
WrapMode::ClampToEdge,
WrapMode::ClampToEdge,
WrapMode::ClampToEdge,
@ -1075,8 +1075,8 @@ impl BackendRenderer for Deko3DRenderer {
&self.device,
align(std::mem::size_of::<Deko3DTextureDesc>() as u32, DK_MEMBLOCK_ALIGNMENT),
)
.set_flags(MemBlockFlags::CpuUncached | MemBlockFlags::GpuCached)
.create();
.set_flags(MemBlockFlags::CpuUncached | MemBlockFlags::GpuCached)
.create();
let scratch_memory = MemBlockMaker::new(&self.device, align(img_total, DK_MEMBLOCK_ALIGNMENT))
.set_flags(MemBlockFlags::CpuUncached | MemBlockFlags::GpuCached)
@ -1107,8 +1107,8 @@ impl BackendRenderer for Deko3DRenderer {
&self.device,
align(layout.get_size() as u32, DK_MEMBLOCK_ALIGNMENT.max(layout.get_alignment())),
)
.set_flags(MemBlockFlags::Image | MemBlockFlags::GpuCached)
.create();
.set_flags(MemBlockFlags::Image | MemBlockFlags::GpuCached)
.create();
let mut image = Image::new();
image.initialize(&layout, &memory, 0);

View File

@ -107,7 +107,7 @@ impl BackendRenderer for NullRenderer {
Ok(())
}
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
fn create_texture_mutable(&mut self, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>> {
Ok(Box::new(NullTexture(width, height)))
}

View File

@ -667,7 +667,7 @@ impl BackendRenderer for SDL2Renderer {
Ok(())
}
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
fn create_texture_mutable(&mut self, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>> {
let mut refs = self.refs.borrow_mut();
let texture = refs

View File

@ -67,7 +67,15 @@ pub fn renderer_initialized(ctx: &mut Context) -> bool {
pub fn create_texture_mutable(ctx: &mut Context, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
if let Some(renderer) = &mut ctx.renderer {
return renderer.create_texture_mutable(width, height);
return renderer.create_texture_mutable(width, height, 1.0);
}
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))
}
pub fn create_texture_mutable_scale(ctx: &mut Context, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>> {
if let Some(renderer) = &mut ctx.renderer {
return renderer.create_texture_mutable(width, height, scale);
}
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))

View File

@ -33,6 +33,8 @@ pub struct GLContext {
pub struct OpenGLTexture {
width: u16,
height: u16,
width_real: u16,
height_real: u16,
texture_id: u32,
framebuffer_id: u32,
shader: RenderShader,
@ -788,25 +790,28 @@ impl BackendRenderer for OpenGLRenderer {
}
}
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
fn create_texture_mutable(&mut self, width: u16, height: u16, scale: f32) -> GameResult<Box<dyn BackendTexture>> {
if let Some((_, gl)) = self.get_context() {
unsafe {
let current_texture_id = return_param(|x| gl.gl.GetIntegerv(gl::TEXTURE_BINDING_2D, x)) as u32;
let texture_id = return_param(|x| gl.gl.GenTextures(1, x));
let width_real = (width as f32 * scale) as u16;
let height_real = (height as f32 * scale) as u16;
gl.gl.BindTexture(gl::TEXTURE_2D, texture_id);
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as _);
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as _);
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _);
gl.gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _);
gl.gl.TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA as _,
width as _,
height as _,
gl::RGBA32F as _,
width_real as _,
height_real as _,
0,
gl::RGBA,
gl::UNSIGNED_BYTE,
gl::FLOAT,
null() as _,
);
@ -831,6 +836,8 @@ impl BackendRenderer for OpenGLRenderer {
framebuffer_id,
width,
height,
width_real,
height_real,
vertices: Vec::new(),
shader: self.render_data.tex_shader,
vbo: self.render_data.vbo,
@ -870,6 +877,8 @@ impl BackendRenderer for OpenGLRenderer {
framebuffer_id: 0,
width,
height,
width_real: width,
height_real: height,
vertices: Vec::new(),
shader: self.render_data.tex_shader,
vbo: self.render_data.vbo,
@ -950,7 +959,7 @@ impl BackendRenderer for OpenGLRenderer {
);
gl.gl.BindFramebuffer(gl::FRAMEBUFFER, gl_texture.framebuffer_id);
gl.gl.Viewport(0, 0, gl_texture.width as _, gl_texture.height as _);
gl.gl.Viewport(0, 0, gl_texture.width_real as _, gl_texture.height_real as _);
} else {
self.curr_matrix = self.def_matrix;

View File

@ -3,17 +3,17 @@ use std::{cmp, ops::Div};
use chrono::{Datelike, Local};
use crate::common::{ControlFlags, Direction, FadeState};
use crate::components::draw_common::{draw_number, Alignment};
use crate::components::draw_common::{Alignment, draw_number};
use crate::data::vanilla::VanillaExtractor;
#[cfg(feature = "discord-rpc")]
use crate::discord::DiscordRPC;
use crate::engine_constants::EngineConstants;
use crate::framework::{filesystem, graphics};
use crate::framework::backend::BackendTexture;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics::{create_texture_mutable, set_render_target};
use crate::framework::graphics::{create_texture_mutable, create_texture_mutable_scale, set_render_target};
use crate::framework::vfs::OpenOptions;
use crate::framework::{filesystem, graphics};
use crate::game::caret::{Caret, CaretType};
use crate::game::npc::NPCTable;
use crate::game::profile::GameProfile;
@ -30,8 +30,8 @@ use crate::input::touch_controls::TouchControls;
use crate::mod_list::ModList;
use crate::mod_requirements::ModRequirements;
use crate::scene::game_scene::GameScene;
use crate::scene::title_scene::TitleScene;
use crate::scene::Scene;
use crate::scene::title_scene::TitleScene;
use crate::sound::SoundManager;
use crate::util::bitvec::BitVec;
use crate::util::rng::XorShift;
@ -324,6 +324,7 @@ pub struct SharedGameState {
pub textscript_vm: TextScriptVM,
pub creditscript_vm: CreditScriptVM,
pub lightmap_canvas: Option<Box<dyn BackendTexture>>,
pub water_canvas: Option<Box<dyn BackendTexture>>,
pub season: Season,
pub menu_character: MenuCharacter,
pub fs_container: Option<FilesystemContainer>,
@ -368,7 +369,7 @@ impl SharedGameState {
#[cfg(not(target_os = "horizon"))]
if let Some(vanilla_extractor) =
VanillaExtractor::from(ctx, vanilla_ext_exe.to_string(), vanilla_ext_outdir.to_string())
VanillaExtractor::from(ctx, vanilla_ext_exe.to_string(), vanilla_ext_outdir.to_string())
{
let result = vanilla_extractor.extract_data();
if let Err(e) = result {
@ -418,11 +419,11 @@ impl SharedGameState {
let locale = SharedGameState::get_locale(&constants, &settings.locale).unwrap_or_default();
if (locale.code == "jp" || locale.code == "en") && constants.is_base() {
constants.textscript.encoding = TextScriptEncoding::ShiftJIS
constants.textscript.encoding = TextScriptEncoding::ShiftJIS
} else {
constants.textscript.encoding = TextScriptEncoding::UTF8
constants.textscript.encoding = TextScriptEncoding::UTF8
}
let font = BMFont::load(&constants.base_paths, &locale.font.path, ctx, locale.font.scale).or_else(|e| {
log::warn!("Failed to load font, using built-in: {}", e);
BMFont::load(&vec!["/".to_owned()], "builtin/builtin_font.fnt", ctx, 1.0)
@ -452,7 +453,7 @@ impl SharedGameState {
let seed = chrono::Local::now().timestamp() as i32;
#[cfg(feature = "discord-rpc")]
let discord_rpc_app_id = match option_env!("DISCORD_RPC_APP_ID") {
let discord_rpc_app_id = match option_env!("DISCORD_RPC_APP_ID") {
Some(app_id) => app_id,
None => "1076523467337367622",
};
@ -492,6 +493,7 @@ impl SharedGameState {
textscript_vm: TextScriptVM::new(),
creditscript_vm: CreditScriptVM::new(),
lightmap_canvas: None,
water_canvas: None,
season,
menu_character: MenuCharacter::Quote,
fs_container: None,
@ -571,9 +573,9 @@ impl SharedGameState {
if let Some(locale) = SharedGameState::get_locale(&self.constants, &self.settings.locale) {
self.loc = locale;
if (self.loc.code == "jp" || self.loc.code == "en") && self.constants.is_base() {
self.constants.textscript.encoding = TextScriptEncoding::ShiftJIS
self.constants.textscript.encoding = TextScriptEncoding::ShiftJIS
} else {
self.constants.textscript.encoding = TextScriptEncoding::UTF8
self.constants.textscript.encoding = TextScriptEncoding::UTF8
}
}
@ -594,10 +596,10 @@ impl SharedGameState {
pub fn start_new_game(&mut self, ctx: &mut Context) -> GameResult {
self.reset();
#[cfg(feature = "scripting-lua")]
self.lua.reload_scripts(ctx)?;
self.lua.reload_scripts(ctx)?;
#[cfg(feature = "discord-rpc")]
self.discord_rpc.update_difficulty(self.difficulty)?;
self.discord_rpc.update_difficulty(self.difficulty)?;
let mut next_scene = GameScene::new(self, ctx, self.constants.game.new_game_stage as usize)?;
next_scene.player1.cond.set_alive(true);
@ -619,7 +621,7 @@ impl SharedGameState {
pub fn start_intro(&mut self, ctx: &mut Context) -> GameResult {
#[cfg(feature = "scripting-lua")]
self.lua.reload_scripts(ctx)?;
self.lua.reload_scripts(ctx)?;
let start_stage_id = self.constants.game.intro_stage as usize;
@ -671,10 +673,10 @@ impl SharedGameState {
profile.apply(self, &mut next_scene, ctx);
#[cfg(feature = "scripting-lua")]
self.lua.reload_scripts(ctx)?;
self.lua.reload_scripts(ctx)?;
#[cfg(feature = "discord-rpc")]
self.discord_rpc.update_difficulty(self.difficulty)?;
self.discord_rpc.update_difficulty(self.difficulty)?;
self.next_scene = Some(Box::new(next_scene));
return Ok(());
@ -717,7 +719,8 @@ impl SharedGameState {
// ensure no texture is bound before destroying them.
set_render_target(ctx, None)?;
self.lightmap_canvas = Some(create_texture_mutable(ctx, width, height)?);
self.lightmap_canvas = Some(create_texture_mutable_scale(ctx, width, height, 0.125)?);
self.water_canvas = Some(create_texture_mutable(ctx, width, height)?);
Ok(())
}
@ -747,7 +750,7 @@ impl SharedGameState {
self.shutdown = true;
#[cfg(feature = "discord-rpc")]
self.discord_rpc.dispose();
self.discord_rpc.dispose();
}
// Stops SFX 40/41/58 (CPS and CSS)

View File

@ -405,8 +405,8 @@ impl GameScene {
'ray: for (i, deg) in angle.enumerate() {
let d = deg as f32 * (std::f32::consts::PI / 180.0);
let dx = d.cos() * -5.0;
let dy = d.sin() * -5.0;
let dx = d.cos() * -3.0;
let dy = d.sin() * -3.0;
let m = 1.0 - ((ahalf - i as f32).abs() / ahalf);
let mut x = px;
let mut y = py;
@ -414,9 +414,11 @@ impl GameScene {
let mut g = bg;
let mut b = bb;
for i in 0..40 {
x += dx;
y += dy;
for i in 0..35 {
let scale = 0.8 + i as f32 * 0.075;
let m = m * (0.25 + i as f32 / 30.0);
x += dx * scale;
y += dy * scale;
const ARR: [(i32, i32); 4] = [(0, 0), (0, 1), (1, 0), (1, 1)];
for (ox, oy) in ARR.iter() {
@ -490,7 +492,7 @@ impl GameScene {
self.draw_light(
x - fx2,
y - fy2,
0.15 + i as f32 / 75.0,
0.075 + i as f32 / 60.0,
((r * m) as u8, (g * m) as u8, (b * m) as u8),
batch,
);