mirror of https://github.com/AxioDL/metaforce.git
Splash screen rendering
This commit is contained in:
parent
8d01afc632
commit
509252a17f
|
@ -72,9 +72,9 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
|||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.34.0+1.2.203"
|
||||
version = "0.35.1+1.2.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df"
|
||||
checksum = "b7fd04def1c9101b5fb488c131022d2d6f87753ef4b1b11b279e2af404fae6b9"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
@ -96,7 +96,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"android_logger",
|
||||
"bindgen",
|
||||
"binread",
|
||||
"binrw",
|
||||
"bytemuck",
|
||||
"bytemuck_derive",
|
||||
"cgmath",
|
||||
|
@ -109,9 +109,8 @@ dependencies = [
|
|||
"imgui-winit-support",
|
||||
"log",
|
||||
"log-panics",
|
||||
"mobile-entry-point",
|
||||
"modular-bitfield",
|
||||
"naga",
|
||||
"naga 0.8.0 (git+https://github.com/gfx-rs/naga?rev=d6f8958b346676396db97053771b8d95684c47ee)",
|
||||
"ndk-glue",
|
||||
"num-traits",
|
||||
"num_enum",
|
||||
|
@ -120,7 +119,6 @@ dependencies = [
|
|||
"smallvec",
|
||||
"twox-hash",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"wgpu",
|
||||
"wgpu-subscriber",
|
||||
"winit",
|
||||
|
@ -156,23 +154,22 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "binread"
|
||||
version = "2.2.0"
|
||||
name = "binrw"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f"
|
||||
checksum = "a13d2fa8772b88ee64a0d84602c636ad2bae9c176873f6c440e2b0a1df4c8c43"
|
||||
dependencies = [
|
||||
"array-init",
|
||||
"binread_derive",
|
||||
"rustversion",
|
||||
"binrw_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binread_derive"
|
||||
version = "2.1.0"
|
||||
name = "binrw_derive"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed"
|
||||
checksum = "193bcff2709da50edf2e9a89e0f9a2118eea70f257b1f4380ccf27d3d8578302"
|
||||
dependencies = [
|
||||
"either",
|
||||
"owo-colors",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -488,9 +485,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
|||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.60"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af5f0799eb4abbd9c46cb58dfaa781386f852386ad6681e65c66a8101b8562af"
|
||||
checksum = "fcd554072878dec8c16f59839336bf712d6d1f0d8d27cf9b471c10a484a3290f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
|
@ -500,13 +497,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.60"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8f82eb643890f29750b559497cd5dc8c82019e5c6ff0284a1d14e85e8c44c7"
|
||||
checksum = "bae954f28208a9c31eb37623d435bdfcdd28fe93ffb5a34dfe6af9a2f1a1ca66"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
|
@ -515,15 +512,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.60"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "394474c4844c6df346936204bda4a45e4cf524d0b7050eb70e4b81fc568ab125"
|
||||
checksum = "1cc629121d3f01cd7c85ba046b3bcef66d182429b495eeb1080396ba4bfb8ae4"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.60"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05055753924c7b4ae9b038eb7823d4d9c64a045a727cb581764a4454a60d0805"
|
||||
checksum = "93a8fa39ee5a91d04a99fc09fc3f1dd780ebfe31817721abcaecd823e00c9f3b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -576,17 +573,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -860,6 +846,7 @@ checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"libloading",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -971,8 +958,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084"
|
||||
source = "git+https://github.com/gfx-rs/metal-rs?rev=140c8f4#140c8f4e39001ae154f153ffc767da6c0c9d7f06"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
|
@ -1010,17 +996,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mobile-entry-point"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81bef5a90018326583471cccca10424d7b3e770397b02f03276543cbb9b6a1a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield"
|
||||
version = "0.11.2"
|
||||
|
@ -1045,7 +1020,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=8df5421#8df5421e2e9d33e092c19779adfdc42e7f8a74e6"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=81dc674#81dc67402a743b4dc6b2d24c0d306cd18799238b"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
|
@ -1060,6 +1035,23 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=d6f8958b346676396db97053771b8d95684c47ee#d6f8958b346676396db97053771b8d95684c47ee"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
"codespan-reporting",
|
||||
"hexf-parse",
|
||||
"indexmap",
|
||||
"log",
|
||||
"num-traits",
|
||||
"rustc-hash",
|
||||
"spirv",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.5.0"
|
||||
|
@ -1160,19 +1152,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.5"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "085fe377a4b2805c0fbc09484415ec261174614b7f080b0e0d520456ac421a67"
|
||||
checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.5"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5249369707a1e07b39f78d98c8f34e00aca7dcb053812fdbb5ad7be82c1bba38"
|
||||
checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
|
@ -1205,6 +1196,12 @@ version = "1.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
|
@ -1272,9 +1269,9 @@ checksum = "bb20dcc30536a1508e75d47dd0e399bb2fe7354dcf35cda9127f2bf1ed92e30e"
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
|
@ -1418,12 +1415,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
|
@ -1876,12 +1867,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=39b7a8a202c21da43035ec8dd5570a58cf4e8ef1#39b7a8a202c21da43035ec8dd5570a58cf4e8ef1"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=766c6cda1917c1265fa8a5f610ef7516d4314d1b#766c6cda1917c1265fa8a5f610ef7516d4314d1b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"js-sys",
|
||||
"log",
|
||||
"naga",
|
||||
"naga 0.8.0 (git+https://github.com/gfx-rs/naga?rev=81dc674)",
|
||||
"parking_lot",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
|
@ -1896,7 +1887,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=39b7a8a202c21da43035ec8dd5570a58cf4e8ef1#39b7a8a202c21da43035ec8dd5570a58cf4e8ef1"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=766c6cda1917c1265fa8a5f610ef7516d4314d1b#766c6cda1917c1265fa8a5f610ef7516d4314d1b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
|
@ -1905,7 +1896,7 @@ dependencies = [
|
|||
"copyless",
|
||||
"fxhash",
|
||||
"log",
|
||||
"naga",
|
||||
"naga 0.8.0 (git+https://github.com/gfx-rs/naga?rev=81dc674)",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
|
@ -1918,7 +1909,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=39b7a8a202c21da43035ec8dd5570a58cf4e8ef1#39b7a8a202c21da43035ec8dd5570a58cf4e8ef1"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=766c6cda1917c1265fa8a5f610ef7516d4314d1b#766c6cda1917c1265fa8a5f610ef7516d4314d1b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ash",
|
||||
|
@ -1938,7 +1929,7 @@ dependencies = [
|
|||
"libloading",
|
||||
"log",
|
||||
"metal",
|
||||
"naga",
|
||||
"naga 0.8.0 (git+https://github.com/gfx-rs/naga?rev=81dc674)",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
|
@ -1968,7 +1959,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=39b7a8a202c21da43035ec8dd5570a58cf4e8ef1#39b7a8a202c21da43035ec8dd5570a58cf4e8ef1"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=766c6cda1917c1265fa8a5f610ef7516d4314d1b#766c6cda1917c1265fa8a5f610ef7516d4314d1b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -2017,12 +2008,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
version = "0.26.0"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70466a5f4825cc88c92963591b06dbc255420bffe19d847bfcda475e82d079c0"
|
||||
checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa",
|
||||
"core-foundation 0.9.2",
|
||||
"core-graphics 0.22.3",
|
||||
|
|
|
@ -13,15 +13,13 @@ crate-type = ["staticlib"]
|
|||
#path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
cxx = "1.0.60"
|
||||
web-sys = "0.3.55"
|
||||
cxx = "1.0.64"
|
||||
env_logger = "0.9.0"
|
||||
mobile-entry-point = "0.1.1"
|
||||
pollster = "0.2.4"
|
||||
binread = { version = "2.2.0", features = ['const_generics'] }
|
||||
binrw = "0.8.4"
|
||||
modular-bitfield = "0.11.2"
|
||||
num-traits = "0.2.14"
|
||||
num_enum = "0.5.5"
|
||||
num_enum = "0.5.6"
|
||||
bytemuck = "1.7.3"
|
||||
bytemuck_derive = "1.0.1"
|
||||
log = "0.4.14"
|
||||
|
@ -30,7 +28,7 @@ cgmath = "0.18.0"
|
|||
smallvec = "1.7.0"
|
||||
scopeguard = "1.1.0"
|
||||
twox-hash = "1.6.2"
|
||||
winit = "0.26.0"
|
||||
winit = "0.26.1"
|
||||
|
||||
[dependencies.imgui]
|
||||
git = "https://github.com/imgui-rs/imgui-rs"
|
||||
|
@ -44,11 +42,12 @@ features = ["winit-26"]
|
|||
imgui-sys = { path = "../imgui-sys" }
|
||||
[patch.crates-io]
|
||||
imgui-sys = { path = "../imgui-sys" }
|
||||
naga = { git = "https://github.com/gfx-rs/naga", rev = "d6f8958b346676396db97053771b8d95684c47ee" }
|
||||
|
||||
[dependencies.wgpu]
|
||||
#path = "../../wgpu/wgpu"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "39b7a8a202c21da43035ec8dd5570a58cf4e8ef1"
|
||||
rev = "766c6cda1917c1265fa8a5f610ef7516d4314d1b"
|
||||
features = ["spirv"]
|
||||
|
||||
#[patch.'https://github.com/gfx-rs/naga']
|
||||
|
@ -56,9 +55,9 @@ features = ["spirv"]
|
|||
|
||||
[build-dependencies]
|
||||
#naga = { path = "../../naga", features = ['spv-out', 'wgsl-in'] }
|
||||
naga = { git = "https://github.com/gfx-rs/naga", rev = "8df5421", features = ['spv-out', 'wgsl-in'] }
|
||||
naga = { git = "https://github.com/gfx-rs/naga", rev = "d6f8958b346676396db97053771b8d95684c47ee", features = ['spv-out', 'wgsl-in'] }
|
||||
bytemuck = "1.7.3"
|
||||
cxx-build = "1.0.60"
|
||||
cxx-build = "1.0.64"
|
||||
bindgen = "0.59.2"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
|
|
|
@ -59,6 +59,7 @@ pub(crate) fn initialize_imgui(window: &winit::window::Window, gpu: &DeviceHolde
|
|||
state
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn ImGuiEngine_AddTexture(
|
||||
state: &mut ImGuiState,
|
||||
gpu: &DeviceHolder,
|
||||
|
|
|
@ -3,21 +3,21 @@ struct Uniforms {
|
|||
};
|
||||
|
||||
struct VertexInput {
|
||||
[[location(0)]] a_Pos: vec2<f32>;
|
||||
[[location(1)]] a_UV: vec2<f32>;
|
||||
[[location(2)]] a_Color: vec4<f32>;
|
||||
@location(0) a_Pos: vec2<f32>;
|
||||
@location(1) a_UV: vec2<f32>;
|
||||
@location(2) a_Color: vec4<f32>;
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
[[location(0)]] v_UV: vec2<f32>;
|
||||
[[location(1)]] v_Color: vec4<f32>;
|
||||
[[builtin(position)]] v_Position: vec4<f32>;
|
||||
@location(0) v_UV: vec2<f32>;
|
||||
@location(1) v_Color: vec4<f32>;
|
||||
@builtin(position) v_Position: vec4<f32>;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]]
|
||||
@group(0) @binding(0)
|
||||
var<uniform> uniforms: Uniforms;
|
||||
|
||||
[[stage(vertex)]]
|
||||
@stage(vertex)
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.v_UV = in.a_UV;
|
||||
|
@ -26,9 +26,9 @@ fn vs_main(in: VertexInput) -> VertexOutput {
|
|||
return out;
|
||||
}
|
||||
|
||||
[[group(1), binding(0)]]
|
||||
@group(1) @binding(0)
|
||||
var u_Texture: texture_2d<f32>;
|
||||
[[group(1), binding(1)]]
|
||||
@group(1) @binding(1)
|
||||
var u_Sampler: sampler;
|
||||
|
||||
fn srgb_to_linear(srgb: vec4<f32>) -> vec4<f32> {
|
||||
|
@ -40,14 +40,14 @@ fn srgb_to_linear(srgb: vec4<f32>) -> vec4<f32> {
|
|||
return vec4<f32>(result, srgb.a);
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fs_main_linear(in: VertexOutput) -> [[location(0)]] vec4<f32> {
|
||||
@stage(fragment)
|
||||
fn fs_main_linear(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let color = srgb_to_linear(in.v_Color);
|
||||
return color * textureSample(u_Texture, u_Sampler, in.v_UV);
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fs_main_srgb(in: VertexOutput) -> [[location(0)]] vec4<f32> {
|
||||
@stage(fragment)
|
||||
fn fs_main_srgb(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let color = in.v_Color;
|
||||
return color * textureSample(u_Texture, u_Sampler, in.v_UV);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ mod imgui;
|
|||
mod imgui_backend;
|
||||
mod shaders;
|
||||
mod zeus;
|
||||
mod util;
|
||||
|
||||
#[cxx::bridge(namespace = "aurora")]
|
||||
mod ffi {
|
||||
|
@ -143,6 +144,8 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
APP.replace(app);
|
||||
ffi::App_onAppLaunched(delegate.as_mut().unwrap());
|
||||
};
|
||||
|
||||
let mut last_frame: Option<Instant> = None;
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
// Have the closure take ownership of the resources.
|
||||
// `event_loop.run` never returns, therefore we must do this to ensure
|
||||
|
@ -153,7 +156,6 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
let imgui = &mut app.imgui;
|
||||
let window_ctx = get_window_context();
|
||||
let gpu = &mut app.gpu;
|
||||
let mut last_frame: Option<Instant> = None;
|
||||
|
||||
*control_flow = ControlFlow::Poll;
|
||||
match event {
|
||||
|
@ -183,7 +185,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
Event::Suspended => {}
|
||||
Event::Resumed => {}
|
||||
Event::MainEventsCleared => {
|
||||
log::info!("Requesting redraw");
|
||||
log::trace!("Requesting redraw");
|
||||
window_ctx.window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
|
@ -208,7 +210,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
return;
|
||||
}
|
||||
|
||||
log::info!("Redrawing");
|
||||
log::trace!("Redrawing");
|
||||
let frame_result = gpu.surface.get_current_texture();
|
||||
if let Err(err) = frame_result {
|
||||
log::warn!("Failed to acquire frame {}", err);
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
struct Uniform {
|
||||
xf: mat4x4<f32>;
|
||||
color: vec4<f32>;
|
||||
};
|
||||
[[group(0), binding(0)]]
|
||||
var<uniform> ubuf: Uniform;
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vs_main([[location(0)]] in_pos: vec3<f32>) -> [[builtin(position)]] vec4<f32> {
|
||||
return ubuf.xf * vec4<f32>(in_pos, 1.0);
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fs_main() -> [[location(0)]] vec4<f32> {
|
||||
return ubuf.color;
|
||||
}
|
|
@ -24,8 +24,10 @@ pub(crate) struct DrawData {
|
|||
pub(crate) struct PipelineConfig {
|
||||
z_only: bool,
|
||||
}
|
||||
pub(crate) const INITIAL_PIPELINES: &[PipelineConfig] =
|
||||
&[PipelineConfig { z_only: false }, PipelineConfig { z_only: true }];
|
||||
pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[
|
||||
PipelineCreateCommand::Aabb(PipelineConfig { z_only: false }),
|
||||
PipelineCreateCommand::Aabb(PipelineConfig { z_only: true }),
|
||||
];
|
||||
|
||||
pub(crate) struct State {
|
||||
shader: wgpu::ShaderModule,
|
||||
|
@ -39,7 +41,7 @@ pub(crate) fn construct_state(
|
|||
_queue: &wgpu::Queue,
|
||||
buffers: &BuiltBuffers,
|
||||
) -> State {
|
||||
let shader = device.create_shader_module(&include_wgsl!("aabb.wgsl"));
|
||||
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
|
||||
let uniform_size = wgpu::BufferSize::new(std::mem::size_of::<Uniform>() as u64);
|
||||
let uniform_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("AABB Bind Group Layout"),
|
||||
|
@ -145,7 +147,7 @@ struct Uniform {
|
|||
}
|
||||
|
||||
pub(crate) fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool) {
|
||||
let pipeline = pipeline_ref(PipelineCreateCommand::Aabb(PipelineConfig { z_only }));
|
||||
let pipeline = pipeline_ref(&PipelineCreateCommand::Aabb(PipelineConfig { z_only }));
|
||||
let vert_range = push_verts(&[
|
||||
CVector3f::new(aabb.max.x, aabb.max.y, aabb.min.z),
|
||||
CVector3f::new(aabb.max.x, aabb.min.y, aabb.min.z),
|
|
@ -0,0 +1,16 @@
|
|||
struct Uniform {
|
||||
xf: mat4x4<f32>;
|
||||
color: vec4<f32>;
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;
|
||||
|
||||
@stage(vertex)
|
||||
fn vs_main(@location(0) in_pos: vec3<f32>) -> @builtin(position) vec4<f32> {
|
||||
return ubuf.xf * vec4<f32>(in_pos, 1.0);
|
||||
}
|
||||
|
||||
@stage(fragment)
|
||||
fn fs_main() -> @location(0) vec4<f32> {
|
||||
return ubuf.color;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
hash::{Hash, Hasher},
|
||||
num::NonZeroU8,
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
|
@ -10,10 +9,12 @@ use aabb::queue_aabb;
|
|||
use bytemuck::Pod;
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use cxx::{type_id, ExternType};
|
||||
use cxx::private::hash;
|
||||
use fog_volume_filter::queue_fog_volume_filter;
|
||||
use fog_volume_plane::queue_fog_volume_plane;
|
||||
use model::{add_material_set, add_model};
|
||||
use texture::{create_render_texture, create_static_texture_2d, drop_texture};
|
||||
use textured_quad::queue_textured_quad;
|
||||
use twox_hash::Xxh3Hash64;
|
||||
use wgpu::RenderPipeline;
|
||||
|
||||
|
@ -21,11 +22,14 @@ use crate::{
|
|||
gpu::GraphicsConfig,
|
||||
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, IDENTITY_MATRIX4F},
|
||||
};
|
||||
use crate::shaders::ffi::{TextureFormat, TextureRef};
|
||||
use crate::shaders::texture::{RenderTexture, TextureWithView};
|
||||
|
||||
mod aabb;
|
||||
mod fog_volume_filter;
|
||||
mod fog_volume_plane;
|
||||
mod model;
|
||||
mod textured_quad;
|
||||
mod texture;
|
||||
|
||||
#[cxx::bridge]
|
||||
|
@ -55,7 +59,7 @@ mod ffi {
|
|||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum CameraFilterType {
|
||||
Passthru,
|
||||
Multiply,
|
||||
|
@ -69,7 +73,7 @@ mod ffi {
|
|||
InvDstMultiply,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum ZTest {
|
||||
None,
|
||||
LEqual,
|
||||
|
@ -96,9 +100,10 @@ mod ffi {
|
|||
ClampToBlack,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) struct TextureRef {
|
||||
pub(crate) id: u32,
|
||||
pub(crate) render: bool,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
|
@ -180,6 +185,15 @@ mod ffi {
|
|||
fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool);
|
||||
fn queue_fog_volume_plane(verts: &CxxVector<CVector4f>, pass: u8);
|
||||
fn queue_fog_volume_filter(color: CColor, two_way: bool);
|
||||
fn queue_textured_quad(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_test: ZTest,
|
||||
color: CColor,
|
||||
uv_scale: f32,
|
||||
rect: CRectangle,
|
||||
z: f32,
|
||||
);
|
||||
|
||||
fn create_static_texture_2d(
|
||||
width: u32,
|
||||
|
@ -210,6 +224,21 @@ impl Default for ffi::FogState {
|
|||
Self { color: Default::default(), a: 0.0, b: 0.5, c: 0.0, mode: ffi::FogMode::None }
|
||||
}
|
||||
}
|
||||
impl Into<u32> for ffi::TextureFormat {
|
||||
// noinspection RsUnreachablePatterns
|
||||
fn into(self) -> u32 {
|
||||
match self {
|
||||
TextureFormat::RGBA8 => 1,
|
||||
TextureFormat::R8 => 2,
|
||||
TextureFormat::R32Float => 3,
|
||||
TextureFormat::DXT1 => 4,
|
||||
TextureFormat::DXT3 => 5,
|
||||
TextureFormat::DXT5 => 6,
|
||||
TextureFormat::BPTC => 7,
|
||||
_ => panic!("Invalid texture format {:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum ColoredStripMode {
|
||||
|
@ -280,12 +309,7 @@ enum ShaderDrawCommand {
|
|||
RandomStaticFilter {/* TODO */},
|
||||
ScanLinesFilter {/* TODO */},
|
||||
TextSupport {/* TODO */},
|
||||
TexturedQuad {
|
||||
filter_type: ffi::CameraFilterType,
|
||||
z_test: ffi::ZTest,
|
||||
tex: u32, /* TODO */
|
||||
/* draw, cropped, verts, filter? */
|
||||
},
|
||||
TexturedQuad(textured_quad::DrawData),
|
||||
ThermalCold,
|
||||
ThermalHot,
|
||||
WorldShadow {
|
||||
|
@ -309,8 +333,11 @@ struct RenderState {
|
|||
storage_alignment: usize,
|
||||
buffers: BuiltBuffers,
|
||||
commands: VecDeque<Command>,
|
||||
textures: HashMap<u32, TextureWithView>,
|
||||
render_textures: HashMap<u32, RenderTexture>,
|
||||
// Shader states
|
||||
aabb: aabb::State,
|
||||
textured_quad: textured_quad::State,
|
||||
}
|
||||
pub(crate) fn construct_state(
|
||||
device: Arc<wgpu::Device>,
|
||||
|
@ -318,7 +345,7 @@ pub(crate) fn construct_state(
|
|||
graphics_config: &GraphicsConfig,
|
||||
) {
|
||||
let limits = device.limits();
|
||||
let mut buffers = BuiltBuffers {
|
||||
let buffers = BuiltBuffers {
|
||||
uniform_buffer: device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Shared Uniform Buffer"),
|
||||
size: 134_217_728, // 128mb
|
||||
|
@ -333,6 +360,7 @@ pub(crate) fn construct_state(
|
|||
}),
|
||||
};
|
||||
let aabb = aabb::construct_state(&device, &queue, &buffers);
|
||||
let textured_quad = textured_quad::construct_state(&device, &queue, &buffers, graphics_config);
|
||||
let mut state = RenderState {
|
||||
device: device.clone(),
|
||||
queue: queue.clone(),
|
||||
|
@ -343,12 +371,16 @@ pub(crate) fn construct_state(
|
|||
storage_alignment: limits.min_storage_buffer_offset_alignment as usize,
|
||||
buffers,
|
||||
commands: Default::default(),
|
||||
textures: Default::default(),
|
||||
render_textures: Default::default(),
|
||||
aabb,
|
||||
textured_quad,
|
||||
};
|
||||
for config in aabb::INITIAL_PIPELINES {
|
||||
let hash = hash_with_seed(config, 0xAABB);
|
||||
let pipeline = aabb::construct_pipeline(&device, graphics_config, &state.aabb, config);
|
||||
state.pipelines.insert(hash, pipeline);
|
||||
construct_pipeline(&mut state, config);
|
||||
}
|
||||
for config in textured_quad::INITIAL_PIPELINES {
|
||||
construct_pipeline(&mut state, config);
|
||||
}
|
||||
unsafe {
|
||||
STATE = Some(state);
|
||||
|
@ -442,8 +474,9 @@ struct PipelineRef {
|
|||
id: u64,
|
||||
}
|
||||
|
||||
enum PipelineCreateCommand {
|
||||
pub(crate) enum PipelineCreateCommand {
|
||||
Aabb(aabb::PipelineConfig),
|
||||
TexturedQuad(textured_quad::PipelineConfig),
|
||||
}
|
||||
#[inline(always)]
|
||||
fn hash_with_seed<T: Hash>(value: &T, seed: u64) -> u64 {
|
||||
|
@ -451,12 +484,11 @@ fn hash_with_seed<T: Hash>(value: &T, seed: u64) -> u64 {
|
|||
value.hash(&mut state);
|
||||
state.finish()
|
||||
}
|
||||
fn pipeline_ref(cmd: PipelineCreateCommand) -> PipelineRef {
|
||||
let state = unsafe { STATE.as_mut().unwrap() };
|
||||
fn construct_pipeline(state: &mut RenderState, cmd: &PipelineCreateCommand) -> u64 {
|
||||
let id = match cmd {
|
||||
PipelineCreateCommand::Aabb(ref config) => hash_with_seed(config, 0xAABB),
|
||||
PipelineCreateCommand::TexturedQuad(ref config) => hash_with_seed(config, 0xEEAD),
|
||||
};
|
||||
// TODO queue for creation if not found
|
||||
if !state.pipelines.contains_key(&id) {
|
||||
let pipeline = match cmd {
|
||||
PipelineCreateCommand::Aabb(ref config) => aabb::construct_pipeline(
|
||||
|
@ -465,14 +497,26 @@ fn pipeline_ref(cmd: PipelineCreateCommand) -> PipelineRef {
|
|||
&state.aabb,
|
||||
config,
|
||||
),
|
||||
PipelineCreateCommand::TexturedQuad(ref config) => textured_quad::construct_pipeline(
|
||||
state.device.as_ref(),
|
||||
&state.graphics_config,
|
||||
&state.textured_quad,
|
||||
config,
|
||||
),
|
||||
};
|
||||
state.pipelines.insert(id, pipeline);
|
||||
}
|
||||
id
|
||||
}
|
||||
fn pipeline_ref(cmd: &PipelineCreateCommand) -> PipelineRef {
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
// TODO queue for creation if not found
|
||||
let id = construct_pipeline(state, cmd);
|
||||
PipelineRef { id }
|
||||
}
|
||||
|
||||
fn bind_pipeline(pipeline_ref: PipelineRef, pass: &mut wgpu::RenderPass) -> bool {
|
||||
let state = unsafe { STATE.as_ref().unwrap() };
|
||||
let state = unsafe { STATE.as_ref().unwrap_unchecked() };
|
||||
if pipeline_ref.id == state.current_pipeline {
|
||||
return true;
|
||||
}
|
||||
|
@ -484,7 +528,7 @@ fn bind_pipeline(pipeline_ref: PipelineRef, pass: &mut wgpu::RenderPass) -> bool
|
|||
}
|
||||
|
||||
pub(crate) fn render_into_pass(pass: &mut wgpu::RenderPass) {
|
||||
let state = unsafe { STATE.as_mut().unwrap() };
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
{
|
||||
let global_buffers = unsafe { &mut GLOBAL_BUFFERS };
|
||||
state.queue.write_buffer(&state.buffers.vertex_buffer, 0, &global_buffers.verts);
|
||||
|
@ -512,6 +556,9 @@ pub(crate) fn render_into_pass(pass: &mut wgpu::RenderPass) {
|
|||
ShaderDrawCommand::Aabb(data) => {
|
||||
aabb::draw_aabb(data, &state.aabb, pass, &state.buffers);
|
||||
}
|
||||
ShaderDrawCommand::TexturedQuad(data) => {
|
||||
textured_quad::draw_textured_quad(data, &state.textured_quad, pass, &state.buffers);
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
}
|
||||
|
@ -554,15 +601,15 @@ fn finalize_global_uniform() -> Range<u64> {
|
|||
}
|
||||
|
||||
fn push_draw_command(cmd: ShaderDrawCommand) {
|
||||
let state = unsafe { STATE.as_mut().unwrap() };
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
state.commands.push_back(Command::Draw(cmd));
|
||||
}
|
||||
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32) {
|
||||
let state = unsafe { STATE.as_mut().unwrap() };
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
state.commands.push_back(Command::SetViewport(rect, znear, zfar));
|
||||
}
|
||||
fn set_scissor(x: u32, y: u32, w: u32, h: u32) {
|
||||
let state = unsafe { STATE.as_mut().unwrap() };
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
state.commands.push_back(Command::SetScissor(x, y, w, h));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
struct PassTrait {
|
||||
constant_color: vec4<f32>;
|
||||
tex_idx: i32;
|
||||
uv_source: i32;
|
||||
tcg_mtx_idx: i32;
|
||||
normalize: u32;
|
||||
sample_alpha: u32;
|
||||
has_constant_color: u32;
|
||||
};
|
||||
struct TCGUniform {
|
||||
mode: i32;
|
||||
f0: f32;
|
||||
f1: f32;
|
||||
f2: f32;
|
||||
f3: f32;
|
||||
f4: f32;
|
||||
f5: f32;
|
||||
f6: f32;
|
||||
f7: f32;
|
||||
f8: f32;
|
||||
pad1: u32;
|
||||
pad2: u32;
|
||||
};
|
||||
struct ConstShaderTraits {
|
||||
shader_type: u32;
|
||||
world_shadow: u32;
|
||||
short_uvs: u32;
|
||||
alpha_discard: u32;
|
||||
samus_reflection: u32;
|
||||
@align(16) tcgs: @stride(48) array<TCGUniform, 4>;
|
||||
};
|
||||
struct MutShaderTraits {
|
||||
post_type: u32;
|
||||
game_blend_mode: u32;
|
||||
model_flags: u32;
|
||||
};
|
||||
struct ConstTraits {
|
||||
shader: ConstShaderTraits;
|
||||
lightmap: PassTrait;
|
||||
diffuse: PassTrait;
|
||||
diffuse_mod: PassTrait;
|
||||
emissive: PassTrait;
|
||||
specular: PassTrait;
|
||||
extended_specular: PassTrait;
|
||||
reflection: PassTrait;
|
||||
alpha: PassTrait;
|
||||
alpha_mod: PassTrait;
|
||||
};
|
||||
@group(2) @binding(10)
|
||||
var<uniform> c_traits: ConstTraits;
|
||||
|
||||
struct Light {
|
||||
pos: vec3<f32>;
|
||||
dir: vec3<f32>;
|
||||
color: vec4<f32>;
|
||||
lin_att: vec3<f32>;
|
||||
ang_att: vec3<f32>;
|
||||
};
|
||||
struct FogState {
|
||||
color: vec4<f32>;
|
||||
a: f32;
|
||||
b: f32;
|
||||
c: f32;
|
||||
mode: u32;
|
||||
};
|
||||
struct ModelUniform {
|
||||
position: vec3<f32>;
|
||||
orientation: vec3<f32>;
|
||||
scale: vec3<f32>;
|
||||
ambient_color: vec4<f32>;
|
||||
lights: array<Light, 8>;
|
||||
};
|
||||
struct GlobalUniform {
|
||||
view: mat4x4<f32>;
|
||||
proj: mat4x4<f32>;
|
||||
ambient: vec4<f32>;
|
||||
lightmap_mul: vec4<f32>;
|
||||
fog: FogState;
|
||||
seconds: f32;
|
||||
};
|
||||
@group(1) @binding(0)
|
||||
var<uniform> u_model: ModelUniform;
|
||||
@group(1) @binding(1)
|
||||
var<uniform> u_global: GlobalUniform;
|
||||
@group(1) @binding(2)
|
||||
var<uniform> u_traits: MutShaderTraits;
|
||||
|
||||
@group(2) @binding(0)
|
||||
var t_lightmap: texture_2d<f32>;
|
||||
@group(2) @binding(1)
|
||||
var t_diffuse: texture_2d<f32>;
|
||||
@group(2) @binding(2)
|
||||
var t_diffuse_mod: texture_2d<f32>;
|
||||
@group(2) @binding(3)
|
||||
var t_emissive: texture_2d<f32>;
|
||||
@group(2) @binding(4)
|
||||
var t_specular: texture_2d<f32>;
|
||||
@group(2) @binding(5)
|
||||
var t_extended_specular: texture_2d<f32>;
|
||||
@group(2) @binding(6)
|
||||
var t_reflection: texture_2d<f32>;
|
||||
@group(2) @binding(7)
|
||||
var t_alpha: texture_2d<f32>;
|
||||
@group(2) @binding(8)
|
||||
var t_alpha_mod: texture_2d<f32>;
|
||||
@group(2) @binding(9)
|
||||
var t_material: texture_2d<f32>;
|
||||
|
||||
@group(3) @binding(0)
|
||||
var s_repeat: sampler;
|
||||
@group(3) @binding(1)
|
||||
var s_clamp: sampler;
|
||||
@group(3) @binding(2)
|
||||
var s_reflect: sampler;
|
||||
@group(3) @binding(3)
|
||||
var s_clamp_edge: sampler;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4<f32>;
|
||||
@location(0) lighting: vec3<f32>;
|
||||
@location(1) uv_lightmap: vec2<f32>;
|
||||
@location(2) uv_diffuse: vec2<f32>;
|
||||
@location(3) uv_diffuse_mod: vec2<f32>;
|
||||
@location(4) uv_emissive: vec2<f32>;
|
||||
@location(5) uv_specular: vec2<f32>;
|
||||
@location(6) uv_extended_specular: vec2<f32>;
|
||||
@location(7) uv_reflection: vec2<f32>;
|
||||
@location(8) uv_alpha: vec2<f32>;
|
||||
@location(9) uv_alpha_mod: vec2<f32>;
|
||||
};
|
||||
|
||||
fn make_rotate_x(r: f32) -> mat4x4<f32> {
|
||||
var s = sin(r);
|
||||
var c = cos(r);
|
||||
return mat4x4<f32>(
|
||||
vec4<f32>(1.0, 0.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, c, s, 0.0),
|
||||
vec4<f32>(0.0, -s, c, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
fn make_rotate_y(r: f32) -> mat4x4<f32> {
|
||||
var s = sin(r);
|
||||
var c = cos(r);
|
||||
return mat4x4<f32>(
|
||||
vec4<f32>(c, 0.0, -s, 0.0),
|
||||
vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
||||
vec4<f32>(s, 0.0, c, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
fn make_rotate_z(r: f32) -> mat4x4<f32> {
|
||||
var s = sin(r);
|
||||
var c = cos(r);
|
||||
return mat4x4<f32>(
|
||||
vec4<f32>(c, s, 0.0, 0.0),
|
||||
vec4<f32>(-s, c, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
fn make_rotate(r: vec3<f32>) -> mat4x4<f32> {
|
||||
return make_rotate_z(r.z)
|
||||
* make_rotate_y(r.y)
|
||||
* make_rotate_x(r.x);
|
||||
}
|
||||
|
||||
fn make_scale(s: vec3<f32>) -> mat4x4<f32> {
|
||||
return mat4x4<f32>(
|
||||
vec4<f32>(s.x, 0.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, s.y, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, s.z, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
fn make_translate(translate: vec3<f32>) -> mat4x4<f32> {
|
||||
return mat4x4<f32>(
|
||||
vec4<f32>(1.0, 0.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||
vec4<f32>(translate, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
struct TCGMatrix {
|
||||
mtx: mat4x4<f32>;
|
||||
post_mtx: mat4x4<f32>;
|
||||
};
|
||||
|
||||
let identity_mtx: mat4x4<f32> = mat4x4<f32>(
|
||||
vec4<f32>(1.0, 0.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
fn process_uv_anim(
|
||||
model_matrix: ptr<function, mat4x4<f32>>,
|
||||
mv_inv: ptr<function, mat4x4<f32>>,
|
||||
traits: PassTrait,
|
||||
) -> TCGMatrix {
|
||||
var out = TCGMatrix(identity_mtx, identity_mtx);
|
||||
var tu = c_traits.shader.tcgs[traits.tcg_mtx_idx];
|
||||
switch (tu.mode) {
|
||||
case 0: {
|
||||
out.mtx = *mv_inv;
|
||||
out.mtx[3][3] = 1.0;
|
||||
out.post_mtx[0][0] = 0.5;
|
||||
out.post_mtx[1][1] = 0.5;
|
||||
out.post_mtx[3][0] = 0.5;
|
||||
out.post_mtx[3][1] = 0.5;
|
||||
}
|
||||
case 1: {
|
||||
out.mtx = *mv_inv;
|
||||
out.mtx[3] = u_global.view * vec4<f32>(u_model.position, 1.0);
|
||||
out.mtx[3][3] = 1.0;
|
||||
out.post_mtx[0][0] = 0.5;
|
||||
out.post_mtx[1][1] = 0.5;
|
||||
out.post_mtx[3][0] = 0.5;
|
||||
out.post_mtx[3][1] = 0.5;
|
||||
}
|
||||
case 2: {
|
||||
out.mtx[3][0] = u_global.seconds * tu.f2 + tu.f0;
|
||||
out.mtx[3][1] = u_global.seconds * tu.f3 + tu.f1;
|
||||
}
|
||||
case 3: {
|
||||
var angle = u_global.seconds * tu.f1 + tu.f0;
|
||||
var acos = cos(angle);
|
||||
var asin = sin(angle);
|
||||
out.mtx[0][0] = acos;
|
||||
out.mtx[0][1] = asin;
|
||||
out.mtx[1][0] = -asin;
|
||||
out.mtx[1][1] = acos;
|
||||
out.mtx[3][0] = (1.0 - (acos - asin)) * 0.5;
|
||||
out.mtx[3][1] = (1.0 - (asin + acos)) * 0.5;
|
||||
}
|
||||
case 4: {
|
||||
var n: f32 = tu.f2 * tu.f0 * (tu.f3 + u_global.seconds);
|
||||
out.mtx[3][0] = trunc(tu.f1 * fract(n)) * tu.f2;
|
||||
}
|
||||
case 5: {
|
||||
var n: f32 = tu.f2 * tu.f0 * (tu.f3 + u_global.seconds);
|
||||
out.mtx[3][1] = trunc(tu.f1 * fract(n)) * tu.f2;
|
||||
}
|
||||
case 6: {
|
||||
let pos = u_model.position;
|
||||
out.mtx = *model_matrix;
|
||||
out.mtx[3] = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||
out.post_mtx[0][0] = 0.5;
|
||||
out.post_mtx[1][1] = 0.0;
|
||||
out.post_mtx[2][1] = 0.5;
|
||||
out.post_mtx[3][0] = pos.x * 0.05;
|
||||
out.post_mtx[3][1] = pos.y * 0.05;
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
fn t_sample(
|
||||
traits: PassTrait,
|
||||
tex: texture_2d<f32>,
|
||||
uv: vec2<f32>,
|
||||
) -> vec3<f32> {
|
||||
// For control flow uniformity, we always have to sample
|
||||
var color: vec4<f32> = textureSample(tex, s_repeat, uv);
|
||||
if (traits.has_constant_color == 1u) {
|
||||
color = traits.constant_color;
|
||||
}
|
||||
if (traits.sample_alpha == 1u) {
|
||||
return vec3<f32>(color.w);
|
||||
}
|
||||
return color.xyz;
|
||||
}
|
||||
|
||||
let kRGBToYPrime: vec3<f32> = vec3<f32>(0.299, 0.587, 0.114);
|
||||
|
||||
fn t_sample_alpha(
|
||||
traits: PassTrait,
|
||||
tex: texture_2d<f32>,
|
||||
uv: vec2<f32>,
|
||||
) -> f32 {
|
||||
// For control flow uniformity, we always have to sample
|
||||
var color: vec4<f32> = textureSample(tex, s_repeat, uv);
|
||||
if (traits.has_constant_color == 1u) {
|
||||
color = traits.constant_color;
|
||||
}
|
||||
if (traits.sample_alpha == 1u) {
|
||||
return color.w;
|
||||
}
|
||||
return dot(color.xyz, kRGBToYPrime);
|
||||
}
|
||||
|
||||
@stage(fragment)
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
var color: vec4<f32>;
|
||||
|
||||
let mat_sample = textureSample(t_material, s_repeat, in.uv_diffuse);
|
||||
|
||||
if (c_traits.shader.shader_type == 0u) {
|
||||
// Invalid
|
||||
color = vec4<f32>(
|
||||
t_sample(c_traits.diffuse, t_diffuse, in.uv_diffuse),
|
||||
t_sample_alpha(c_traits.alpha, t_alpha, in.uv_alpha)
|
||||
);
|
||||
} else if (c_traits.shader.shader_type == 1u) {
|
||||
// RetroShader
|
||||
var rgb = t_sample(c_traits.lightmap, t_lightmap, in.uv_lightmap)
|
||||
* u_global.lightmap_mul.xyz + in.lighting;
|
||||
rgb = rgb * t_sample(c_traits.diffuse, t_diffuse, in.uv_diffuse)
|
||||
+ t_sample(c_traits.emissive, t_emissive, in.uv_emissive);
|
||||
let specular = t_sample(c_traits.specular, t_specular, in.uv_specular)
|
||||
+ t_sample(c_traits.extended_specular, t_extended_specular, in.uv_extended_specular)
|
||||
* in.lighting;
|
||||
rgb = rgb + specular * t_sample(c_traits.reflection, t_reflection, in.uv_reflection);
|
||||
// TODO DynReflectionSample
|
||||
color = vec4<f32>(rgb, t_sample_alpha(c_traits.alpha, t_alpha, in.uv_alpha)
|
||||
* t_sample_alpha(c_traits.alpha_mod, t_alpha_mod, in.uv_alpha_mod));
|
||||
} else if (c_traits.shader.shader_type == 2u) {
|
||||
// RetroDynamicShader
|
||||
var rgb = t_sample(c_traits.lightmap, t_lightmap, in.uv_lightmap)
|
||||
* u_global.lightmap_mul.xyz + in.lighting;
|
||||
rgb = rgb * t_sample(c_traits.diffuse, t_diffuse, in.uv_diffuse)
|
||||
+ t_sample(c_traits.emissive, t_emissive, in.uv_emissive);
|
||||
let specular = t_sample(c_traits.specular, t_specular, in.uv_specular)
|
||||
+ t_sample(c_traits.extended_specular, t_extended_specular, in.uv_extended_specular)
|
||||
* in.lighting;
|
||||
rgb = rgb + specular * t_sample(c_traits.reflection, t_reflection, in.uv_reflection);
|
||||
// TODO DynReflectionSample
|
||||
color = vec4<f32>(rgb, t_sample_alpha(c_traits.alpha, t_alpha, in.uv_alpha)
|
||||
* t_sample_alpha(c_traits.alpha_mod, t_alpha_mod, in.uv_alpha_mod));
|
||||
} else {
|
||||
// TODO RetroDynamicAlphaShader + RetroDynamicCharacterShader
|
||||
}
|
||||
|
||||
// TODO fog shader
|
||||
|
||||
// TODO post type
|
||||
|
||||
if (c_traits.shader.alpha_discard == 1u && color.w < 0.25) {
|
||||
discard;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
struct Vec3Block {
|
||||
data: @stride(16) array<vec3<f32>>;
|
||||
};
|
||||
struct Vec2Block {
|
||||
data: @stride(8) array<vec2<f32>>;
|
||||
};
|
||||
struct TCGUniforms {
|
||||
data: array<TCGUniform>;
|
||||
};
|
||||
|
||||
@group(0) @binding(0)
|
||||
var<storage, read> v_verts: Vec3Block;
|
||||
@group(0) @binding(1)
|
||||
var<storage, read> v_norms: Vec3Block;
|
||||
@group(0) @binding(2)
|
||||
var<storage, read> v_uvs: Vec2Block;
|
||||
@group(0) @binding(3)
|
||||
var<storage, read> v_short_uvs: Vec2Block;
|
||||
//@group(0) @binding(4)
|
||||
//var<uniform> v_tcg: TCGUniforms;
|
||||
|
||||
fn calculate_tcg(
|
||||
traits: PassTrait,
|
||||
obj_pos: ptr<function, vec4<f32>>,
|
||||
obj_norm: ptr<function, vec4<f32>>,
|
||||
model_matrix: ptr<function, mat4x4<f32>>,
|
||||
mv_inv: ptr<function, mat4x4<f32>>,
|
||||
uv_0_4_idx: vec4<i32>,
|
||||
uv_4_7_idx: vec4<i32>,
|
||||
) -> vec2<f32> {
|
||||
if (traits.uv_source == -1) {
|
||||
return vec2<f32>(0.0);
|
||||
}
|
||||
if (traits.tcg_mtx_idx >= 0) {
|
||||
var src: vec4<f32>;
|
||||
switch (traits.uv_source) {
|
||||
case 0: { src = vec4<f32>((*obj_pos).xyz, 1.0); }
|
||||
case 1: { src = vec4<f32>((*obj_norm).xyz, 1.0); }
|
||||
case 2: {
|
||||
if (c_traits.shader.short_uvs == 1u) {
|
||||
src = vec4<f32>(v_short_uvs.data[uv_0_4_idx.x], 0.0, 1.0);
|
||||
} else {
|
||||
src = vec4<f32>(v_uvs.data[uv_0_4_idx.x], 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
case 3: { src = vec4<f32>(v_uvs.data[uv_0_4_idx.y], 0.0, 1.0); }
|
||||
case 4: { src = vec4<f32>(v_uvs.data[uv_0_4_idx.z], 0.0, 1.0); }
|
||||
case 5: { src = vec4<f32>(v_uvs.data[uv_0_4_idx.w], 0.0, 1.0); }
|
||||
case 6: { src = vec4<f32>(v_uvs.data[uv_4_7_idx.x], 0.0, 1.0); }
|
||||
case 7: { src = vec4<f32>(v_uvs.data[uv_4_7_idx.y], 0.0, 1.0); }
|
||||
case 8: { src = vec4<f32>(v_uvs.data[uv_4_7_idx.z], 0.0, 1.0); }
|
||||
default: {}
|
||||
}
|
||||
let tcgm = process_uv_anim(model_matrix, mv_inv, traits);
|
||||
var tmp = (tcgm.mtx * src).xyz;
|
||||
if (traits.normalize == 1u) {
|
||||
tmp = normalize(tmp);
|
||||
}
|
||||
let tmp_proj = tcgm.post_mtx * vec4<f32>(tmp, 1.0);
|
||||
return (tmp_proj / tmp_proj.w).xy;
|
||||
} else {
|
||||
switch (traits.uv_source) {
|
||||
case 0: { return (*obj_pos).xy; }
|
||||
case 1: { return (*obj_norm).xy; }
|
||||
case 2: {
|
||||
if (c_traits.shader.short_uvs == 1u) {
|
||||
return v_short_uvs.data[uv_0_4_idx.x];
|
||||
} else {
|
||||
return v_uvs.data[uv_0_4_idx.x];
|
||||
}
|
||||
}
|
||||
case 3: { return v_uvs.data[uv_0_4_idx.y]; }
|
||||
case 4: { return v_uvs.data[uv_0_4_idx.z]; }
|
||||
case 5: { return v_uvs.data[uv_0_4_idx.w]; }
|
||||
case 6: { return v_uvs.data[uv_4_7_idx.x]; }
|
||||
case 7: { return v_uvs.data[uv_4_7_idx.y]; }
|
||||
case 8: { return v_uvs.data[uv_4_7_idx.z]; }
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
return vec2<f32>(0.0);
|
||||
}
|
||||
|
||||
@stage(vertex)
|
||||
fn vs_main(
|
||||
@location(0) pos_norm_idx: vec2<i32>,
|
||||
@location(1) uv_0_4_idx: vec4<i32>,
|
||||
@location(2) uv_4_7_idx: vec4<i32>,
|
||||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
var obj_pos = vec4<f32>(v_verts.data[pos_norm_idx.x], 1.0);
|
||||
var obj_norm = vec4<f32>(v_norms.data[pos_norm_idx.y], 0.0);
|
||||
var model_matrix_no_trans = make_rotate(radians(u_model.orientation)) * make_scale(u_model.scale);
|
||||
var model_matrix = make_translate(u_model.position) * model_matrix_no_trans;
|
||||
var mv = u_global.view * model_matrix;
|
||||
var mv_inv = transpose(u_global.view * model_matrix_no_trans);
|
||||
var mv_pos = mv * obj_pos;
|
||||
var mv_norm = mv_inv * obj_norm;
|
||||
|
||||
out.position = u_global.proj * mv_pos;
|
||||
out.uv_lightmap = calculate_tcg(c_traits.lightmap, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_diffuse = calculate_tcg(c_traits.diffuse, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_diffuse_mod = calculate_tcg(c_traits.diffuse_mod, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_emissive = calculate_tcg(c_traits.emissive, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_specular = calculate_tcg(c_traits.specular, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_extended_specular = calculate_tcg(c_traits.extended_specular, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_reflection = calculate_tcg(c_traits.reflection, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_alpha = calculate_tcg(c_traits.alpha, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
out.uv_alpha_mod = calculate_tcg(c_traits.alpha_mod, &obj_pos, &obj_norm, &model_matrix, &mv_inv, uv_0_4_idx, uv_4_7_idx);
|
||||
|
||||
if (c_traits.shader.samus_reflection == 1u) {
|
||||
// TODO dyn reflection
|
||||
}
|
||||
|
||||
if (u_traits.post_type > 0u && u_traits.post_type < 5u) {
|
||||
out.lighting = vec3<f32>(1.0);
|
||||
} else {
|
||||
var lighting = u_global.ambient.xyz + u_model.ambient_color.xyz;
|
||||
for (var i = 0; i < 8; i = i + 1) {
|
||||
var light = u_model.lights[i];
|
||||
var delta = mv_pos.xyz - light.pos;
|
||||
var dist = length(delta);
|
||||
var delta_norm = delta / dist;
|
||||
var ang_dot = max(dot(delta_norm, light.dir), 0.0);
|
||||
var lin_att = light.lin_att;
|
||||
var att = 1.0 / (lin_att.z * dist * dist * lin_att.y * dist + lin_att.x);
|
||||
var ang_att = light.ang_att;
|
||||
var ang_att_d = ang_att.z * ang_dot * ang_dot * ang_att.y * ang_dot + ang_att.x;
|
||||
var this_color = light.color.xyz * ang_att_d * att * max(dot(-delta_norm, mv_norm.xyz), 0.0);
|
||||
if (i == 0 && c_traits.shader.world_shadow == 1u) {
|
||||
// TODO ExtTex0 sample
|
||||
}
|
||||
lighting = lighting + this_color;
|
||||
}
|
||||
out.lighting = clamp(lighting, vec3<f32>(0.0), vec3<f32>(1.0));
|
||||
}
|
||||
|
||||
// TODO dyn reflection sample
|
||||
|
||||
return out;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
fn calculate_tcg(
|
||||
traits: PassTrait,
|
||||
uv_in: vec3<f32>,
|
||||
obj_pos: ptr<function, vec4<f32>>,
|
||||
obj_norm: ptr<function, vec4<f32>>,
|
||||
model_matrix: ptr<function, mat4x4<f32>>,
|
||||
mv_inv: ptr<function, mat4x4<f32>>,
|
||||
) -> vec2<f32> {
|
||||
var uv: vec4<f32> = vec4<f32>(uv_in, 1.0);
|
||||
if (traits.tcg_mtx_idx >= 0) {
|
||||
let tcgm = process_uv_anim(model_matrix, mv_inv, traits);
|
||||
var tmp = (tcgm.mtx * uv).xyz;
|
||||
if (traits.normalize == 1u) {
|
||||
tmp = normalize(tmp);
|
||||
}
|
||||
let tmp_proj = tcgm.post_mtx * vec4<f32>(tmp, 1.0);
|
||||
return (tmp_proj / tmp_proj.w).xy;
|
||||
}
|
||||
return uv.xy;
|
||||
}
|
||||
|
||||
@stage(vertex)
|
||||
fn vs_main(
|
||||
@location(0) pos: vec3<f32>,
|
||||
@location(1) norm: vec3<f32>,
|
||||
@location(2) in_uv_lightmap: vec3<f32>,
|
||||
@location(3) in_uv_diffuse: vec2<f32>,
|
||||
@location(4) in_uv_diffuse_mod: vec2<f32>,
|
||||
@location(5) in_uv_emissive: vec2<f32>,
|
||||
@location(6) in_uv_specular: vec2<f32>,
|
||||
@location(7) in_uv_extended_specular: vec2<f32>,
|
||||
@location(8) in_uv_reflection: vec2<f32>,
|
||||
@location(9) in_uv_alpha: vec2<f32>,
|
||||
@location(10) in_uv_alpha_mod: vec2<f32>,
|
||||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
var obj_pos = vec4<f32>(pos, 1.0);
|
||||
var obj_norm = vec4<f32>(norm, 0.0);
|
||||
var model_matrix_no_trans = make_rotate(radians(u_model.orientation)) * make_scale(u_model.scale);
|
||||
var model_matrix = make_translate(u_model.position) * model_matrix_no_trans;
|
||||
var mv = u_global.view * model_matrix;
|
||||
var mv_inv = transpose(u_global.view * model_matrix_no_trans);
|
||||
var mv_pos = mv * obj_pos;
|
||||
var mv_norm = mv_inv * obj_norm;
|
||||
|
||||
out.position = u_global.proj * mv_pos;
|
||||
out.uv_lightmap = calculate_tcg(c_traits.lightmap, in_uv_lightmap, &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_diffuse = calculate_tcg(c_traits.diffuse, vec3<f32>(in_uv_diffuse, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_diffuse_mod = calculate_tcg(c_traits.diffuse_mod, vec3<f32>(in_uv_diffuse_mod, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_emissive = calculate_tcg(c_traits.emissive, vec3<f32>(in_uv_emissive, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_specular = calculate_tcg(c_traits.specular, vec3<f32>(in_uv_specular, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_extended_specular = calculate_tcg(c_traits.extended_specular, vec3<f32>(in_uv_extended_specular, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_reflection = calculate_tcg(c_traits.reflection, vec3<f32>(in_uv_reflection, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_alpha = calculate_tcg(c_traits.alpha, vec3<f32>(in_uv_alpha, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
out.uv_alpha_mod = calculate_tcg(c_traits.alpha_mod, vec3<f32>(in_uv_alpha_mod, 0.0), &obj_pos, &obj_norm, &model_matrix, &mv_inv);
|
||||
|
||||
if (c_traits.shader.samus_reflection == 1u) {
|
||||
// TODO dyn reflection
|
||||
}
|
||||
|
||||
if (u_traits.post_type > 0u && u_traits.post_type < 5u) {
|
||||
out.lighting = vec3<f32>(1.0);
|
||||
} else {
|
||||
var lighting = u_global.ambient.xyz + u_model.ambient_color.xyz;
|
||||
for (var i = 0; i < 8; i = i + 1) {
|
||||
var light = u_model.lights[i];
|
||||
var delta = mv_pos.xyz - light.pos;
|
||||
var dist = length(delta);
|
||||
var delta_norm = delta / dist;
|
||||
var ang_dot = max(dot(delta_norm, light.dir), 0.0);
|
||||
var lin_att = light.lin_att;
|
||||
var att = 1.0 / (lin_att.z * dist * dist * lin_att.y * dist + lin_att.x);
|
||||
var ang_att = light.ang_att;
|
||||
var ang_att_d = ang_att.z * ang_dot * ang_dot * ang_att.y * ang_dot + ang_att.x;
|
||||
var this_color = light.color.xyz * ang_att_d * att * max(dot(-delta_norm, mv_norm.xyz), 0.0);
|
||||
if (i == 0 && c_traits.shader.world_shadow == 1u) {
|
||||
// TODO ExtTex0 sample
|
||||
}
|
||||
lighting = lighting + this_color;
|
||||
}
|
||||
out.lighting = clamp(lighting, vec3<f32>(0.0), vec3<f32>(1.0));
|
||||
}
|
||||
|
||||
// TODO dyn reflection sample
|
||||
|
||||
return out;
|
||||
}
|
|
@ -1,17 +1,20 @@
|
|||
use std::ptr::null;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
use cxx::SharedPtr;
|
||||
use twox_hash::XxHash32;
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::{
|
||||
get_app,
|
||||
gpu::TextureWithSampler,
|
||||
shaders::ffi::{TextureClampMode, TextureFormat, TextureRef},
|
||||
shaders::{
|
||||
ffi::{TextureFormat, TextureRef},
|
||||
STATE,
|
||||
},
|
||||
};
|
||||
|
||||
pub(crate) struct TextureWithView {
|
||||
texture: wgpu::Texture,
|
||||
view: wgpu::TextureView,
|
||||
pub(crate) texture: wgpu::Texture,
|
||||
pub(crate) view: wgpu::TextureView,
|
||||
}
|
||||
impl TextureWithView {
|
||||
fn new(texture: wgpu::Texture) -> Self {
|
||||
|
@ -21,12 +24,8 @@ impl TextureWithView {
|
|||
}
|
||||
|
||||
pub(crate) struct RenderTexture {
|
||||
color_texture: Option<TextureWithView>,
|
||||
depth_texture: Option<TextureWithView>,
|
||||
}
|
||||
|
||||
pub(crate) struct Texture {
|
||||
texture: wgpu::Texture,
|
||||
pub(crate) color_texture: Option<TextureWithView>,
|
||||
pub(crate) depth_texture: Option<TextureWithView>,
|
||||
}
|
||||
|
||||
pub(crate) fn create_static_texture_2d(
|
||||
|
@ -60,7 +59,20 @@ pub(crate) fn create_static_texture_2d(
|
|||
},
|
||||
data,
|
||||
);
|
||||
TextureRef { id: u32::MAX }
|
||||
|
||||
// Generate texture hash as ID
|
||||
let mut hasher = XxHash32::with_seed(format.into());
|
||||
width.hash(&mut hasher);
|
||||
height.hash(&mut hasher);
|
||||
mips.hash(&mut hasher);
|
||||
data.hash(&mut hasher);
|
||||
label.hash(&mut hasher);
|
||||
let id = hasher.finish() as u32;
|
||||
|
||||
// Store texture and return reference
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
state.textures.insert(id, TextureWithView::new(texture));
|
||||
TextureRef { id, render: false }
|
||||
}
|
||||
|
||||
pub(crate) fn create_render_texture(
|
||||
|
@ -122,8 +134,54 @@ pub(crate) fn create_render_texture(
|
|||
// anisotropy_clamp: None,
|
||||
// border_color,
|
||||
// });
|
||||
RenderTexture { color_texture, depth_texture };
|
||||
TextureRef { id: u32::MAX }
|
||||
|
||||
// Generate texture hash as ID
|
||||
let mut hasher = XxHash32::default();
|
||||
width.hash(&mut hasher);
|
||||
height.hash(&mut hasher);
|
||||
color_bind_count.hash(&mut hasher);
|
||||
depth_bind_count.hash(&mut hasher);
|
||||
label.hash(&mut hasher);
|
||||
let id = hasher.finish() as u32;
|
||||
|
||||
// Store texture and return reference
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
state.render_textures.insert(id, RenderTexture { color_texture, depth_texture });
|
||||
TextureRef { id, render: true }
|
||||
}
|
||||
|
||||
pub(crate) fn drop_texture(handle: TextureRef) {}
|
||||
pub(crate) fn drop_texture(handle: TextureRef) {
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
if handle.render {
|
||||
state.render_textures.remove(&handle.id).expect("Render texture already dropped");
|
||||
} else {
|
||||
state.textures.remove(&handle.id).expect("Texture already dropped");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_sampler(
|
||||
device: &wgpu::Device,
|
||||
mut address_mode: wgpu::AddressMode,
|
||||
mut border_color: Option<wgpu::SamplerBorderColor>,
|
||||
) -> wgpu::Sampler {
|
||||
if address_mode == wgpu::AddressMode::ClampToBorder
|
||||
&& !device.features().contains(wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER)
|
||||
{
|
||||
address_mode = wgpu::AddressMode::ClampToEdge;
|
||||
border_color = None;
|
||||
}
|
||||
device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: address_mode,
|
||||
address_mode_v: address_mode,
|
||||
address_mode_w: address_mode,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Linear,
|
||||
lod_min_clamp: 0.0,
|
||||
lod_max_clamp: f32::MAX,
|
||||
compare: None,
|
||||
anisotropy_clamp: NonZeroU8::new(16),
|
||||
border_color,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
use std::{collections::HashMap, hash::Hash, ops::Range};
|
||||
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use wgpu::{include_wgsl, vertex_attr_array};
|
||||
|
||||
use crate::{
|
||||
get_app,
|
||||
gpu::GraphicsConfig,
|
||||
shaders::{
|
||||
bind_pipeline,
|
||||
BuiltBuffers,
|
||||
ffi::{CameraFilterType, TextureRef, ZTest}, pipeline_ref, PipelineCreateCommand, PipelineHolder, PipelineRef,
|
||||
push_draw_command, push_uniform, push_verts, ShaderDrawCommand, STATE,
|
||||
},
|
||||
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
|
||||
};
|
||||
use crate::shaders::texture::create_sampler;
|
||||
use crate::util::{align, Vec2, Vec3};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct DrawData {
|
||||
pipeline: PipelineRef,
|
||||
vert_range: Range<u64>,
|
||||
uniform_range: Range<u64>,
|
||||
texture: TextureRef,
|
||||
}
|
||||
|
||||
#[derive(Hash)]
|
||||
pub(crate) struct PipelineConfig {
|
||||
filter_type: CameraFilterType,
|
||||
z_test: ZTest,
|
||||
}
|
||||
pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[
|
||||
// PipelineCreateCommand::TexturedQuad(PipelineConfig { z_only: false }),
|
||||
// PipelineCreateCommand::TexturedQuad(PipelineConfig { z_only: true }),
|
||||
];
|
||||
|
||||
pub(crate) struct State {
|
||||
shader: wgpu::ShaderModule,
|
||||
uniform_layout: wgpu::BindGroupLayout,
|
||||
uniform_bind_group: wgpu::BindGroup,
|
||||
texture_layout: wgpu::BindGroupLayout,
|
||||
sampler: wgpu::Sampler,
|
||||
pipeline_layout: wgpu::PipelineLayout,
|
||||
// Transient state
|
||||
texture_bind_groups: HashMap<u32, wgpu::BindGroup>,
|
||||
frame_used_textures: Vec<u32>, // TODO use to clear bind groups
|
||||
}
|
||||
|
||||
pub(crate) fn construct_state(
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
buffers: &BuiltBuffers,
|
||||
graphics_config: &GraphicsConfig,
|
||||
) -> State {
|
||||
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
|
||||
let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment;
|
||||
let uniform_size = wgpu::BufferSize::new(align(std::mem::size_of::<Uniform>() as u64, uniform_alignment as u64));
|
||||
let uniform_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Textured Quad Uniform Bind Group Layout"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: uniform_size,
|
||||
},
|
||||
count: None,
|
||||
}, wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let sampler = create_sampler(device, wgpu::AddressMode::Repeat, None);
|
||||
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("Textured Quad Uniform Bind Group"),
|
||||
layout: &uniform_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||
buffer: &buffers.uniform_buffer,
|
||||
offset: 0, // dynamic
|
||||
size: uniform_size,
|
||||
}),
|
||||
}, wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
}],
|
||||
});
|
||||
let texture_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Textured Quad Texture Bind Group Layout"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Textured Quad Pipeline Layout"),
|
||||
bind_group_layouts: &[&uniform_layout, &texture_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
State {
|
||||
shader,
|
||||
uniform_layout,
|
||||
uniform_bind_group,
|
||||
texture_layout,
|
||||
sampler,
|
||||
pipeline_layout,
|
||||
texture_bind_groups: Default::default(),
|
||||
frame_used_textures: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn construct_pipeline(
|
||||
device: &wgpu::Device,
|
||||
graphics: &GraphicsConfig,
|
||||
state: &State,
|
||||
config: &PipelineConfig,
|
||||
) -> PipelineHolder {
|
||||
let (blend_component, alpha_write) = match config.filter_type {
|
||||
CameraFilterType::Multiply => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::Zero,
|
||||
dst_factor: wgpu::BlendFactor::Src,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
true,
|
||||
),
|
||||
CameraFilterType::Add => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::Subtract => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
operation: wgpu::BlendOperation::Subtract,
|
||||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::Blend => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::InvDstMultiply => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::Zero,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrc,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
true,
|
||||
),
|
||||
_ => todo!(),
|
||||
};
|
||||
log::warn!("VERT SIZE: {}", std::mem::size_of::<Vert>() as u64);
|
||||
PipelineHolder {
|
||||
pipeline: device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Textured Quad Pipeline"),
|
||||
layout: Some(&state.pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &state.shader,
|
||||
entry_point: "vs_main",
|
||||
buffers: &[wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<Vert>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float32x3, 1 => Float32x2],
|
||||
}],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: graphics.depth_format,
|
||||
depth_write_enabled: config.z_test == ZTest::GEqualZWrite,
|
||||
depth_compare: match config.z_test {
|
||||
ZTest::None => wgpu::CompareFunction::Always,
|
||||
ZTest::LEqual => wgpu::CompareFunction::LessEqual,
|
||||
ZTest::GEqual | ZTest::GEqualZWrite => wgpu::CompareFunction::GreaterEqual,
|
||||
_ => todo!(),
|
||||
},
|
||||
stencil: Default::default(),
|
||||
bias: Default::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: graphics.msaa_samples,
|
||||
..Default::default()
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &state.shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
format: graphics.color_format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
color: blend_component,
|
||||
alpha: blend_component,
|
||||
}),
|
||||
write_mask: if alpha_write {
|
||||
wgpu::ColorWrites::ALL
|
||||
} else {
|
||||
wgpu::ColorWrites::COLOR
|
||||
},
|
||||
}],
|
||||
}),
|
||||
multiview: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
|
||||
#[repr(C)]
|
||||
struct Uniform {
|
||||
xf: CMatrix4f,
|
||||
color: CColor,
|
||||
lod: f32,
|
||||
}
|
||||
|
||||
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
|
||||
#[repr(C)]
|
||||
struct Vert {
|
||||
pos: Vec3<f32>,
|
||||
uv: Vec2<f32>,
|
||||
}
|
||||
|
||||
pub(crate) fn queue_textured_quad(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_test: ZTest,
|
||||
color: CColor,
|
||||
uv_scale: f32,
|
||||
rect: CRectangle,
|
||||
z: f32,
|
||||
) {
|
||||
let pipeline =
|
||||
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_test }));
|
||||
let vert_range = push_verts(&[
|
||||
Vert { pos: Vec3::new(0.0, 0.0, z), uv: Vec2::new(0.0, 0.0) },
|
||||
Vert { pos: Vec3::new(0.0, 1.0, z), uv: Vec2::new(0.0, uv_scale) },
|
||||
Vert { pos: Vec3::new(1.0, 0.0, z), uv: Vec2::new(uv_scale, 0.0) },
|
||||
Vert { pos: Vec3::new(1.0, 1.0, z), uv: Vec2::new(uv_scale, uv_scale) },
|
||||
]);
|
||||
let uniform_range = push_uniform(&Uniform {
|
||||
xf: CMatrix4f::new(
|
||||
CVector4f::new(rect.size.x * 2.0, 0.0, 0.0, 0.0),
|
||||
CVector4f::new(0.0, rect.size.y * 2.0, 0.0, 0.0),
|
||||
CVector4f::new(0.0, 0.0, 1.0, 0.0),
|
||||
CVector4f::new(rect.position.x * 2.0 - 1.0, rect.position.y * 2.0 - 1.0, 0.0, 1.0),
|
||||
),
|
||||
color,
|
||||
lod: 0.0,
|
||||
});
|
||||
|
||||
// TODO defer bind group creation to draw time or another thread?
|
||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||
let groups = &mut state.textured_quad.texture_bind_groups;
|
||||
if !groups.contains_key(&texture.id) {
|
||||
let tex = state.textures.get(&texture.id).unwrap();
|
||||
let bind_group = get_app().gpu.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &state.textured_quad.texture_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&tex.view),
|
||||
}],
|
||||
});
|
||||
groups.insert(texture.id, bind_group);
|
||||
}
|
||||
|
||||
push_draw_command(ShaderDrawCommand::TexturedQuad(DrawData {
|
||||
pipeline,
|
||||
vert_range,
|
||||
uniform_range,
|
||||
texture,
|
||||
}));
|
||||
}
|
||||
|
||||
pub(crate) fn draw_textured_quad<'a>(
|
||||
data: &DrawData,
|
||||
state: &'a State,
|
||||
pass: &mut wgpu::RenderPass<'a>,
|
||||
buffers: &'a BuiltBuffers,
|
||||
) {
|
||||
if !bind_pipeline(data.pipeline, pass) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uniform bind group
|
||||
pass.set_bind_group(0, &state.uniform_bind_group, &[
|
||||
data.uniform_range.start as wgpu::DynamicOffset
|
||||
]);
|
||||
|
||||
// Texture bind group
|
||||
let texture_bind_group =
|
||||
state.texture_bind_groups.get(&data.texture.id).expect("Failed to find texture bind group");
|
||||
pass.set_bind_group(1, texture_bind_group, &[]);
|
||||
|
||||
// Vertex buffer
|
||||
pass.set_vertex_buffer(0, buffers.vertex_buffer.slice(data.vert_range.clone()));
|
||||
pass.draw(0..4, 0..1);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
struct Uniform {
|
||||
xf: mat4x4<f32>;
|
||||
color: vec4<f32>;
|
||||
lod: f32;
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;
|
||||
@group(0) @binding(1)
|
||||
var texture_sampler: sampler;
|
||||
@group(1) @binding(0)
|
||||
var texture: texture_2d<f32>;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) pos: vec4<f32>;
|
||||
@location(0) uv: vec2<f32>;
|
||||
};
|
||||
|
||||
@stage(vertex)
|
||||
fn vs_main(@location(0) in_pos: vec3<f32>, @location(1) in_uv: vec2<f32>) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);
|
||||
out.uv = in_uv;
|
||||
return out;
|
||||
}
|
||||
|
||||
@stage(fragment)
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
return ubuf.color * textureSampleBias(texture, texture_sampler, in.uv, ubuf.lod);
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//! This contains regular vector types for use in packed buffers (i.e. vertex).
|
||||
//! zeus types are all aligned to f32x4
|
||||
use binrw::BinRead;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, BinRead, Default)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct Vec3<T: 'static + BinRead<Args = ()> + Pod> {
|
||||
pub(crate) x: T,
|
||||
pub(crate) y: T,
|
||||
pub(crate) z: T,
|
||||
}
|
||||
impl<T: 'static + BinRead<Args = ()> + Pod> Vec3<T> {
|
||||
// TODO const
|
||||
pub fn new(x: T, y: T, z: T) -> Self { Self { x, y, z } }
|
||||
}
|
||||
|
||||
unsafe impl<T: BinRead<Args = ()> + Pod> Zeroable for Vec3<T> {}
|
||||
|
||||
unsafe impl<T: BinRead<Args = ()> + Pod> Pod for Vec3<T> {}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<T> for Vec3<T> {
|
||||
fn from(v: T) -> Self { Vec3::<T> { x: v, y: v, z: v } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<cgmath::Vector3<T>> for Vec3<T> {
|
||||
fn from(v: cgmath::Vector3<T>) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<Vec3<T>> for cgmath::Vector3<T> {
|
||||
fn from(v: Vec3<T>) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<cgmath::Point3<T>> for Vec3<T> {
|
||||
fn from(v: cgmath::Point3<T>) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<Vec3<T>> for cgmath::Point3<T> {
|
||||
fn from(v: Vec3<T>) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
|
||||
// pub(crate) const fn vec3_splat<T: BinRead<Args = ()> + Pod>(v: T) -> Vec3<T> {
|
||||
// Vec3::<T> { x: v, y: v, z: v }
|
||||
// }
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, BinRead, Default)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct Vec2<T: 'static + BinRead<Args = ()> + Pod> {
|
||||
pub(crate) x: T,
|
||||
pub(crate) y: T,
|
||||
}
|
||||
impl<T: 'static + BinRead<Args = ()> + Pod> Vec2<T> {
|
||||
// TODO const
|
||||
pub fn new(x: T, y: T) -> Self { Self { x, y } }
|
||||
}
|
||||
|
||||
unsafe impl<T: BinRead<Args = ()> + Pod> Zeroable for Vec2<T> {}
|
||||
|
||||
unsafe impl<T: BinRead<Args = ()> + Pod> Pod for Vec2<T> {}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<T> for Vec2<T> {
|
||||
fn from(v: T) -> Self { Self { x: v, y: v } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<cgmath::Vector2<T>> for Vec2<T> {
|
||||
fn from(v: cgmath::Vector2<T>) -> Self { Self { x: v.x, y: v.y } }
|
||||
}
|
||||
|
||||
impl<T: BinRead<Args = ()> + Pod> From<Vec2<T>> for cgmath::Vector2<T> {
|
||||
fn from(v: Vec2<T>) -> Self { Self { x: v.x, y: v.y } }
|
||||
}
|
||||
|
||||
impl From<Vec2<i16>> for Vec2<f32> {
|
||||
fn from(v: Vec2<i16>) -> Self { Self { x: v.x as f32 / 32768.0, y: v.y as f32 / 32768.0 } }
|
||||
}
|
||||
|
||||
// pub(crate) const fn vec2_splat<T: BinRead<Args = ()> + Pod>(v: T) -> Vec2<T> {
|
||||
// Vec2::<T> { x: v, y: v }
|
||||
// }
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn align<
|
||||
T: Copy
|
||||
+ std::ops::Sub<Output = T>
|
||||
+ std::ops::Add<Output = T>
|
||||
+ std::ops::Not<Output = T>
|
||||
+ std::ops::BitAnd<Output = T>
|
||||
+ num_traits::One
|
||||
+ num_traits::Zero
|
||||
+ std::cmp::PartialEq,
|
||||
>(
|
||||
n: T,
|
||||
a: T,
|
||||
) -> T {
|
||||
if a == num_traits::Zero::zero() {
|
||||
return n;
|
||||
}
|
||||
(n + (a - num_traits::One::one())) & !(a - num_traits::One::one())
|
||||
}
|
|
@ -15,13 +15,13 @@ constexpr std::array SplashTextures{"TXTR_NintendoLogo"sv, "TXTR_RetroLogo"sv, "
|
|||
CSplashScreen::CSplashScreen(ESplashScreen which)
|
||||
: CIOWin("SplashScreen")
|
||||
, x14_which(which)
|
||||
, m_quad(EFilterType::Blend, g_SimplePool->GetObj(SplashTextures[size_t(which)])) {}
|
||||
, m_texture(g_SimplePool->GetObj(SplashTextures[size_t(which)])) {}
|
||||
|
||||
CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) {
|
||||
switch (msg.GetType()) {
|
||||
case EArchMsgType::TimerTick: {
|
||||
if (!x25_textureLoaded) {
|
||||
if (!m_quad.GetTex().IsLoaded())
|
||||
if (!m_texture.IsLoaded())
|
||||
return EMessageReturn::Exit;
|
||||
x25_textureLoaded = true;
|
||||
}
|
||||
|
@ -68,12 +68,20 @@ void CSplashScreen::Draw() {
|
|||
}
|
||||
|
||||
zeus::CRectangle rect;
|
||||
rect.size.x() = m_quad.GetTex()->GetWidth() / (480.f * g_Viewport.aspect);
|
||||
rect.size.y() = m_quad.GetTex()->GetHeight() / 480.f;
|
||||
rect.size.x() = m_texture->GetWidth() / (480.f * g_Viewport.aspect);
|
||||
rect.size.y() = m_texture->GetHeight() / 480.f;
|
||||
rect.position.x() = 0.5f - rect.size.x() / 2.f;
|
||||
rect.position.y() = 0.5f - rect.size.y() / 2.f;
|
||||
|
||||
m_quad.draw(color, 1.f, rect);
|
||||
aurora::shaders::queue_textured_quad(
|
||||
aurora::shaders::CameraFilterType::Blend,
|
||||
m_texture->GetTexture()->ref,
|
||||
aurora::shaders::ZTest::None,
|
||||
color,
|
||||
1.f,
|
||||
rect,
|
||||
0.f
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -19,7 +19,7 @@ private:
|
|||
// EProgressivePhase x20_progressivePhase = EProgressivePhase::Before;
|
||||
// bool x24_progressiveSelection = true;
|
||||
bool x25_textureLoaded = false;
|
||||
CTexturedQuadFilterAlpha m_quad;
|
||||
TLockedToken<CTexture> m_texture;
|
||||
|
||||
public:
|
||||
explicit CSplashScreen(ESplashScreen);
|
||||
|
|
Loading…
Reference in New Issue