Masked Actor Shader

Share custom commands, script functions, actor implementations and other Naninovel plug-ins you've created.
Post Reply
User avatar
Elringus
Admin
Posts: 414
Joined: 11 May 2020 18:03

Masked Actor Shader

Post by Elringus »

A custom actor shader with mask support. Provided by Gigacee.

Code: Select all

Shader "Hidden/MaskableTransparent"
{
    Properties
    {
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _Opacity ("Opacity", float) = 0
        _StencilComp ("Stencil Comparison", float) = 3
    }

    SubShader
    {
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }

        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
            Stencil
            {
                Ref 1
                Comp [_StencilComp]
            }

            CGPROGRAM
            #include "UnityCG.cginc"

            #pragma target 2.0
            #pragma vertex ComputeVertex
            #pragma fragment ComputeFragment

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Opacity;

            struct VertexInput
            {
                float4 Vertex : POSITION;
                float2 TexCoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct VertexOutput
            {
                float4 Vertex : SV_POSITION;
                float2 TexCoord : TEXCOORD0;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            VertexOutput ComputeVertex(VertexInput vertexInput)
            {
                VertexOutput vertexOutput;
                UNITY_SETUP_INSTANCE_ID(vertexInput);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(vertexOutput);
                vertexOutput.Vertex = UnityObjectToClipPos(vertexInput.Vertex);
                vertexOutput.TexCoord = TRANSFORM_TEX(vertexInput.TexCoord, _MainTex);
                return vertexOutput;
            }

            fixed4 ComputeFragment(VertexOutput vertexOutput) : SV_Target
            {
                fixed4 color = tex2D(_MainTex, vertexOutput.TexCoord);
                color.rgb *= _Opacity;
                return color;
            }
            ENDCG
        }
    }
}

Image

User avatar
Gigacee
Posts: 2
Joined: 25 Apr 2021 10:59
Contact:

Re: Masked Actor Shader

Post by Gigacee »

I created the command to change whether or not the actor is the target of masking.

Code: Select all

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Naninovel
{
    [CommandAlias("mask")]
    public class ChangeActorMaskability : Command
    {
        [ParameterAlias(NamelessParameterAlias)]
        [RequiredParameter]
        [ActorContext]
        public StringListParameter ActorIds;

    [ParameterDefaultValue("true")]
    public BooleanParameter Enable = true;

    public override UniTask ExecuteAsync(AsyncToken asyncToken = default)
    {
        IReadOnlyCollection<IActorManager> managers = Engine.FindAllServices<IActorManager>(
            m => ActorIds.Any(id => m.ActorExists(id))
        );

        foreach (NullableString actorId in ActorIds)
        {
            if (managers.FirstOrDefault(m => m.ActorExists(actorId)) is { } manager)
            {
                switch (manager.GetActor(actorId))
                {
                    case MonoBehaviourActor<CharacterMetadata> actor:
                        ChangeMaskability(actor.GameObject);
                        break;

                    case MonoBehaviourActor<BackgroundMetadata> actor:
                        ChangeMaskability(actor.GameObject);
                        break;
                }
            }
        }

        return UniTask.CompletedTask;
    }

    private void ChangeMaskability(GameObject go)
    {
        go
            .GetComponent<TransitionalSpriteRenderer>()
            .SpriteMaterial
            .SetFloat(ShaderPropertyIds.StencilComp, Enable ? 3f : 8f);
    }

    private struct ShaderPropertyIds
    {
        public static readonly int StencilComp = Shader.PropertyToID("_StencilComp");
    }
}
}

Usage:

Code: Select all

@char YourCharacter

; Enable Mask
@mask YourCharacter

; Disable Mask
@mask YourCharacter enable:false

This command will work with Naninovel v1.18.

Post Reply