Ghosttt
Topic Author
Posts: 12
Joined: 06 Jun 2025, 01:09

How to create a responsive custom mask/clip

28 Jun 2025, 15:55

Hi Noesis Studio team,

Sorry for asking while my first questioned hasn't been resolved! I wonder if there is a way to create a responsive, scalable and custom mask within Noesis Studio? The attached image is an example - a tilted mask has been used to mask out the character and VFX light behind it. I am trying to achieve similar effect

I have tried:
Opacity Mask - It seems that opacity mask will move along with the children element? I can't make the opacity mask stay in the correct position / in the correct shape, which make the masking weird

Clipping path - The clipping shape won't scale along with the aspect radio
Clip, path geometry - Same issue with clipping path

Clip to Bound - I thought it would make the child element clip to parent container? I tried putting a tilted shape in parent container (grid) and hopefully it worked, but it didn't. I guess the parent container only reflect to the very top of element? (In my case, it will only clip to grid rather than the tilted shape)

Using a shape to contain image brush - It works, but it won't work with component / other elements. It also won't allow me to put multiple objects inside the shape.

I wonder if there is a way to create responsive mask with custom shape, that can contain multiple layers inside it?

Thank you again for your every help, always appreciate for everything you have done!
Attachments
Knighthood07112020-082607-35098.jpg
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: How to create a responsive custom mask/clip

03 Jul 2025, 12:13

Hello,

You can create an OpacityMask by using another element as reference. Please have a look at the attached xaml for an example (it defines the source of the mask by applying some Skew transform).
skew-mask.png
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  d:DesignWidth="1920"
  d:DesignHeight="1080"
  Background="#FF4D5052" xmlns:noesis="clr-namespace:NoesisGUIExtensions">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="150"/>
      <RowDefinition Height="1*"/>
      <RowDefinition Height="150"/>
      <RowDefinition Height="150"/>
      <RowDefinition Height="1*"/>
      <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <Grid x:Name="MaskSrc" Margin="0" Grid.Row="1" Grid.RowSpan="2">
      <Grid.RowDefinitions>
        <RowDefinition Height="1*"/>
        <RowDefinition Height="1*"/>
        <RowDefinition Height="1*"/>
      </Grid.RowDefinitions>
      <Rectangle Fill="#FFFF0097" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2"/>
      <Rectangle Fill="#FFFF0097" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2" Grid.Row="1">
        <Rectangle.RenderTransform>
          <TransformGroup>
            <ScaleTransform/>
            <SkewTransform AngleY="-4"/>
            <RotateTransform/>
            <TranslateTransform/>
          </TransformGroup>
        </Rectangle.RenderTransform>
      </Rectangle>
    </Grid>
    <Grid x:Name="BottomContent" Grid.RowSpan="3" Margin="0" Grid.Row="2">
      <Grid.Background>
        <RadialGradientBrush RadiusY="1.443525" RadiusX="0.47148907" GradientOrigin="0.613177,0.803255" Center="0.613177,0.803255">
          <RadialGradientBrush.RelativeTransform>
            <TransformGroup>
              <ScaleTransform CenterY="0.72338" CenterX="0.588424"/>
              <SkewTransform CenterY="0.72338" CenterX="0.588424"/>
              <RotateTransform Angle="-0.24513023" CenterY="0.8032555" CenterX="0.61317706"/>
              <TranslateTransform/>
            </TransformGroup>
          </RadialGradientBrush.RelativeTransform>
          <GradientStop Color="#FFD9D6E6" Offset="0"/>
          <GradientStop Color="#FFBDA9DE" Offset="0.243"/>
          <GradientStop Color="#FF334776" Offset="1"/>
          <GradientStop Color="#FF7C82AA" Offset="0.526"/>
        </RadialGradientBrush>
      </Grid.Background>
      <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="150"/>
            <RowDefinition Height="1*"/>
          </Grid.RowDefinitions>
          <StackPanel VerticalAlignment="Center" Grid.Row="1" Margin="0,0,150,0" Width="300">
            <TextBlock Text="Common" TextWrapping="Wrap" FontSize="25"/>
            <Path Data="M20,0.5 24.3784,13.9736 38.5456,13.9742 27.0844,22.3019 31.4618,35.7758 20,27.449 8.53819,35.7758 12.9156,22.3019 1.4544,13.9742 15.6216,13.9736 20,0.499998z" Fill="#FFFFCD24" Stretch="Fill" Stroke="#FFD78B24" Height="36.275833" Margin="0.954,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="38.0912"/>
            <TextBlock Text="HELMAR" TextWrapping="Wrap" Foreground="#FFFFFFFF" FontWeight="Bold" FontSize="65"/>
            <TextBlock Text="Strong vs Outlaw" TextWrapping="Wrap" FontSize="25"/>
            <TextBlock Text="Level 1" TextWrapping="Wrap" Foreground="#FFFFFFFF" FontWeight="Bold" FontSize="45"/>
            <Button Content="SWAP"/>
          </StackPanel>
        </Grid>
        <Ellipse Width="400" Margin="0,160,20,-150" HorizontalAlignment="Center">
          <Ellipse.Fill>
            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
              <GradientStop Color="#FFFFC6B6" Offset="0"/>
              <GradientStop Color="#FF00143C" Offset="1"/>
            </LinearGradientBrush>
          </Ellipse.Fill>
        </Ellipse>
      </StackPanel>
    </Grid>
    <Grid x:Name="TopContent" Grid.RowSpan="3" Margin="0" Grid.Row="1">
      <Grid.OpacityMask>
        <VisualBrush Visual="{Binding ElementName=MaskSrc}" Stretch="Uniform" AlignmentY="Top"/>
      </Grid.OpacityMask>
      <Grid.Background>
        <RadialGradientBrush RadiusY="1.443525" RadiusX="0.47148907" GradientOrigin="0.613177,0.803255" Center="0.613177,0.803255">
          <RadialGradientBrush.RelativeTransform>
            <TransformGroup>
              <ScaleTransform CenterY="0.72338" CenterX="0.588424"/>
              <SkewTransform CenterY="0.72338" CenterX="0.588424"/>
              <RotateTransform Angle="-0.24513023" CenterY="0.8032555" CenterX="0.61317706"/>
              <TranslateTransform/>
            </TransformGroup>
          </RadialGradientBrush.RelativeTransform>
          <GradientStop Color="#FFD9D6E6" Offset="0"/>
          <GradientStop Color="#FFBDA9DE" Offset="0.243"/>
          <GradientStop Color="#FF464B68" Offset="1"/>
          <GradientStop Color="#FF7C82AA" Offset="0.526"/>
        </RadialGradientBrush>
      </Grid.Background>
      <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="150"/>
          </Grid.RowDefinitions>
          <StackPanel VerticalAlignment="Center" Margin="0,0,150,0" Width="300">
            <TextBlock Text="Common" TextWrapping="Wrap" FontSize="25"/>
            <Path Data="M20,0.5 24.3784,13.9736 38.5456,13.9742 27.0844,22.3019 31.4618,35.7758 20,27.449 8.53819,35.7758 12.9156,22.3019 1.4544,13.9742 15.6216,13.9736 20,0.499998z" Fill="#FFFFCD24" Stretch="Fill" Stroke="#FFD78B24" Height="36.275833" Margin="0.954,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="38.0912"/>
            <TextBlock Text="ASH" TextWrapping="Wrap" Foreground="#FFFFFFFF" FontWeight="Bold" FontSize="65"/>
            <TextBlock Text="Strong vs Beast" TextWrapping="Wrap" FontSize="25"/>
            <TextBlock Text="Level 1" TextWrapping="Wrap" Foreground="#FFFFFFFF" FontWeight="Bold" FontSize="45"/>
            <Button Content="SWAP"/>
          </StackPanel>
        </Grid>
        <Ellipse Width="400" Margin="0,10,20,0" HorizontalAlignment="Center">
          <Ellipse.Fill>
            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
              <GradientStop Color="#FFB6FFBC" Offset="0"/>
              <GradientStop Color="#FF133C00" Offset="1"/>
            </LinearGradientBrush>
          </Ellipse.Fill>
        </Ellipse>
      </StackPanel>
    </Grid>
    <Grid x:Name="Header" Background="#FF002775"/>
    <Grid x:Name="Footer" Grid.Row="5">
      <Grid.Background>
        <LinearGradientBrush StartPoint="-0.00409131,0.5" EndPoint="1.00292,0.5">
          <GradientStop Color="#FF002775" Offset="0"/>
          <GradientStop Color="#FF733068" Offset="1"/>
        </LinearGradientBrush>
      </Grid.Background>
    </Grid>
  </Grid>
</Page>
Please let me know if this is what you where looking for.
 
Ghosttt
Topic Author
Posts: 12
Joined: 06 Jun 2025, 01:09

Re: How to create a responsive custom mask/clip

04 Jul 2025, 13:08

Hi sfernandez,

Thank you for your reply! I think this is the closest solution to my problem. I have looked into the file and try to replicate it, but I figure a few pain points:

1. The mask and the clipping layer seems need to sit under the same master grid - I have tried using two different grid to do it, but the shape will disappear when I put them on top of mask src, it will show as the clipping shape tho if I move them out of the mask src area.
2. The mask source is technically still here but covered by the new image, what if I don't have a background fill for the masking element? I tried making the mask transparent or hide the mask, but it will make the element being massed disappear as well.
3. For some reason, the mask is not working as intended even if I put them in a same master grid, the cropping weirdly move down when I apply opacity mask? it looks like they have an extra edge around the masking source while they don't. I am putting a mask with a horizontal stack with 5 elements.

Sorry for being a pain but I can't show the exact screen as the screen is protected by NDA. Many thanks.
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: How to create a responsive custom mask/clip

09 Jul 2025, 11:08

Hi,

I created the mask source under the same Grid for simplicity, but you can have separate panels for that. The only requirement is that the mask source has the same size and aspect ratio as the group of UI elements you want to mask. And then adjust the VisualBrush used in the OpacityMask. In my example I applied Stretch=Uniform and AlignmentY=Top to place the mask in the right position.

Regarding the mask source, it needs to have solid parts to define the masked area. But you can group the mask source in an invisible parent if you want to hide it from the UI:
<Grid Opacity="0">
  <Grid x:Name="MaskSource">...</Grid>
</Grid>
If you need to share sensible information you can create a private ticket in our bugtracker. We'll try to identify what is happening in your scenario and provide the solution.
 
Ghosttt
Topic Author
Posts: 12
Joined: 06 Jun 2025, 01:09

Re: How to create a responsive custom mask/clip

16 Jul 2025, 12:33

Hi sfernandez,

Thank you for the suggestion and explanation! I try to convert the issue into a xaml that is safe to share, as I believe that it will help more people if we can take thing onto the table :D Unfortunately I can't replicate the disappearing issue, but I will probably update it with a new topic if I encounter it! Again I zip the xaml, I can also copy the whole coding to here. I will appreciate if you can check the issue here!
Attachments
MaskIssue.zip
(904 Bytes) Downloaded 417 times
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: How to create a responsive custom mask/clip

18 Jul 2025, 15:57

The wrong clipping you're seeing in the xaml you attached are caused by the group being clipped not having the same rendered area (it includes children area) as the mask.

I modified your xaml to clip (ClipToBounds=True) children parts that are out of the parent container, and also see how the parent container has a background, even if transparent, so it accounts for the rendered area.
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  d:DesignWidth="1920"
  d:DesignHeight="1080"
  Background="#FF4D5052">
  <Grid x:Name="MasterGrid">
    <Grid x:Name="MarginGrid">
      <Grid.RowDefinitions>
        <RowDefinition Height="1*"/>
        <RowDefinition Height="9*"/>
        <RowDefinition Height="1*"/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*"/>
        <ColumnDefinition Width="8*"/>
        <ColumnDefinition Width="1*"/>
      </Grid.ColumnDefinitions>
      <Grid x:Name="Case1_WeirdCutOff" Grid.Row="1" Grid.Column="1">
        <Grid.RowDefinitions>
          <RowDefinition Height="442*"/>
          <RowDefinition Height="442*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="MaskHiddenParent" Grid.Row="1" Opacity="0">
          <Grid x:Name="MaskSrc">
            <Path Stretch="Fill" Fill="#FFF4F4F5" Height="441.81818" Width="1536" Data="M27.5526,0 100,0 100,100 0,100z"/>
          </Grid>
        </Grid>
        <Grid x:Name="Case1_Content" Grid.Row="1" ClipToBounds="True" Background="#00000000">
          <Grid.OpacityMask>
            <VisualBrush Visual="{Binding ElementName=MaskSrc}"/>
          </Grid.OpacityMask>
          <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="1043,-99,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
          <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="615,147,0,-11" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
          <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="158,17,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
          <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="1203,221,0,-85" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
        </Grid>
      </Grid>
      <Grid x:Name="Case2_SiblingGroup" Grid.Column="1" Grid.Row="1">
        <Grid.RowDefinitions>
          <RowDefinition Height="1*"/>
          <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="Case2_MaskChangingDependsOnChildren" Margin="0">
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="442*"/>
          </Grid.RowDefinitions>
          <Grid x:Name="Case2_Content" Grid.Row="1" Background="#FF000000" ClipToBounds="True">
            <Grid.OpacityMask>
              <VisualBrush Visual="{Binding ElementName=MaskSrc}"/>
            </Grid.OpacityMask>
            <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="512,-66,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
            <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="820,195,0,-60" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
            <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="43,214,0,-78" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
            <Ellipse Stroke="#FF000000" Height="306" Width="306" Margin="1362,19,-132,0" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#FF3838FF"/>
          </Grid>
        </Grid>
      </Grid>
    </Grid>
  </Grid>
</Page>
Hope this helps.

Who is online

Users browsing this forum: No registered users and 2 guests