Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render: Implement reposition in Z-axis #19405

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/avm1/globals/bitmap_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ fn draw<'gc>(
Transform {
matrix,
color_transform,
tz: 0.0,
},
smoothing,
blend_mode,
Expand Down
24 changes: 17 additions & 7 deletions core/src/avm2/globals/flash/display/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,20 +412,30 @@ pub fn set_y<'gc>(
}

pub fn get_z<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Value<'gc>,
_activation: &mut Activation<'_, 'gc>,
this: Value<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_getter!(activation, "flash.display.DisplayObject", "z");
Ok(0.into())
let this = this.as_object().unwrap();

if let Some(dobj) = this.as_display_object() {
return Ok(dobj.z().into());
}
Ok(Value::Undefined)
}

pub fn set_z<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Value<'gc>,
_args: &[Value<'gc>],
this: Value<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_setter!(activation, "flash.display.DisplayObject", "z");
let this = this.as_object().unwrap();

if let Some(dobj) = this.as_display_object() {
let z = args.get_f64(activation, 0)?;
dobj.set_z(activation.gc(), z);
dobj.base_mut(activation.gc()).set_has_matrix3d_stub(true);
}
Ok(Value::Undefined)
}

Expand Down
11 changes: 7 additions & 4 deletions core/src/avm2/globals/flash/geom/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ pub fn get_matrix_3d<'gc>(
let display_object = get_display_object(this);
if display_object.base().has_matrix3d_stub() {
let matrix = *get_display_object(this).base().matrix();
let matrix3d = Matrix3D::from(matrix);
let mut matrix3d = Matrix3D::from(matrix);
matrix3d.set_tz(display_object.z());
matrix3d_to_object(matrix3d, activation)
} else {
Ok(Value::Null)
Expand All @@ -359,17 +360,19 @@ pub fn set_matrix_3d<'gc>(

let display_object = get_display_object(this);

let (matrix, has_matrix3d) = {
let (matrix, has_matrix3d, tz) = {
match args.try_get_object(activation, 0) {
Some(obj) => {
let matrix3d = object_to_matrix3d(obj, activation)?;
let matrix = Matrix::from(matrix3d);
(matrix, true)
let tz = matrix3d.tz();
(matrix, true, tz)
}
None => (Matrix::IDENTITY, false),
None => (Matrix::IDENTITY, false, 0.0),
}
};

display_object.base_mut(activation.gc()).set_matrix_tz(tz);
display_object.set_matrix(activation.gc(), matrix);
if let Some(parent) = display_object.parent() {
// Self-transform changes are automatically handled,
Expand Down
41 changes: 41 additions & 0 deletions core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,14 @@ impl<'gc> DisplayObjectBase<'gc> {
&mut self.transform.matrix
}

pub fn matrix_tz(&mut self) -> f64 {
self.transform.tz
}

pub fn set_matrix_tz(&mut self, tz: f64) {
self.transform.tz = tz;
}

pub fn set_matrix(&mut self, matrix: Matrix) {
self.transform.matrix = matrix;
self.set_scale_rotation_cached(false);
Expand Down Expand Up @@ -375,6 +383,17 @@ impl<'gc> DisplayObjectBase<'gc> {
changed
}

fn z(&self) -> f64 {
self.transform.tz
}

fn set_z(&mut self, tz: f64) -> bool {
let changed = self.matrix_tz() != tz;
self.set_transformed_by_script(true);
self.set_matrix_tz(tz);
changed
}

/// Caches the scale and rotation factors for this display object, if necessary.
/// Calculating these requires heavy trig ops, so we only do it when `_xscale`, `_yscale` or
/// `_rotation` is accessed.
Expand Down Expand Up @@ -941,6 +960,7 @@ pub fn render_base<'gc>(this: DisplayObject<'gc>, context: &mut RenderContext<'_
ty: -offset_y,
..cache_info.base_transform.matrix
},
tz: 0.0,
});
let mut offscreen_context = RenderContext {
renderer: context.renderer,
Expand Down Expand Up @@ -973,6 +993,7 @@ pub fn render_base<'gc>(this: DisplayObject<'gc>, context: &mut RenderContext<'_
..Default::default()
},
color_transform: cache_info.base_transform.color_transform,
tz: context.transform_stack.transform().tz,
},
true,
PixelSnapping::Always, // cacheAsBitmap forces pixel snapping
Expand Down Expand Up @@ -1045,6 +1066,7 @@ pub fn apply_standard_mask_and_scroll<'gc, F>(
context.transform_stack.push(&Transform {
matrix: Matrix::translate(-rect.x_min, -rect.y_min),
color_transform: Default::default(),
tz: 0.0,
});
}

Expand Down Expand Up @@ -1373,6 +1395,25 @@ pub trait TDisplayObject<'gc>:
}
}

/// The `z` position in pixels of this display object in local space.
/// Returned by the `_z`/`z` ActionScript properties.
fn z(&self) -> f64 {
self.base().z()
}

/// Sets the `z` position of this display object in local space.
/// Set by the `_z`/`z` ActionScript properties.
/// This invalidates any ancestors cacheAsBitmap automatically.
fn set_z(&self, gc_context: &Mutation<'gc>, z: f64) {
if self.base_mut(gc_context).set_z(z) {
if let Some(parent) = self.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(gc_context);
}
}
}

/// The rotation in degrees this display object in local space.
/// Returned by the `_rotation`/`rotation` ActionScript properties.
fn rotation(&self, gc_context: &Mutation<'gc>) -> Degrees {
Expand Down
1 change: 1 addition & 0 deletions core/src/display_object/edit_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,7 @@ impl<'gc> EditText<'gc> {
context.transform_stack.push(&Transform {
matrix: transform.matrix,
color_transform: ColorTransform::IDENTITY,
tz: 0.0,
});
} else {
context.transform_stack.push(transform);
Expand Down
1 change: 1 addition & 0 deletions core/src/display_object/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ impl<'gc> TDisplayObject<'gc> for Stage<'gc> {
context.transform_stack.push(&Transform {
matrix: self.0.read().viewport_matrix,
color_transform: Default::default(),
tz: 0.0,
});

// All of our Stage3D instances get rendered *underneath* the main stage.
Expand Down
34 changes: 34 additions & 0 deletions render/src/matrix3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,37 @@ impl From<Matrix3D> for Matrix {
}
}
}

impl Matrix3D {
pub const ZERO: Self = Self {
raw_data: [0.0; 16],
};
pub const IDENTITY: Self = Self {
raw_data: [
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
],
};

pub fn tz(&self) -> f64 {
self.raw_data[14]
}
pub fn set_tz(&mut self, tz: f64) {
self.raw_data[14] = tz;
}
}

impl std::ops::Mul for Matrix3D {
type Output = Self;

fn mul(self, rhs: Self) -> Self::Output {
let mut res = Matrix3D::ZERO;
for i in 0..4 {
for j in 0..4 {
for k in 0..4 {
res.raw_data[i + 4 * j] += self.raw_data[i + 4 * k] * rhs.raw_data[k + 4 * j];
}
}
}
res
}
}
3 changes: 3 additions & 0 deletions render/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use swf::ColorTransform;
#[derive(Clone, Debug, Default)]
pub struct Transform {
pub matrix: Matrix,
pub tz: f64,
pub color_transform: ColorTransform,
}

Expand All @@ -20,9 +21,11 @@ impl TransformStack {
let cur_transform = self.transform();
let matrix = cur_transform.matrix * transform.matrix;
let color_transform = cur_transform.color_transform * transform.color_transform;
let tz = cur_transform.tz + transform.tz;
self.0.push(Transform {
matrix,
color_transform,
tz,
});
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/alpha.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
Copy link
Contributor Author

@cookie-s cookie-s Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure of this change to be honest. Because in other WGSL files, the uv is independent of world_matrix (and sometimes uses another matrix texture_matrix), I thought this is correct, but not sure.

Copy link
Contributor Author

@cookie-s cookie-s Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is correct. I believe Ruffle uses those coordinate systems?:

  • in.position: [0, 1] * [0, 1] (e.g. Quad) (wgpu texture coordinate system)
  • world_matrix * in.position: [0, width] * [0, height] (FP coordinate system)
  • view_matrix * world_matrix * in.position: [-1, 1] * [-1, 1] (wgpu render coordinate system)

wgpu coordinate systems: https://github.com/gfx-rs/wgpu?tab=readme-ov-file#coordinate-systems

return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/darken.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/difference.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/erase.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/hardlight.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/invert.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/lighten.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/multiply.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
4 changes: 2 additions & 2 deletions render/wgpu/shaders/blend/overlay.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct VertexOutput {

@vertex
fn main_vertex(in: common__VertexInput) -> VertexOutput {
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
let pos = common__globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
let uv = vec2<f32>(in.position.xy);
return VertexOutput(pos, uv);
}

Expand Down
Loading