+30
-31
lightweight_viewer/src/char.rs
+30
-31
lightweight_viewer/src/char.rs
···
1
use crate::State;
2
use crate::render::shape_data_to_render_3d_shape;
3
use glam::{Vec3, uvec2};
4
-
use image::{DynamicImage, RgbaImage};
5
use vfl::color::nx::ModulationIntent;
6
use vfl::draw::render_3d::Rendered3dShape;
7
-
use vfl::res::tex::nx::{ResourceTexture, TextureElement};
8
use vfl::{
9
color::nx::{ColorModulated, modulate},
10
draw::{
···
15
};
16
use wgpu::{CommandEncoder, TextureView};
17
18
-
pub fn draw_noseline(st: &mut State, texture_view: &TextureView, encoder: &mut CommandEncoder) {
19
let res_texture = &st.resources.texture_header;
20
let file_texture = &st.resources.texture_data;
21
22
let noseline_num = usize::from(st.char_info.nose_type);
23
24
-
let tex: image::ImageBuffer<image::Rgba<u8>, Vec<u8>> = res_texture.noseline[noseline_num]
25
-
.get_image(file_texture)
26
.unwrap()
27
.unwrap();
28
-
let tex = DynamicImage::ImageRgba8(tex);
29
30
Rendered2dShape::render_texture_trivial(
31
tex,
32
modulate(ColorModulated::NoseLineShape, &st.char_info),
33
None,
34
st,
35
-
texture_view,
36
encoder,
37
);
38
}
39
40
pub fn draw_mask(st: &mut State, texture_view: &TextureView, encoder: &mut CommandEncoder) {
···
56
st: &mut State,
57
texture_element: TextureElement,
58
modulated: ColorModulated,
59
-
) -> Option<(DynamicImage, ModulationIntent)> {
60
texture_element
61
-
.get_image(&st.resources.texture_data)
62
.unwrap()
63
-
.map(|tex| {
64
-
(
65
-
DynamicImage::ImageRgba8(tex),
66
-
modulate(modulated, &st.char_info),
67
-
)
68
-
})
69
}
70
71
// Load faceline textures in order [wrinkle, makeup, beard], and removes any that don't exist
72
fn get_faceline_textures(
73
st: &mut State,
74
res_texture: &ResourceTexture,
75
-
) -> Vec<(DynamicImage, ModulationIntent)> {
76
vec![
77
load_faceline_texture(
78
st,
···
101
fn draw_faceline(st: &mut State, texture_view: &TextureView, encoder: &mut CommandEncoder) {
102
let res_texture = st.resources.texture_header;
103
104
-
// let makeup_tex = res_texture.makeup[st.char_info.faceline_make as usize]
105
-
// .get_image(&st.resources.texture_data)
106
-
// .unwrap();
107
-
// let Some(makeup_tex) = makeup_tex else {
108
-
// return;
109
-
// };
110
-
// let makeup_tex = image::DynamicImage::ImageRgba8(tex);
111
-
112
let textures = get_faceline_textures(st, &res_texture);
113
114
for (i, (rendered_texture, modulation)) in textures.iter().enumerate() {
···
121
Rendered2dShape::render_texture_trivial(
122
rendered_texture.to_owned(),
123
modulation.to_owned(),
124
-
opaque,
125
st,
126
texture_view,
127
encoder,
···
197
// // "noselinetex",
198
// // );
199
200
-
let noseline_texture =
201
-
texture::Texture::create_texture(&st.device, &uvec2(256, 256), "noselinetex");
202
203
-
draw_noseline(st, &noseline_texture.view, encoder);
204
205
Some(noseline_texture)
206
}
207
Shape::Mask => {
208
let mask_texture =
209
-
texture::Texture::create_texture(&st.device, &uvec2(512, 512), "masktex");
210
211
draw_mask(st, &mask_texture.view, encoder);
212
···
214
}
215
Shape::FaceLine => {
216
let faceline_texture =
217
-
texture::Texture::create_texture(&st.device, &uvec2(512, 512), "facelinetex");
218
219
-
println!("hi!");
220
draw_faceline(st, &faceline_texture.view, encoder);
221
222
Some(faceline_texture)
···
1
use crate::State;
2
use crate::render::shape_data_to_render_3d_shape;
3
use glam::{Vec3, uvec2};
4
+
use image::DynamicImage;
5
use vfl::color::nx::ModulationIntent;
6
+
use vfl::draw::render_2d::texture_format_to_wgpu;
7
use vfl::draw::render_3d::Rendered3dShape;
8
+
use vfl::draw::wgpu_render::texture::TextureBundle;
9
+
use vfl::res::tex::nx::{RawTexture, ResourceTexture, TextureElement};
10
use vfl::{
11
color::nx::{ColorModulated, modulate},
12
draw::{
···
17
};
18
use wgpu::{CommandEncoder, TextureView};
19
20
+
pub fn draw_noseline(
21
+
st: &mut State,
22
+
texture_view: Option<TextureBundle>,
23
+
encoder: &mut CommandEncoder,
24
+
) -> texture::TextureBundle {
25
let res_texture = &st.resources.texture_header;
26
let file_texture = &st.resources.texture_data;
27
28
let noseline_num = usize::from(st.char_info.nose_type);
29
30
+
let tex = res_texture.noseline[noseline_num]
31
+
.get_uncompressed_bytes(file_texture)
32
.unwrap()
33
.unwrap();
34
+
35
+
let output_texture = if let Some(texture_view) = texture_view {
36
+
texture_view
37
+
} else {
38
+
texture::TextureBundle::create_texture(&st.device, &uvec2(256, 256), "noselinetex")
39
+
};
40
41
Rendered2dShape::render_texture_trivial(
42
tex,
43
modulate(ColorModulated::NoseLineShape, &st.char_info),
44
None,
45
st,
46
+
&output_texture.view,
47
encoder,
48
);
49
+
50
+
output_texture
51
}
52
53
pub fn draw_mask(st: &mut State, texture_view: &TextureView, encoder: &mut CommandEncoder) {
···
69
st: &mut State,
70
texture_element: TextureElement,
71
modulated: ColorModulated,
72
+
) -> Option<(RawTexture, ModulationIntent)> {
73
texture_element
74
+
.get_uncompressed_bytes(&st.resources.texture_data)
75
.unwrap()
76
+
.map(|bytes| (bytes, modulate(modulated, &st.char_info)))
77
}
78
79
// Load faceline textures in order [wrinkle, makeup, beard], and removes any that don't exist
80
fn get_faceline_textures(
81
st: &mut State,
82
res_texture: &ResourceTexture,
83
+
) -> Vec<(RawTexture, ModulationIntent)> {
84
vec![
85
load_faceline_texture(
86
st,
···
109
fn draw_faceline(st: &mut State, texture_view: &TextureView, encoder: &mut CommandEncoder) {
110
let res_texture = st.resources.texture_header;
111
112
let textures = get_faceline_textures(st, &res_texture);
113
114
for (i, (rendered_texture, modulation)) in textures.iter().enumerate() {
···
121
Rendered2dShape::render_texture_trivial(
122
rendered_texture.to_owned(),
123
modulation.to_owned(),
124
+
None,
125
st,
126
texture_view,
127
encoder,
···
197
// // "noselinetex",
198
// // );
199
200
+
// let noseline_texture =
201
+
// texture::TextureBundle::create_texture(&st.device, &uvec2(256, 256), "noselinetex");
202
203
+
let noseline_texture = draw_noseline(st, None, encoder);
204
205
Some(noseline_texture)
206
}
207
Shape::Mask => {
208
let mask_texture =
209
+
texture::TextureBundle::create_texture(&st.device, &uvec2(512, 512), "masktex");
210
211
draw_mask(st, &mask_texture.view, encoder);
212
···
214
}
215
Shape::FaceLine => {
216
let faceline_texture =
217
+
texture::TextureBundle::create_texture(&st.device, &uvec2(512, 512), "facelinetex");
218
219
draw_faceline(st, &faceline_texture.view, encoder);
220
221
Some(faceline_texture)
+6
-11
lightweight_viewer/src/char_model.rs
+6
-11
lightweight_viewer/src/char_model.rs
···
1
-
use vfl::{
2
-
draw::{faceline, render_3d::Rendered3dShape},
3
-
res::shape::nx::{Shape, ShapeData},
4
-
};
5
use wgpu::{CommandEncoder, TextureView};
6
7
use crate::{State, char::load_shape};
8
9
-
type Tex = wgpu::Texture;
10
-
type TexOpt = Option<wgpu::Texture>;
11
type Model = Rendered3dShape;
12
type ModelOpt = Option<Rendered3dShape>;
13
···
37
encoder: &mut CommandEncoder,
38
) {
39
self.face_line.render(st, texture_view, encoder);
40
-
if let Some(hair) = self.hair.as_mut() {
41
-
hair.render(st, texture_view, encoder);
42
-
}
43
-
self.mask.render(st, texture_view, encoder);
44
45
-
self.nose_line.render(st, texture_view, encoder);
46
}
47
}
48
···
1
+
use vfl::{draw::render_3d::Rendered3dShape, res::shape::nx::Shape};
2
use wgpu::{CommandEncoder, TextureView};
3
4
use crate::{State, char::load_shape};
5
6
type Model = Rendered3dShape;
7
type ModelOpt = Option<Rendered3dShape>;
8
···
32
encoder: &mut CommandEncoder,
33
) {
34
self.face_line.render(st, texture_view, encoder);
35
+
// if let Some(hair) = self.hair.as_mut() {
36
+
// hair.render(st, texture_view, encoder);
37
+
// }
38
+
// self.mask.render(st, texture_view, encoder);
39
40
+
// self.nose_line.render(st, texture_view, encoder);
41
}
42
}
43
+28
-68
lightweight_viewer/src/main.rs
+28
-68
lightweight_viewer/src/main.rs
···
1
-
use std::rc::Rc;
2
-
use std::sync::{Mutex, OnceLock};
3
-
use std::{f32::consts::FRAC_PI_2, fs::File, io::BufReader, sync::Arc};
4
-
5
use camera::{Camera, CameraUniform};
6
-
use char::draw_char;
7
use char_model::CharModel;
8
use glam::{UVec2, Vec3, Vec4, uvec2, vec4};
9
use vfl::res::shape::nx::ResourceShape;
10
use vfl::res::tex::nx::ResourceTexture;
11
use vfl::{
···
13
draw::{render_3d::ProgramState, wgpu_render::texture},
14
res::{shape::nx::SHAPE_MID_DAT, tex::nx::TEXTURE_MID_SRGB_DAT},
15
};
16
use wgpu::{Backends, util::DeviceExt};
17
-
use wgpu::{CommandEncoder, TextureView};
18
use winit::{
19
application::ApplicationHandler,
20
event::WindowEvent,
···
28
pub mod char_model;
29
pub mod render;
30
31
const OVERLAY_REBECCA_PURPLE: wgpu::Color = wgpu::Color {
32
r: 0.1,
33
g: 0.12,
···
65
shape_data: Vec<u8>,
66
}
67
68
-
struct WgpuSubState<'a> {
69
-
inner: (
70
-
wgpu::Device,
71
-
wgpu::Queue,
72
-
&'a wgpu::BindGroupLayout,
73
-
&'a wgpu::BindGroup,
74
-
wgpu::TextureFormat,
75
-
&'a texture::Texture,
76
-
),
77
-
}
78
-
79
pub struct State {
80
window: Arc<Window>,
81
device: wgpu::Device,
···
84
surface: wgpu::Surface<'static>,
85
surface_format: wgpu::TextureFormat,
86
char_info: NxCharInfo,
87
-
char_model: Option<CharModel>,
88
char_remake: bool,
89
camera: Camera,
90
camera_buffer: wgpu::Buffer,
91
camera_bind_group: wgpu::BindGroup,
92
camera_uniform: CameraUniform,
93
camera_bind_group_layout: wgpu::BindGroupLayout,
94
-
depth_texture: texture::Texture,
95
camera_rotations: usize,
96
resources: ResourceData,
97
}
···
117
self.surface_format
118
}
119
120
-
fn depth_texture(&self) -> &vfl::draw::wgpu_render::texture::Texture {
121
&self.depth_texture
122
}
123
}
124
125
-
impl<'a> ProgramState for WgpuSubState<'a> {
126
-
fn device(&self) -> wgpu::Device {
127
-
self.inner.0.clone()
128
-
}
129
-
130
-
fn queue(&self) -> wgpu::Queue {
131
-
self.inner.1.clone()
132
-
}
133
-
134
-
fn camera_bgl(&self) -> &wgpu::BindGroupLayout {
135
-
self.inner.2
136
-
}
137
-
138
-
fn camera_bg(&self) -> &wgpu::BindGroup {
139
-
self.inner.3
140
-
}
141
-
142
-
fn surface_fmt(&self) -> wgpu::TextureFormat {
143
-
self.inner.4.clone()
144
-
}
145
-
146
-
fn depth_texture(&self) -> &texture::Texture {
147
-
self.inner.5
148
-
}
149
-
}
150
-
151
impl State {
152
-
fn wgpu_sub_state(&self) -> WgpuSubState {
153
-
WgpuSubState {
154
-
inner: (
155
-
self.device(),
156
-
self.queue(),
157
-
self.camera_bgl(),
158
-
self.camera_bg(),
159
-
self.surface_fmt(),
160
-
self.depth_texture(),
161
-
),
162
-
}
163
-
}
164
-
165
async fn new(window: Arc<Window>) -> State {
166
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
167
backends: Backends::PRIMARY | Backends::SECONDARY,
···
171
.request_adapter(&wgpu::RequestAdapterOptions::default())
172
.await
173
.unwrap();
174
-
let (device, queue) = adapter
175
-
.request_device(&wgpu::DeviceDescriptor::default())
176
-
.await
177
-
.unwrap();
178
179
let size = window.inner_size();
180
let size = uvec2(size.width, size.height);
···
183
let cap = surface.get_capabilities(&adapter);
184
let surface_format = cap.formats[0];
185
186
-
let depth_texture = texture::Texture::create_depth_texture(&device, &size, "depth_texture");
187
188
let mut char_info =
189
File::open(format!("{}/../{}", env!("CARGO_MANIFEST_DIR"), FACES[0])).unwrap();
···
237
let shape_header = ResourceShape::read(&mut File::open(SHAPE_MID_DAT).unwrap()).unwrap();
238
let texture_header =
239
ResourceTexture::read(&mut File::open(TEXTURE_MID_SRGB_DAT).unwrap()).unwrap();
240
-
let shape_data = (std::fs::read(SHAPE_MID_DAT).unwrap());
241
-
let texture_data = (std::fs::read(TEXTURE_MID_SRGB_DAT).unwrap());
242
243
let resources = ResourceData {
244
shape_header,
···
255
surface,
256
surface_format,
257
char_info,
258
-
char_model: None,
259
camera,
260
camera_buffer,
261
camera_bind_group,
···
299
self.configure_surface();
300
301
self.depth_texture =
302
-
texture::Texture::create_depth_texture(&self.device, &self.size, "depth_texture");
303
}
304
305
fn render(&mut self) {
···
356
let new_model = CharModel::new(self, &mut encoder);
357
CHAR_MODEL.set(Mutex::new(new_model)).unwrap();
358
}
359
if self.char_remake {
360
self.char_remake = false;
361
// let mut encoder = self.device.create_command_encoder(&Default::default());
···
1
use camera::{Camera, CameraUniform};
2
use char_model::CharModel;
3
use glam::{UVec2, Vec3, Vec4, uvec2, vec4};
4
+
use std::sync::{Mutex, OnceLock};
5
+
use std::{f32::consts::FRAC_PI_2, fs::File, sync::Arc};
6
use vfl::res::shape::nx::ResourceShape;
7
use vfl::res::tex::nx::ResourceTexture;
8
use vfl::{
···
10
draw::{render_3d::ProgramState, wgpu_render::texture},
11
res::{shape::nx::SHAPE_MID_DAT, tex::nx::TEXTURE_MID_SRGB_DAT},
12
};
13
+
use wgpu::Features;
14
use wgpu::{Backends, util::DeviceExt};
15
use winit::{
16
application::ApplicationHandler,
17
event::WindowEvent,
···
25
pub mod char_model;
26
pub mod render;
27
28
+
#[allow(unused)]
29
const OVERLAY_REBECCA_PURPLE: wgpu::Color = wgpu::Color {
30
r: 0.1,
31
g: 0.12,
···
63
shape_data: Vec<u8>,
64
}
65
66
pub struct State {
67
window: Arc<Window>,
68
device: wgpu::Device,
···
71
surface: wgpu::Surface<'static>,
72
surface_format: wgpu::TextureFormat,
73
char_info: NxCharInfo,
74
char_remake: bool,
75
camera: Camera,
76
camera_buffer: wgpu::Buffer,
77
camera_bind_group: wgpu::BindGroup,
78
camera_uniform: CameraUniform,
79
camera_bind_group_layout: wgpu::BindGroupLayout,
80
+
depth_texture: texture::TextureBundle,
81
camera_rotations: usize,
82
resources: ResourceData,
83
}
···
103
self.surface_format
104
}
105
106
+
fn depth_texture(&self) -> &vfl::draw::wgpu_render::texture::TextureBundle {
107
&self.depth_texture
108
}
109
}
110
111
impl State {
112
async fn new(window: Arc<Window>) -> State {
113
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
114
backends: Backends::PRIMARY | Backends::SECONDARY,
···
118
.request_adapter(&wgpu::RequestAdapterOptions::default())
119
.await
120
.unwrap();
121
+
122
+
dbg!(
123
+
adapter.get_texture_format_features(wgpu::TextureFormat::Astc {
124
+
block: wgpu::AstcBlock::B4x4,
125
+
channel: wgpu::AstcChannel::Unorm
126
+
})
127
+
);
128
+
let device_descriptor = wgpu::DeviceDescriptor {
129
+
required_features: Features::TEXTURE_COMPRESSION_ASTC
130
+
| Features::TEXTURE_COMPRESSION_BC,
131
+
..Default::default()
132
+
};
133
+
let (device, queue) = adapter.request_device(&device_descriptor).await.unwrap();
134
135
let size = window.inner_size();
136
let size = uvec2(size.width, size.height);
···
139
let cap = surface.get_capabilities(&adapter);
140
let surface_format = cap.formats[0];
141
142
+
let depth_texture =
143
+
texture::TextureBundle::create_depth_texture(&device, &size, "depth_texture");
144
145
let mut char_info =
146
File::open(format!("{}/../{}", env!("CARGO_MANIFEST_DIR"), FACES[0])).unwrap();
···
194
let shape_header = ResourceShape::read(&mut File::open(SHAPE_MID_DAT).unwrap()).unwrap();
195
let texture_header =
196
ResourceTexture::read(&mut File::open(TEXTURE_MID_SRGB_DAT).unwrap()).unwrap();
197
+
let shape_data = std::fs::read(SHAPE_MID_DAT).unwrap();
198
+
let texture_data = std::fs::read(TEXTURE_MID_SRGB_DAT).unwrap();
199
200
let resources = ResourceData {
201
shape_header,
···
212
surface,
213
surface_format,
214
char_info,
215
camera,
216
camera_buffer,
217
camera_bind_group,
···
255
self.configure_surface();
256
257
self.depth_texture =
258
+
texture::TextureBundle::create_depth_texture(&self.device, &self.size, "depth_texture");
259
}
260
261
fn render(&mut self) {
···
312
let new_model = CharModel::new(self, &mut encoder);
313
CHAR_MODEL.set(Mutex::new(new_model)).unwrap();
314
}
315
+
316
+
// For profiling:
317
+
// self.char_remake = true;
318
+
319
if self.char_remake {
320
self.char_remake = false;
321
// let mut encoder = self.device.create_command_encoder(&Default::default());
+1
-3
lightweight_viewer/src/render.rs
+1
-3
lightweight_viewer/src/render.rs
···
1
-
use crate::OVERLAY_REBECCA_PURPLE;
2
-
use crate::wgpu_color_to_vec4;
3
use glam::{Vec3, vec4};
4
use vfl::draw::render_3d::Rendered3dShape;
5
use vfl::draw::wgpu_render::texture;
···
15
shape: Shape,
16
color: usize,
17
position: Vec3,
18
-
projected_texture: Option<texture::Texture>,
19
) -> Rendered3dShape {
20
let mut vertices: Vec<Vertex> = vec![];
21
let tex_coords = d
···
1
use glam::{Vec3, vec4};
2
use vfl::draw::render_3d::Rendered3dShape;
3
use vfl::draw::wgpu_render::texture;
···
13
shape: Shape,
14
color: usize,
15
position: Vec3,
16
+
projected_texture: Option<texture::TextureBundle>,
17
) -> Rendered3dShape {
18
let mut vertices: Vec<Vertex> = vec![];
19
let tex_coords = d
+67
-18
vfl/src/draw/render_2d.rs
+67
-18
vfl/src/draw/render_2d.rs
···
3
use image::DynamicImage;
4
use nalgebra::Matrix4;
5
use wgpu::{
6
-
CommandEncoder, PipelineCompilationOptions, TexelCopyTextureInfo, TextureView, include_wgsl,
7
-
util::DeviceExt,
8
};
9
10
use crate::{
11
color::nx::{ModulationIntent, modulate},
12
-
res::tex::nx::ResourceTextureFormat,
13
};
14
15
use super::{
···
25
pub struct Rendered2dShape {
26
pub vertices: Vec<Vertex>,
27
pub indices: Vec<u32>,
28
-
pub tex: DynamicImage,
29
pub mvp_matrix: Matrix4<f32>,
30
pub modulation: ModulationIntent,
31
pub opaque: Option<Color>,
32
}
33
34
impl Rendered2dShape {
35
pub fn render_texture_trivial(
36
-
rendered_texture: DynamicImage,
37
modulation: ModulationIntent,
38
opaque: Option<Color>,
39
st: &mut impl ProgramState,
···
84
usage: wgpu::BufferUsages::INDEX,
85
});
86
87
-
let shape_texture_rgba = self.tex.to_rgba8();
88
-
let shape_texture_dimensions = shape_texture_rgba.dimensions();
89
let shape_texture_size = wgpu::Extent3d {
90
-
width: shape_texture_dimensions.0,
91
-
height: shape_texture_dimensions.1,
92
depth_or_array_layers: 1,
93
};
94
let shape_diffuse_texture = st.device().create_texture(&wgpu::TextureDescriptor {
···
96
mip_level_count: 1,
97
sample_count: 1,
98
dimension: wgpu::TextureDimension::D2,
99
-
format: st.surface_fmt().add_srgb_suffix(),
100
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
101
label: Some("diffuse_texture"),
102
-
view_formats: &[st.surface_fmt()],
103
});
104
105
st.queue().write_texture(
···
109
origin: wgpu::Origin3d::ZERO,
110
aspect: wgpu::TextureAspect::All,
111
},
112
-
&shape_texture_rgba,
113
-
wgpu::TexelCopyBufferLayout {
114
-
offset: 0,
115
-
bytes_per_row: Some(4 * shape_texture_dimensions.0),
116
-
rows_per_image: Some(shape_texture_dimensions.1),
117
-
},
118
shape_texture_size,
119
);
120
121
let shape_diffuse_texture_view =
122
-
shape_diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
123
let shape_diffuse_sampler = st.device().create_sampler(&wgpu::SamplerDescriptor {
124
address_mode_u: wgpu::AddressMode::ClampToEdge,
125
address_mode_v: wgpu::AddressMode::ClampToEdge,
···
3
use image::DynamicImage;
4
use nalgebra::Matrix4;
5
use wgpu::{
6
+
CommandEncoder, PipelineCompilationOptions, TexelCopyTextureInfo, TextureFormat, TextureView,
7
+
include_wgsl, util::DeviceExt,
8
};
9
10
use crate::{
11
color::nx::{ModulationIntent, modulate},
12
+
res::tex::nx::{RawTexture, ResourceTexture, ResourceTextureFormat, TextureElement},
13
};
14
15
use super::{
···
25
pub struct Rendered2dShape {
26
pub vertices: Vec<Vertex>,
27
pub indices: Vec<u32>,
28
+
pub tex: RawTexture,
29
pub mvp_matrix: Matrix4<f32>,
30
pub modulation: ModulationIntent,
31
pub opaque: Option<Color>,
32
}
33
34
+
pub fn texture_format_to_wgpu(tex: TextureElement) -> TextureFormat {
35
+
use TextureFormat as WgpuTextureFormat;
36
+
let format = ResourceTextureFormat::try_from(tex.texture.format).unwrap();
37
+
match format {
38
+
ResourceTextureFormat::R => WgpuTextureFormat::R8Unorm,
39
+
ResourceTextureFormat::Rg => WgpuTextureFormat::Rg8Unorm,
40
+
ResourceTextureFormat::Rgba => WgpuTextureFormat::Rgba8Unorm,
41
+
ResourceTextureFormat::Bc4 => WgpuTextureFormat::Bc4RUnorm,
42
+
ResourceTextureFormat::Bc5 => WgpuTextureFormat::Bc5RgUnorm,
43
+
ResourceTextureFormat::Bc7 => WgpuTextureFormat::Bc7RgbaUnorm,
44
+
ResourceTextureFormat::Astc4x4 => WgpuTextureFormat::Astc {
45
+
block: wgpu::AstcBlock::B4x4,
46
+
channel: wgpu::AstcChannel::Unorm,
47
+
},
48
+
}
49
+
}
50
+
51
+
pub fn texture_format_buffer_layout(tex: TextureElement) -> wgpu::TexelCopyBufferLayout {
52
+
use ResourceTextureFormat as Rtf;
53
+
const BC3_BYTES_PER_BLOCK: u32 = 16;
54
+
const BC3_PIXELS_PER_BLOCK: u32 = 4;
55
+
const BC4_BYTES_PER_BLOCK: u32 = 8;
56
+
57
+
let format = Rtf::try_from(tex.texture.format).unwrap();
58
+
59
+
match format {
60
+
Rtf::R => wgpu::TexelCopyBufferLayout {
61
+
offset: 0,
62
+
bytes_per_row: Some(u32::from(tex.texture.width)),
63
+
rows_per_image: None,
64
+
},
65
+
Rtf::Rg => wgpu::TexelCopyBufferLayout {
66
+
offset: 0,
67
+
bytes_per_row: Some(2 * u32::from(tex.texture.width)),
68
+
rows_per_image: None,
69
+
},
70
+
Rtf::Astc4x4 | Rtf::Bc7 | Rtf::Bc4 | Rtf::Rgba => wgpu::TexelCopyBufferLayout {
71
+
offset: 0,
72
+
bytes_per_row: Some((16 / 4) * u32::from(tex.texture.width)),
73
+
rows_per_image: None,
74
+
},
75
+
Rtf::Bc5 => wgpu::TexelCopyBufferLayout {
76
+
offset: 0,
77
+
bytes_per_row: Some((32 / 4) * u32::from(tex.texture.width)),
78
+
rows_per_image: None,
79
+
},
80
+
}
81
+
}
82
+
83
impl Rendered2dShape {
84
pub fn render_texture_trivial(
85
+
rendered_texture: RawTexture,
86
modulation: ModulationIntent,
87
opaque: Option<Color>,
88
st: &mut impl ProgramState,
···
133
usage: wgpu::BufferUsages::INDEX,
134
});
135
136
let shape_texture_size = wgpu::Extent3d {
137
+
width: u32::from(self.tex.metadata.texture.width),
138
+
height: u32::from(self.tex.metadata.texture.height),
139
depth_or_array_layers: 1,
140
};
141
let shape_diffuse_texture = st.device().create_texture(&wgpu::TextureDescriptor {
···
143
mip_level_count: 1,
144
sample_count: 1,
145
dimension: wgpu::TextureDimension::D2,
146
+
format: texture_format_to_wgpu(self.tex.metadata),
147
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
148
label: Some("diffuse_texture"),
149
+
view_formats: &[
150
+
texture_format_to_wgpu(self.tex.metadata),
151
+
texture_format_to_wgpu(self.tex.metadata).add_srgb_suffix(),
152
+
],
153
});
154
155
st.queue().write_texture(
···
159
origin: wgpu::Origin3d::ZERO,
160
aspect: wgpu::TextureAspect::All,
161
},
162
+
&self.tex.bytes,
163
+
texture_format_buffer_layout(self.tex.metadata),
164
shape_texture_size,
165
);
166
167
let shape_diffuse_texture_view =
168
+
shape_diffuse_texture.create_view(&wgpu::TextureViewDescriptor {
169
+
format: Some(texture_format_to_wgpu(self.tex.metadata)),
170
+
..Default::default()
171
+
});
172
let shape_diffuse_sampler = st.device().create_sampler(&wgpu::SamplerDescriptor {
173
address_mode_u: wgpu::AddressMode::ClampToEdge,
174
address_mode_v: wgpu::AddressMode::ClampToEdge,
+3
-3
vfl/src/draw/render_3d.rs
+3
-3
vfl/src/draw/render_3d.rs
···
21
fn camera_bgl(&self) -> &wgpu::BindGroupLayout;
22
fn camera_bg(&self) -> &wgpu::BindGroup;
23
fn surface_fmt(&self) -> wgpu::TextureFormat;
24
-
fn depth_texture(&self) -> &texture::Texture;
25
}
26
27
#[derive(Default, Debug)]
···
29
pub vertices: Vec<Vertex>,
30
pub indices: Vec<u32>,
31
pub color: Vec4,
32
-
pub texture: Option<crate::draw::wgpu_render::texture::Texture>,
33
pub position: Vec3,
34
}
35
···
190
conservative: false,
191
},
192
depth_stencil: Some(wgpu::DepthStencilState {
193
-
format: texture::Texture::DEPTH_FORMAT,
194
depth_write_enabled: true,
195
depth_compare: wgpu::CompareFunction::Less, // 1.
196
stencil: wgpu::StencilState::default(), // 2.
···
21
fn camera_bgl(&self) -> &wgpu::BindGroupLayout;
22
fn camera_bg(&self) -> &wgpu::BindGroup;
23
fn surface_fmt(&self) -> wgpu::TextureFormat;
24
+
fn depth_texture(&self) -> &texture::TextureBundle;
25
}
26
27
#[derive(Default, Debug)]
···
29
pub vertices: Vec<Vertex>,
30
pub indices: Vec<u32>,
31
pub color: Vec4,
32
+
pub texture: Option<crate::draw::wgpu_render::texture::TextureBundle>,
33
pub position: Vec3,
34
}
35
···
190
conservative: false,
191
},
192
depth_stencil: Some(wgpu::DepthStencilState {
193
+
format: texture::TextureBundle::DEPTH_FORMAT,
194
depth_write_enabled: true,
195
depth_compare: wgpu::CompareFunction::Less, // 1.
196
stencil: wgpu::StencilState::default(), // 2.
+16
-12
vfl/src/draw/shader.wgsl
+16
-12
vfl/src/draw/shader.wgsl
···
52
// AlphaTexture = 3,
53
// LuminanceAlphaTexture = 4,
54
// }
55
-
56
if mvp.modulation_mode == 0 {
57
return modulate_single_color(color);
58
-
} else if mvp.modulation_mode == 1 {
59
-
return modulate_direct_texture(color);
60
-
} else if mvp.modulation_mode == 2 {
61
-
return modulate_rgba(color);
62
-
} else if mvp.modulation_mode == 3 {
63
-
return modulate_alpha(color);
64
-
} else if mvp.modulation_mode == 4 {
65
-
return modulate_lum_alpha(color);
66
-
} else {
67
-
// OOB access, return RebeccaPurple
68
-
return vec4f(0.4, 0.2, 0.6, 1.0);
69
}
70
}
71
72
// Two trivial cases
···
52
// AlphaTexture = 3,
53
// LuminanceAlphaTexture = 4,
54
// }
55
if mvp.modulation_mode == 0 {
56
return modulate_single_color(color);
57
}
58
+
return color;
59
+
60
+
// if mvp.modulation_mode == 0 {
61
+
// return modulate_single_color(color);
62
+
// } else if mvp.modulation_mode == 1 {
63
+
// return modulate_direct_texture(color);
64
+
// } else if mvp.modulation_mode == 2 {
65
+
// return modulate_rgba(color);
66
+
// } else if mvp.modulation_mode == 3 {
67
+
// return modulate_alpha(color);
68
+
// } else if mvp.modulation_mode == 4 {
69
+
// return modulate_lum_alpha(color);
70
+
// } else {
71
+
// // OOB access, return RebeccaPurple
72
+
// return vec4f(0.4, 0.2, 0.6, 1.0);
73
+
// }
74
}
75
76
// Two trivial cases
+21
-349
vfl/src/draw/wgpu_render.rs
+21
-349
vfl/src/draw/wgpu_render.rs
···
113
256.0,
114
);
115
116
-
let tex = tex_data.get_image(file_texture).unwrap().unwrap();
117
118
Rendered2dShape {
119
vertices,
120
indices,
121
-
tex: image::DynamicImage::ImageRgba8(tex),
122
mvp_matrix: mtx,
123
modulation: modulate(modulated, char),
124
opaque: None,
···
181
256.0,
182
);
183
184
-
let tex = tex_data.get_image(file_texture).unwrap().unwrap();
185
186
Rendered2dShape {
187
vertices,
188
indices,
189
-
tex: image::DynamicImage::ImageRgba8(tex),
190
mvp_matrix: mtx,
191
modulation: modulate(modulated, char),
192
opaque: None,
···
231
256.0,
232
);
233
234
-
let tex = tex_data.get_image(file_texture)?.unwrap();
235
236
let glass_l_render_shape = Rendered2dShape {
237
vertices,
238
indices,
239
-
tex: image::DynamicImage::ImageRgba8(tex.clone()),
240
mvp_matrix: mtx,
241
modulation: modulate(ColorModulated::Glass, &char),
242
opaque: None,
···
257
let glass_r_render_shape = Rendered2dShape {
258
vertices,
259
indices,
260
-
tex: image::DynamicImage::ImageRgba8(tex),
261
mvp_matrix: mtx,
262
modulation: modulate(ColorModulated::Glass, &char),
263
opaque: None,
···
378
camera_bgl: wgpu::BindGroupLayout,
379
camera_bg: wgpu::BindGroup,
380
surface_fmt: wgpu::TextureFormat,
381
-
depth_texture: texture::Texture,
382
}
383
384
impl ProgramState for HeadlessRenderer {
···
402
self.surface_fmt
403
}
404
405
-
fn depth_texture(&self) -> &texture::Texture {
406
&self.depth_texture
407
}
408
}
···
440
// let surface_fmt = cap.formats[0];
441
let surface_fmt = wgpu::TextureFormat::Bgra8Unorm;
442
443
-
let depth_texture = texture::Texture::create_depth_texture(&device, &SIZE, "depth_texture");
444
445
let camera = Camera {
446
eye: (0.0, 25.0, 100.0).into(),
···
496
497
pub fn output_texture(
498
&mut self,
499
-
texture: &texture::Texture,
500
mut encoder: CommandEncoder,
501
) -> DynamicImage {
502
pollster::block_on(async {
···
567
}
568
}
569
570
-
#[deprecated]
571
-
#[allow(clippy::too_many_lines)]
572
-
pub async fn render_context_wgpu(render_context: RenderContext) -> DynamicImage {
573
-
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
574
-
backends: wgpu::Backends::all(),
575
-
..Default::default()
576
-
});
577
-
let adapter = instance
578
-
.request_adapter(&wgpu::RequestAdapterOptions {
579
-
power_preference: wgpu::PowerPreference::default(),
580
-
compatible_surface: None,
581
-
force_fallback_adapter: false,
582
-
})
583
-
.await
584
-
.unwrap();
585
-
let (device, queue) = adapter
586
-
.request_device(&DeviceDescriptor::default())
587
-
.await
588
-
.unwrap();
589
-
590
-
let texture_desc = wgpu::TextureDescriptor {
591
-
size: wgpu::Extent3d {
592
-
width: render_context.size.x,
593
-
height: render_context.size.y,
594
-
depth_or_array_layers: 1,
595
-
},
596
-
mip_level_count: 1,
597
-
sample_count: 1,
598
-
dimension: wgpu::TextureDimension::D2,
599
-
format: wgpu::TextureFormat::Rgba8UnormSrgb,
600
-
usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT,
601
-
label: None,
602
-
view_formats: &[wgpu::TextureFormat::Rgba8UnormSrgb],
603
-
};
604
-
let texture = device.create_texture(&texture_desc);
605
-
let texture_view = texture.create_view(&Default::default());
606
-
let u32_size = std::mem::size_of::<u32>() as u32;
607
-
let output_buffer_size =
608
-
wgpu::BufferAddress::from(u32_size * render_context.size.x * render_context.size.y);
609
-
let output_buffer_desc = wgpu::BufferDescriptor {
610
-
size: output_buffer_size,
611
-
usage: wgpu::BufferUsages::COPY_DST
612
-
// this tells wpgu that we want to read this buffer from the cpu
613
-
| wgpu::BufferUsages::MAP_READ,
614
-
label: None,
615
-
mapped_at_creation: false,
616
-
};
617
-
let output_buffer = device.create_buffer(&output_buffer_desc);
618
-
619
-
let mut encoder =
620
-
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
621
-
622
-
for shape in render_context.shape {
623
-
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
624
-
label: Some("Vertex Buffer"),
625
-
contents: bytemuck::cast_slice(&shape.vertices),
626
-
usage: wgpu::BufferUsages::VERTEX,
627
-
});
628
-
629
-
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
630
-
label: Some("Index Buffer"),
631
-
contents: bytemuck::cast_slice(&shape.indices),
632
-
usage: wgpu::BufferUsages::INDEX,
633
-
});
634
-
635
-
let shape_texture_rgba = shape.tex.to_rgba8();
636
-
let shape_texture_dimensions = shape_texture_rgba.dimensions();
637
-
let shape_texture_size = wgpu::Extent3d {
638
-
width: shape_texture_dimensions.0,
639
-
height: shape_texture_dimensions.1,
640
-
// All textures are stored as 3D, we represent our 2D texture
641
-
// by setting depth to 1.
642
-
depth_or_array_layers: 1,
643
-
};
644
-
let shape_diffuse_texture = device.create_texture(&wgpu::TextureDescriptor {
645
-
size: shape_texture_size,
646
-
mip_level_count: 1, // We'll talk about this a little later
647
-
sample_count: 1,
648
-
dimension: wgpu::TextureDimension::D2,
649
-
// Most images are stored using sRGB, so we need to reflect that here.
650
-
format: wgpu::TextureFormat::Rgba8UnormSrgb,
651
-
// TEXTURE_BINDING tells wgpu that we want to use this texture in shaders
652
-
// COPY_DST means that we want to copy data to this texture
653
-
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
654
-
label: Some("diffuse_texture"),
655
-
// This is the same as with the SurfaceConfig. It
656
-
// specifies what texture formats can be used to
657
-
// create TextureViews for this texture. The base
658
-
// texture format (Rgba8UnormSrgb in this case) is
659
-
// always supported. Note that using a different
660
-
// texture format is not supported on the WebGL2
661
-
// backend.
662
-
view_formats: &[],
663
-
});
664
-
665
-
queue.write_texture(
666
-
TexelCopyTextureInfo {
667
-
texture: &shape_diffuse_texture,
668
-
mip_level: 0,
669
-
origin: wgpu::Origin3d::ZERO,
670
-
aspect: wgpu::TextureAspect::All,
671
-
},
672
-
&shape_texture_rgba,
673
-
wgpu::TexelCopyBufferLayout {
674
-
offset: 0,
675
-
bytes_per_row: Some(4 * shape_texture_dimensions.0),
676
-
rows_per_image: Some(shape_texture_dimensions.1),
677
-
},
678
-
shape_texture_size,
679
-
);
680
-
681
-
let shape_diffuse_texture_view =
682
-
shape_diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default());
683
-
let shape_diffuse_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
684
-
address_mode_u: wgpu::AddressMode::ClampToEdge,
685
-
address_mode_v: wgpu::AddressMode::ClampToEdge,
686
-
address_mode_w: wgpu::AddressMode::ClampToEdge,
687
-
mag_filter: wgpu::FilterMode::Linear,
688
-
min_filter: wgpu::FilterMode::Nearest,
689
-
mipmap_filter: wgpu::FilterMode::Nearest,
690
-
..Default::default()
691
-
});
692
-
693
-
let texture_bind_group_layout =
694
-
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
695
-
entries: &[
696
-
wgpu::BindGroupLayoutEntry {
697
-
binding: 0,
698
-
visibility: wgpu::ShaderStages::FRAGMENT,
699
-
ty: wgpu::BindingType::Texture {
700
-
multisampled: false,
701
-
view_dimension: wgpu::TextureViewDimension::D2,
702
-
sample_type: wgpu::TextureSampleType::Float { filterable: true },
703
-
},
704
-
count: None,
705
-
},
706
-
wgpu::BindGroupLayoutEntry {
707
-
binding: 1,
708
-
visibility: wgpu::ShaderStages::FRAGMENT,
709
-
// This should match the filterable field of the
710
-
// corresponding Texture entry above.
711
-
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
712
-
count: None,
713
-
},
714
-
],
715
-
label: Some("texture_bind_group_layout"),
716
-
});
717
-
718
-
let shape_diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
719
-
layout: &texture_bind_group_layout,
720
-
entries: &[
721
-
wgpu::BindGroupEntry {
722
-
binding: 0,
723
-
resource: wgpu::BindingResource::TextureView(&shape_diffuse_texture_view),
724
-
},
725
-
wgpu::BindGroupEntry {
726
-
binding: 1,
727
-
resource: wgpu::BindingResource::Sampler(&shape_diffuse_sampler),
728
-
},
729
-
],
730
-
label: Some("diffuse_bind_group"),
731
-
});
732
-
733
-
let mvp_matrix = shape.mvp_matrix.into();
734
-
let mvp_uniform = TextureTransformUniform {
735
-
mvp_matrix,
736
-
channel_replacements_r: shape.modulation.channels[0],
737
-
channel_replacements_g: shape.modulation.channels[1],
738
-
channel_replacements_b: shape.modulation.channels[2],
739
-
texture_type: (Into::<u8>::into(shape.modulation.mode)).into(),
740
-
pad: Default::default(),
741
-
};
742
-
743
-
let mvp_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
744
-
label: Some("MvpMatrix Buffer"),
745
-
contents: bytemuck::cast_slice(&[mvp_uniform]),
746
-
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
747
-
});
748
-
749
-
let mvp_bind_group_layout =
750
-
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
751
-
entries: &[wgpu::BindGroupLayoutEntry {
752
-
binding: 0,
753
-
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
754
-
ty: wgpu::BindingType::Buffer {
755
-
ty: wgpu::BufferBindingType::Uniform,
756
-
has_dynamic_offset: false,
757
-
min_binding_size: None,
758
-
},
759
-
count: None,
760
-
}],
761
-
label: Some("mvp_bind_group_layout"),
762
-
});
763
-
764
-
let mvp_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
765
-
layout: &mvp_bind_group_layout,
766
-
entries: &[wgpu::BindGroupEntry {
767
-
binding: 0,
768
-
resource: mvp_buffer.as_entire_binding(),
769
-
}],
770
-
label: Some("mvp_bind_group"),
771
-
});
772
-
773
-
let shader = wgpu::ShaderSource::Wgsl(SHADER.into());
774
-
let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
775
-
label: Some("Shader"),
776
-
source: shader,
777
-
});
778
-
let render_pipeline_layout =
779
-
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
780
-
label: Some("Render Pipeline Layout"),
781
-
bind_group_layouts: &[&texture_bind_group_layout, &mvp_bind_group_layout],
782
-
push_constant_ranges: &[],
783
-
});
784
-
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
785
-
label: Some("Render Pipeline"),
786
-
layout: Some(&render_pipeline_layout),
787
-
vertex: wgpu::VertexState {
788
-
module: &shader_module,
789
-
entry_point: Some("vs_main"),
790
-
buffers: &[Vertex::desc()],
791
-
compilation_options: Default::default(),
792
-
},
793
-
fragment: Some(wgpu::FragmentState {
794
-
module: &shader_module,
795
-
entry_point: Some("fs_main"),
796
-
targets: &[Some(wgpu::ColorTargetState {
797
-
format: texture_desc.format,
798
-
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
799
-
write_mask: wgpu::ColorWrites::ALL,
800
-
})],
801
-
compilation_options: Default::default(),
802
-
}),
803
-
primitive: wgpu::PrimitiveState {
804
-
topology: wgpu::PrimitiveTopology::TriangleList,
805
-
strip_index_format: None,
806
-
front_face: wgpu::FrontFace::Ccw,
807
-
cull_mode: Some(wgpu::Face::Back),
808
-
// Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
809
-
polygon_mode: wgpu::PolygonMode::Fill,
810
-
// Requires Features::DEPTH_CLIP_CONTROL
811
-
unclipped_depth: false,
812
-
// Requires Features::CONSERVATIVE_RASTERIZATION
813
-
conservative: false,
814
-
},
815
-
depth_stencil: None,
816
-
multisample: wgpu::MultisampleState {
817
-
count: 1,
818
-
mask: !0,
819
-
alpha_to_coverage_enabled: false,
820
-
},
821
-
// If the pipeline will be used with a multiview render pass, this
822
-
// indicates how many array layers the attachments will have.
823
-
multiview: None,
824
-
cache: None,
825
-
});
826
-
827
-
{
828
-
let render_pass_desc = wgpu::RenderPassDescriptor {
829
-
label: Some("Render Pass"),
830
-
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
831
-
view: &texture_view,
832
-
resolve_target: None,
833
-
ops: wgpu::Operations {
834
-
load: wgpu::LoadOp::Load,
835
-
store: wgpu::StoreOp::Store,
836
-
},
837
-
})],
838
-
depth_stencil_attachment: None,
839
-
occlusion_query_set: None,
840
-
timestamp_writes: None,
841
-
};
842
-
let mut render_pass = encoder.begin_render_pass(&render_pass_desc);
843
-
844
-
render_pass.set_pipeline(&render_pipeline);
845
-
render_pass.set_bind_group(0, &shape_diffuse_bind_group, &[]);
846
-
render_pass.set_bind_group(1, &mvp_bind_group, &[]);
847
-
render_pass.set_vertex_buffer(0, vertex_buffer.slice(..));
848
-
render_pass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint32);
849
-
850
-
render_pass.draw_indexed(0..shape.indices.len() as u32, 0, 0..1);
851
-
}
852
-
}
853
-
encoder.copy_texture_to_buffer(
854
-
wgpu::TexelCopyTextureInfo {
855
-
aspect: wgpu::TextureAspect::All,
856
-
texture: &texture,
857
-
mip_level: 0,
858
-
origin: wgpu::Origin3d::ZERO,
859
-
},
860
-
wgpu::TexelCopyBufferInfo {
861
-
buffer: &output_buffer,
862
-
layout: wgpu::TexelCopyBufferLayout {
863
-
offset: 0,
864
-
bytes_per_row: Some(u32_size * render_context.size.x),
865
-
rows_per_image: Some(render_context.size.x),
866
-
},
867
-
},
868
-
texture_desc.size,
869
-
);
870
-
871
-
queue.submit(Some(encoder.finish()));
872
-
873
-
let mut image = None;
874
-
// We need to scope the mapping variables so that we can
875
-
// unmap the buffer
876
-
{
877
-
let buffer_slice = output_buffer.slice(..);
878
-
879
-
// NOTE: We have to create the mapping THEN device.poll() before await
880
-
// the future. Otherwise the application will freeze.
881
-
let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel();
882
-
buffer_slice.map_async(wgpu::MapMode::Read, move |result| {
883
-
tx.send(result).unwrap();
884
-
});
885
-
device.poll(wgpu::PollType::Wait).unwrap();
886
-
rx.receive().await.unwrap().unwrap();
887
-
888
-
let data = &buffer_slice.get_mapped_range()[..];
889
-
890
-
use image::{ImageBuffer, Rgba};
891
-
let buffer: RgbaImage = ImageBuffer::<Rgba<u8>, _>::from_raw(
892
-
render_context.size.x,
893
-
render_context.size.y,
894
-
data.to_owned(),
895
-
)
896
-
.unwrap();
897
-
// buffer.save("image.png").unwrap();
898
-
image = Some(DynamicImage::ImageRgba8(buffer));
899
-
}
900
-
output_buffer.unmap();
901
-
902
-
image.unwrap()
903
-
}
904
-
905
pub mod texture {
906
use std::error::Error;
907
use std::fmt::Debug;
···
910
use image::GenericImageView;
911
use wgpu::TextureFormat;
912
913
-
pub struct Texture {
914
#[allow(unused)]
915
pub texture: wgpu::Texture,
916
pub view: wgpu::TextureView,
917
pub sampler: wgpu::Sampler,
918
}
919
-
impl Debug for Texture {
920
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
921
f.debug_struct("Texture").finish()
922
}
923
}
924
925
#[allow(unused)]
926
-
impl Texture {
927
pub fn from_bytes(
928
device: &wgpu::Device,
929
queue: &wgpu::Queue,
···
113
256.0,
114
);
115
116
+
let tex = tex_data
117
+
.get_uncompressed_bytes(file_texture)
118
+
.unwrap()
119
+
.unwrap();
120
121
Rendered2dShape {
122
vertices,
123
indices,
124
+
tex,
125
mvp_matrix: mtx,
126
modulation: modulate(modulated, char),
127
opaque: None,
···
184
256.0,
185
);
186
187
+
let tex = tex_data
188
+
.get_uncompressed_bytes(file_texture)
189
+
.unwrap()
190
+
.unwrap();
191
192
Rendered2dShape {
193
vertices,
194
indices,
195
+
tex,
196
mvp_matrix: mtx,
197
modulation: modulate(modulated, char),
198
opaque: None,
···
237
256.0,
238
);
239
240
+
let tex = tex_data.get_uncompressed_bytes(file_texture)?.unwrap();
241
242
let glass_l_render_shape = Rendered2dShape {
243
vertices,
244
indices,
245
+
tex: tex.clone(),
246
mvp_matrix: mtx,
247
modulation: modulate(ColorModulated::Glass, &char),
248
opaque: None,
···
263
let glass_r_render_shape = Rendered2dShape {
264
vertices,
265
indices,
266
+
tex,
267
mvp_matrix: mtx,
268
modulation: modulate(ColorModulated::Glass, &char),
269
opaque: None,
···
384
camera_bgl: wgpu::BindGroupLayout,
385
camera_bg: wgpu::BindGroup,
386
surface_fmt: wgpu::TextureFormat,
387
+
depth_texture: texture::TextureBundle,
388
}
389
390
impl ProgramState for HeadlessRenderer {
···
408
self.surface_fmt
409
}
410
411
+
fn depth_texture(&self) -> &texture::TextureBundle {
412
&self.depth_texture
413
}
414
}
···
446
// let surface_fmt = cap.formats[0];
447
let surface_fmt = wgpu::TextureFormat::Bgra8Unorm;
448
449
+
let depth_texture =
450
+
texture::TextureBundle::create_depth_texture(&device, &SIZE, "depth_texture");
451
452
let camera = Camera {
453
eye: (0.0, 25.0, 100.0).into(),
···
503
504
pub fn output_texture(
505
&mut self,
506
+
texture: &texture::TextureBundle,
507
mut encoder: CommandEncoder,
508
) -> DynamicImage {
509
pollster::block_on(async {
···
574
}
575
}
576
577
pub mod texture {
578
use std::error::Error;
579
use std::fmt::Debug;
···
582
use image::GenericImageView;
583
use wgpu::TextureFormat;
584
585
+
pub struct TextureBundle {
586
#[allow(unused)]
587
pub texture: wgpu::Texture,
588
pub view: wgpu::TextureView,
589
pub sampler: wgpu::Sampler,
590
}
591
+
impl Debug for TextureBundle {
592
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
593
f.debug_struct("Texture").finish()
594
}
595
}
596
597
#[allow(unused)]
598
+
impl TextureBundle {
599
pub fn from_bytes(
600
device: &wgpu::Device,
601
queue: &wgpu::Queue,
+27
-8
vfl/src/res/tex/nx.rs
+27
-8
vfl/src/res/tex/nx.rs
···
34
#[repr(u8)]
35
pub enum ResourceTextureFormat {
36
R = 0, // R8Unorm (Ffl Name)
37
-
Rb = 1, // R8B8Unorm
38
-
Rgba = 2, // R8B8G8A8Unorm
39
Bc4 = 3, // Bc4Unorm (Compressed R)
40
Bc5 = 4, // Bc5Unorm (Compressed Rb)
41
Bc7 = 5, // Bc7Unorm (Compressed Rgba)
42
Astc4x4 = 6, // Astc4x4Unorm (Compressed Rgba)
43
}
44
45
impl TextureElement {
46
pub fn get_texture_bytes(&self, file: &Vec<u8>) -> Result<Vec<u8>, Box<dyn Error>> {
47
let start: usize = self.common.offset as usize;
···
64
let tex_data = if needs_swizzling {
65
let block_size = match ResourceTextureFormat::try_from(self.texture.format).unwrap() {
66
ResourceTextureFormat::R
67
-
| ResourceTextureFormat::Rb
68
| ResourceTextureFormat::Rgba => 1,
69
ResourceTextureFormat::Bc4
70
| ResourceTextureFormat::Bc5
···
75
let bytes_per_pixel =
76
match ResourceTextureFormat::try_from(self.texture.format).unwrap() {
77
ResourceTextureFormat::R
78
-
| ResourceTextureFormat::Rb
79
| ResourceTextureFormat::Rgba => 1,
80
ResourceTextureFormat::Bc4 => 8,
81
ResourceTextureFormat::Bc5
···
106
pub fn get_uncompressed_bytes(
107
&self,
108
file: &Vec<u8>,
109
-
) -> Result<Option<Vec<u8>>, Box<dyn Error>> {
110
let normalize_textures = false;
111
112
if self.texture.width == 0 || self.texture.height == 0 {
···
191
})
192
.collect();
193
194
-
Ok(Some(tex_data_decoded))
195
}
196
197
#[cfg(feature = "draw")]
198
pub fn get_image(&self, bytes: &Vec<u8>) -> Result<Option<RgbaImage>, Box<dyn Error>> {
199
-
let bytes = match self.get_uncompressed_bytes(bytes) {
200
Ok(Some(bytes)) => bytes,
201
Ok(None) => return Ok(None),
202
Err(e) => return Err(e),
···
205
let img: ImageBuffer<Rgba<u8>, Vec<u8>> = image::RgbaImage::from_raw(
206
self.texture.width.into(),
207
self.texture.height.into(),
208
-
bytes,
209
)
210
.unwrap();
211
···
34
#[repr(u8)]
35
pub enum ResourceTextureFormat {
36
R = 0, // R8Unorm (Ffl Name)
37
+
Rg = 1, // R8G8Unorm
38
+
Rgba = 2, // R8G8B8A8Unorm
39
Bc4 = 3, // Bc4Unorm (Compressed R)
40
Bc5 = 4, // Bc5Unorm (Compressed Rb)
41
Bc7 = 5, // Bc7Unorm (Compressed Rgba)
42
Astc4x4 = 6, // Astc4x4Unorm (Compressed Rgba)
43
}
44
45
+
// pub enum RawTexture {
46
+
// R(Vec<u8>),
47
+
// Rb(Vec<u8>),
48
+
// Rgba(Vec<u8>),
49
+
// Bc4(Vec<u8>),
50
+
// Bc5(Vec<u8>),
51
+
// Bc7(Vec<u8>),
52
+
// Astc4x4(Vec<u8>),
53
+
// }
54
+
55
+
#[derive(Clone, Debug)]
56
+
pub struct RawTexture {
57
+
pub bytes: Vec<u8>,
58
+
pub metadata: TextureElement,
59
+
}
60
+
61
impl TextureElement {
62
pub fn get_texture_bytes(&self, file: &Vec<u8>) -> Result<Vec<u8>, Box<dyn Error>> {
63
let start: usize = self.common.offset as usize;
···
80
let tex_data = if needs_swizzling {
81
let block_size = match ResourceTextureFormat::try_from(self.texture.format).unwrap() {
82
ResourceTextureFormat::R
83
+
| ResourceTextureFormat::Rg
84
| ResourceTextureFormat::Rgba => 1,
85
ResourceTextureFormat::Bc4
86
| ResourceTextureFormat::Bc5
···
91
let bytes_per_pixel =
92
match ResourceTextureFormat::try_from(self.texture.format).unwrap() {
93
ResourceTextureFormat::R
94
+
| ResourceTextureFormat::Rg
95
| ResourceTextureFormat::Rgba => 1,
96
ResourceTextureFormat::Bc4 => 8,
97
ResourceTextureFormat::Bc5
···
122
pub fn get_uncompressed_bytes(
123
&self,
124
file: &Vec<u8>,
125
+
) -> Result<Option<RawTexture>, Box<dyn Error>> {
126
let normalize_textures = false;
127
128
if self.texture.width == 0 || self.texture.height == 0 {
···
207
})
208
.collect();
209
210
+
Ok(Some(RawTexture {
211
+
bytes: tex_data_decoded,
212
+
metadata: self.clone(),
213
+
}))
214
}
215
216
#[cfg(feature = "draw")]
217
pub fn get_image(&self, bytes: &Vec<u8>) -> Result<Option<RgbaImage>, Box<dyn Error>> {
218
+
let raw_texture = match self.get_uncompressed_bytes(bytes) {
219
Ok(Some(bytes)) => bytes,
220
Ok(None) => return Ok(None),
221
Err(e) => return Err(e),
···
224
let img: ImageBuffer<Rgba<u8>, Vec<u8>> = image::RgbaImage::from_raw(
225
self.texture.width.into(),
226
self.texture.height.into(),
227
+
raw_texture.bytes,
228
)
229
.unwrap();
230