idk shitload of stuff
This commit is contained in:
+42
-16
@@ -10,11 +10,14 @@ use std::sync::Arc;
|
||||
|
||||
use winit::window::Window;
|
||||
|
||||
use crate::engine::tga::Image;
|
||||
use crate::render::math::Mat4;
|
||||
use crate::render::scene::ScenePass;
|
||||
use crate::render::scene::{Mesh, ScenePass};
|
||||
use crate::render::sprite::SpritePass;
|
||||
use crate::render::ui::Ui;
|
||||
|
||||
pub const INTERNAL_W: u32 = 480;
|
||||
pub const INTERNAL_H: u32 = 360;
|
||||
pub const INTERNAL_W: u32 = 320;
|
||||
pub const INTERNAL_H: u32 = 240;
|
||||
|
||||
/// D16 reicht für PS1-Geometrieskalen und ist das älteste, überall
|
||||
/// (auch GL-Fallback) unterstützte Depth-Format.
|
||||
@@ -31,12 +34,19 @@ pub struct Gpu {
|
||||
depth_view: wgpu::TextureView,
|
||||
|
||||
scene: ScenePass,
|
||||
sprite: SpritePass,
|
||||
blit_pipeline: wgpu::RenderPipeline,
|
||||
blit_bind: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
impl Gpu {
|
||||
pub fn new(window: Arc<Window>, display: winit::event_loop::OwnedDisplayHandle) -> Self {
|
||||
pub fn new(
|
||||
window: Arc<Window>,
|
||||
display: winit::event_loop::OwnedDisplayHandle,
|
||||
mesh: &Mesh,
|
||||
images: &[Image],
|
||||
ui_textures: &[Image],
|
||||
) -> Self {
|
||||
let size = window.inner_size();
|
||||
// Display-Handle mitgeben: für den GL-Fallback (v.a. Wayland)
|
||||
// Pflicht; Vulkan ignoriert es. `with_env` erlaubt Overrides wie
|
||||
@@ -86,8 +96,15 @@ impl Gpu {
|
||||
|
||||
let (internal_view, depth_view) = make_internal_targets(&device);
|
||||
|
||||
// Pass 1: die Szene.
|
||||
let scene = ScenePass::new(&device, INTERNAL_FORMAT, DEPTH_FORMAT);
|
||||
// Pass 1: die Szene. Geometrie + Bilder kommen fertig vom Aufrufer
|
||||
// (Decode in render::run); hier wird nur hochgeladen.
|
||||
let scene = ScenePass::new(&device, &queue, INTERNAL_FORMAT, DEPTH_FORMAT, mesh, images);
|
||||
|
||||
// Overlay-Pass: zeichnet nach der Szene ins selbe interne Target.
|
||||
let sprite = SpritePass::new(
|
||||
&device, &queue, INTERNAL_FORMAT, DEPTH_FORMAT,
|
||||
[INTERNAL_W as f32, INTERNAL_H as f32], ui_textures,
|
||||
);
|
||||
|
||||
// Pass 2: internes Target nearest-gesampelt auf die Surface.
|
||||
let blit_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
@@ -139,7 +156,7 @@ impl Gpu {
|
||||
Self {
|
||||
surface, device, queue, config,
|
||||
internal_view, depth_view,
|
||||
scene, blit_pipeline, blit_bind,
|
||||
scene, sprite, blit_pipeline, blit_bind,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,20 +166,27 @@ impl Gpu {
|
||||
self.surface.configure(&self.device, &self.config);
|
||||
}
|
||||
|
||||
/// Einen Frame rendern. `t` = Sekunden seit Start (treibt vorerst
|
||||
/// die Orbit-Kamera; ab Schritt 4 kommt die Kamera vom Aufrufer).
|
||||
pub fn frame(&mut self, t: f32) {
|
||||
// Hartkodierte Orbit-Kamera um den Testwürfel — macht Vertex-Snap
|
||||
// und Dither in Bewegung sichtbar. Die Flycam ersetzt sie.
|
||||
let yaw = t * 0.4;
|
||||
let eye = [2.2 * yaw.sin(), 1.3, 2.2 * yaw.cos()];
|
||||
let view = Mat4::view(eye, yaw, -0.5);
|
||||
/// Fenster-Pixel (physisch) → interne Pixel, über dieselbe Letterbox wie
|
||||
/// der Blit. Außerhalb des Bildbereichs auf die Ränder geklemmt.
|
||||
pub fn map_cursor(&self, win: [f32; 2]) -> [f32; 2] {
|
||||
let (vx, vy, vw, vh) = letterbox(self.config.width, self.config.height);
|
||||
let ix = (win[0] - vx) / vw * INTERNAL_W as f32;
|
||||
let iy = (win[1] - vy) / vh * INTERNAL_H as f32;
|
||||
[ix.clamp(0.0, INTERNAL_W as f32), iy.clamp(0.0, INTERNAL_H as f32)]
|
||||
}
|
||||
|
||||
/// Einen Frame rendern. Die View-Matrix kommt vom Aufrufer (Flycam);
|
||||
/// die Projektion gehört hierher, weil sie an der internen Auflösung
|
||||
/// hängt.
|
||||
pub fn frame(&mut self, view: &Mat4, ui: &Ui) {
|
||||
let proj = Mat4::perspective(
|
||||
60f32.to_radians(),
|
||||
INTERNAL_W as f32 / INTERNAL_H as f32,
|
||||
0.1, 100.0,
|
||||
);
|
||||
self.scene.prepare(&self.queue, &proj.mul(&view));
|
||||
let half_res = [INTERNAL_W as f32 * 0.5, INTERNAL_H as f32 * 0.5];
|
||||
self.scene.prepare(&self.queue, &proj.mul(view), half_res);
|
||||
self.sprite.prepare(&self.queue, &ui.verts);
|
||||
|
||||
use wgpu::CurrentSurfaceTexture as Cst;
|
||||
let frame = match self.surface.get_current_texture() {
|
||||
@@ -206,6 +230,8 @@ impl Gpu {
|
||||
multiview_mask: None,
|
||||
});
|
||||
self.scene.draw(&mut pass);
|
||||
// Overlay obenauf, im selben Pass (kein Tiefentest).
|
||||
self.sprite.draw(&mut pass, &ui.batches);
|
||||
}
|
||||
|
||||
// Pass 2: Letterbox-Blit aufs Fenster.
|
||||
|
||||
Reference in New Issue
Block a user