Added proper texture scaling

This commit is contained in:
Steins7 2022-08-20 19:51:21 +02:00
parent 7a46eff82c
commit 2591b60a5d
4 changed files with 66 additions and 31 deletions

View File

@ -63,11 +63,11 @@ impl Application<ExampleState> for ExampleApp {
//// 20 x 20 sprite of a picture //// 20 x 20 sprite of a picture
let texture = canvas.create_texture_from_file("assets/camel.jpg", None, None, None) let texture = canvas.create_texture_from_file("assets/camel.jpg", None, None, None)
.unwrap(); .unwrap();
let mut tex_sprite = canvas.create_texture_sprite(Size {w: 200, h: 200}); let mut tex_sprite = canvas.create_texture_sprite(Size {w: 1280, h: 720});
tex_sprite.set_texture(texture.clone(), Some(Position {x: 0, y: 0})); tex_sprite.set_texture(texture.clone(), Some(Position {x: 0, y: 0}), 1.0);
let mut sub_sprite = canvas.create_texture_sprite(Size {w: 350, h: 427}); let mut sub_sprite = canvas.create_texture_sprite(Size {w: 200, h: 200});
sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0})); sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}), 1.0);
canvas.clear(); canvas.clear();
canvas.update(); canvas.update();
@ -103,11 +103,12 @@ impl Application<ExampleState> for ExampleApp {
state.last_offset += 1; state.last_offset += 1;
state.last_pos.x += 1; state.last_pos.x += 1;
state.last_rot += 1.0; state.last_rot += 1.0;
state.tex_sprite.set_texture(state.texture.clone(), None, state.last_rot/100.0);
state.sub_sprite.set_texture(state.texture.clone(), state.sub_sprite.set_texture(state.texture.clone(),
Some(Position {x: state.last_offset, y: 0})); Some(Position {x: state.last_offset, y: 0}), 1.0);
//state.sub_sprite.set_position(state.last_pos); state.sub_sprite.set_position(state.last_pos);
state.sub_sprite.set_rotation(state.last_rot); state.sub_sprite.set_rotation(state.last_rot);
state.sub_sprite.set_scale(state.last_rot/1000.0); //state.sub_sprite.set_scale(state.last_rot/1000.0);
// inputs // inputs
//if canvas.key_pressed(Key::A) { //if canvas.key_pressed(Key::A) {

View File

@ -82,7 +82,9 @@ impl WgpuRenderer {
surface.configure(&device, &config); surface.configure(&device, &config);
let surface_size = size; let surface_size = size;
let aspect_matrix = Matrix3::from_nonuniform_scale(size.h as f32 / size.w as f32, 1.0); let aspect_matrix
= Matrix3::from_nonuniform_scale(1.0 / size.w as f32, 1.0 / size.h as f32);
let output = Some(surface.get_current_texture() let output = Some(surface.get_current_texture()
.map_err(|_| "Failed to create SurfaceTexture")?); .map_err(|_| "Failed to create SurfaceTexture")?);
@ -320,10 +322,7 @@ impl WgpuRenderer {
render_pass.set_push_constants( render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX, wgpu::ShaderStages::VERTEX,
0, 0,
bytemuck::bytes_of(&( bytemuck::bytes_of(&(self.aspect_matrix * matrix.get_matrix()))
self.aspect_matrix
* matrix.compute_matrix(self.surface_size)
))
); );
render_pass.draw_indexed(0..gpu_mesh.index_number, 0, 0..1); render_pass.draw_indexed(0..gpu_mesh.index_number, 0, 0..1);
@ -374,7 +373,8 @@ impl WgpuRenderer {
} }
self.surface_size = size; self.surface_size = size;
self.aspect_matrix = Matrix3::from_nonuniform_scale(size.h as f32 / size.w as f32, 1.0); self.aspect_matrix
= Matrix3::from_nonuniform_scale(1.0 / size.w as f32, 1.0 / size.h as f32);
self.config.width = size.w; self.config.width = size.w;
self.config.height = size.h; self.config.height = size.h;
self.surface.configure(&self.device, &self.config); self.surface.configure(&self.device, &self.config);
@ -433,7 +433,8 @@ where
mapped_at_creation: false, mapped_at_creation: false,
} }
); );
let index_buffer = device.create_buffer( &wgpu_types::BufferDescriptor {
let index_buffer = device.create_buffer( &wgpu_types::BufferDescriptor {
label: Some("Index Buffer"), label: Some("Index Buffer"),
size: (I_NB * size_of::<u16>()) as u64, size: (I_NB * size_of::<u16>()) as u64,
usage: Usages::INDEX.union(Usages::COPY_DST), usage: Usages::INDEX.union(Usages::COPY_DST),

View File

@ -5,7 +5,7 @@ use crate::{
renderer::{Mesh, GpuMesh, RenderData, TextureVertex}, renderer::{Mesh, GpuMesh, RenderData, TextureVertex},
shape::Shape, shape::Shape,
texture::Texture, texture::Texture,
utils::{Pixel, Position, Size}, utils::{Pixel, Position, Size, NormalizedSize},
}; };
use cgmath::{ use cgmath::{
@ -75,14 +75,14 @@ impl ModelMatrix {
self.is_synced = false; self.is_synced = false;
} }
pub fn compute_matrix(&mut self, size: Size) -> Matrix3<f32> { pub fn get_matrix(&mut self) -> Matrix3<f32> {
use cgmath::{Basis3, Rotation3, SquareMatrix}; use cgmath::{Basis3, Rotation3, SquareMatrix};
if self.is_synced == false { if self.is_synced == false {
let pos_vec = Vector2 { let pos_vec = Vector2 {
x: self.position.x as f32 / size.w as f32, x: self.position.x as f32,
y: self.position.y as f32 / size.h as f32, y: self.position.y as f32,
}; };
let rotation_mat = Matrix3::from(Basis3::from_angle_z(self.rotation)); let rotation_mat = Matrix3::from(Basis3::from_angle_z(self.rotation));
let scale_mat = Matrix3::from_scale(self.scale); let scale_mat = Matrix3::from_scale(self.scale);
@ -100,54 +100,68 @@ impl ModelMatrix {
pub struct TextureSprite { pub struct TextureSprite {
matrix: ModelMatrix, matrix: ModelMatrix,
gpu_mesh: GpuMesh<TextureVertex, 4, 6>, gpu_mesh: GpuMesh<TextureVertex, 4, 6>,
inner_size: Size, //TODO move to f32
texture: Texture, texture: Texture,
texture_offset: Position, texture_offset: Position,
texture_size: Size, texture_scale: f32,
} }
impl TextureSprite { impl TextureSprite {
pub fn create(texture: Texture, size: Size, gpu_mesh: GpuMesh<TextureVertex, 4, 6>) -> Self { pub fn create(texture: Texture, size: Size, gpu_mesh: GpuMesh<TextureVertex, 4, 6>) -> Self {
Self { let mut sprite = Self {
matrix: ModelMatrix::default(), matrix: ModelMatrix::default(),
gpu_mesh, gpu_mesh,
texture, inner_size: size,
texture: texture.clone(),
texture_offset: Position::origin(), texture_offset: Position::origin(),
texture_size: size, texture_scale: 1.0,
} };
//generate proper mesh
//TODO improve that
sprite.set_texture(texture, None, 1.0);
sprite
} }
pub fn set_texture(&mut self, texture: Texture, offset: Option<Position>) { pub fn set_texture(&mut self, texture: Texture, offset: Option<Position>, scale: f32) {
// update texture // update texture
self.texture = texture; self.texture = texture;
self.texture_scale = scale;
let size = self.texture.get_size(); let size = self.texture.get_size();
// compute normalized coordinates // compute normalized coordinates
self.texture_offset = offset.unwrap_or(Position::origin()); self.texture_offset = offset.unwrap_or(Position::origin());
let x_size = self.texture_size.w as f32 / size.w as f32; let x_size = self.inner_size.w as f32 / size.w as f32 * scale;
let y_size = self.texture_size.h as f32 / size.h as f32; let y_size = self.inner_size.h as f32 / size.h as f32 * scale;
let x_offset = self.texture_offset.x as f32 / size.w as f32; let x_offset = self.texture_offset.x as f32 / size.w as f32;
let y_offset = self.texture_offset.y as f32 / size.h as f32; let y_offset = self.texture_offset.y as f32 / size.h as f32;
// compute mesh size
let w = self.inner_size.w as f32;
let h = self.inner_size.h as f32;
// generate new sprite mesh // generate new sprite mesh
let mesh = Mesh { let mesh = Mesh {
vertices: [ vertices: [
TextureVertex { TextureVertex {
position: [-0.5, -0.5], position: [-w, -h],
tex_coords: [x_offset , y_offset + y_size], tex_coords: [x_offset , y_offset + y_size],
}, },
TextureVertex { TextureVertex {
position: [ 0.5, -0.5], position: [ w, -h],
tex_coords: [x_offset + x_size, y_offset + y_size], tex_coords: [x_offset + x_size, y_offset + y_size],
}, },
TextureVertex { TextureVertex {
position: [ 0.5, 0.5], position: [ w, h],
tex_coords: [x_offset + x_size, y_offset ], tex_coords: [x_offset + x_size, y_offset ],
}, },
TextureVertex { TextureVertex {
position: [-0.5, 0.5], position: [-w, h],
tex_coords: [x_offset , y_offset ], tex_coords: [x_offset , y_offset ],
}, },
], ],
@ -167,7 +181,8 @@ impl TextureSprite {
pub fn for_each<F: FnMut(&mut Pixel)>(&mut self, func: F) { pub fn for_each<F: FnMut(&mut Pixel)>(&mut self, func: F) {
//TODO check pos ? //TODO check pos ?
self.texture.for_each_in_area(func, self.texture_offset, self.texture_size); //TODO take scale into account
self.texture.for_each_in_area(func, self.texture_offset, self.inner_size);
} }
} }

View File

@ -79,6 +79,24 @@ impl From<winit::dpi::PhysicalSize<u32>> for Size {
} }
} }
//--NormalizedSize struct---------------------------------------------------------------------------
#[derive(Copy, Clone)]
pub struct NormalizedSize {
pub w: f32,
pub h: f32,
}
impl NormalizedSize {
pub fn from_size(size: Size, surface_size: Size) -> Self {
Self {
w: size.w as f32 / surface_size.w as f32,
h: size.h as f32 / surface_size.h as f32,
}
}
}
//--Pixel struct------------------------------------------------------------------------------------ //--Pixel struct------------------------------------------------------------------------------------
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)] #[repr(C)]