Краска Сплат в Единстве - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь нарисовать куб с сеточным коллайдером, когда мой шарик с краской сталкивается с ним. я могу выплеснуть свою краску на куб, но она разбрызгивает все 6 сторон куба, а также на передние точки.

This script is attached to every object that can be drawn.
    public class DrawableBehaviour : MonoBehaviour
{
    [Tooltip("Number of pixels per 1 unit of size in world coordinates.")]
    [Range(16, 8182)]
    [SerializeField] private int _textureSize = 64;

    private readonly Color _color = new Color(0, 0, 0, 0);

    private Material _material;
    private Texture2D _texture;
    private bool _isEnabled = false;

    private object _lockFlag = new object();

    private void Start()
    {
        Renderer renderer = GetComponent<Renderer>();
        if (null == renderer)
            return;

        foreach (Material material in renderer.materials)
        {
            if (material.shader.name.Contains("Custom/PaintShader"))
            {
                _material = material;
                break;
            }
        }

        if (_material)
        {
            _texture = new Texture2D(_textureSize, _textureSize);
            for (int x = 0; x < _textureSize; ++x)
                for (int y = 0; y < _textureSize; ++y)
                    _texture.SetPixel(x, y, _color);
            _texture.Apply();

            _material.SetTexture("_DrawingTex", _texture);
            _isEnabled = true;
        }
    }

    public void PaintOnColored(Vector2 textureCoord, float[,] splashTexture, Color color)
    {
        MyPaintOn(textureCoord, splashTexture, color);
    }

    private void MyPaintOn(Vector2 textureCoord, float[,] splashTexture, Color targetColor)
    {
        if (_isEnabled)
        {
            lock (_lockFlag)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                int reqnx = splashTexture.GetLength(0);
                int reqny = splashTexture.GetLength(1);
                int reqX = (int)(textureCoord.x * _textureSize) - (reqnx / 2);
                int reqY = (int)(textureCoord.y * _textureSize) - (reqny / 2);
                int right = _texture.width - 1;
                int bottom = _texture.height - 1;

                int x = IntMax(reqX, 0);
                int y = IntMax(reqY, 0);
                int nx = IntMin(x + reqnx, right) - x;
                int ny = IntMin(y + reqny, bottom) - y;

                Color[] pixels = _texture.GetPixels(x, y, nx, ny);

                int counter = 0;
                for (int i = 0; i < nx; ++i)
                {
                    for (int j = 0; j < ny; ++j)
                    {
                        float currAlpha = splashTexture[i, j];
                        if (currAlpha == 1)
                            pixels[counter] = targetColor;
                        else
                        {
                            Color currColor = pixels[counter];
                            // resulting color is an addition of splash texture to the texture based on alpha
                            Color newColor = Color.Lerp(currColor, targetColor, currAlpha);
                            // but resulting alpha is a sum of alphas (adding transparent color should not make base color more transparent)
                            newColor.a = pixels[counter].a + currAlpha;
                            pixels[counter] = newColor;
                        }
                        counter++;
                    }
                }

                _texture.SetPixels(x, y, nx, ny, pixels);
                _texture.Apply();
                sw.Stop();
            }
        }
    }

    private int IntMax(int a, int b)
    {
        return a > b ? a : b;
    }

    private int IntMin(int a, int b)
    {
        return a < b ? a : b;
    }
}

Это сценарий моего объекта шара

    public class PaintBallBehaviour : MonoBehaviour
{
    [SerializeField] private Texture2D _splashTexture;

    private void OnTriggerEnter(Collider other)
    {        
        PaintProjectileManager manager = GameManager.GetInstance().GetProjectileManager();
        var position = transform.position;
        Vector3 backPos = new Vector3(position.x, position.y, position.z-2);
        for (int i = 0; i < 14; ++i)
        {
            RaycastHit hit;
            if (Physics.Raycast(backPos, transform.forward /*GetSphereRay(i)*/, out hit /*, paintDiameter*/))
            {
                if (hit.collider is MeshCollider)
                {
                    DrawableBehaviour drawable = hit.collider.gameObject.GetComponent<DrawableBehaviour>();
                    if (drawable)
                    {
                        Debug.Log(hit.textureCoord2);
                        drawable.PaintOnColored(hit.textureCoord2, manager.GetRandomProjectileSplash(),
                            new Color32(0, 47, 255, 255));

                    }
                }
            }
        }

        Debug.DrawRay(backPos, manager.GetRandomSphereRay(),Color.red);
        LeanPool.Despawn(gameObject);
    }
}

И этомой шейдер

Shader "Custom/PaintShader"
{
    Properties
    {
        [HideInInspector]_DrawingTex("Drawing texture", 2D) = "" {}
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _DrawingTex;
        sampler2D _MainTex;

        struct Input
        {
            float2 uv_DrawingTex;
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            float4 drawData = tex2D(_DrawingTex, IN.uv_DrawingTex);
            float4 mainData = tex2D(_MainTex, IN.uv_MainTex) * _Color;
            fixed4 c = lerp(mainData, drawData, drawData.a);
            c.a = drawData.a + mainData.a;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Я не очень разбираюсь в отображении сплатов и тому подобном, поэтому кто-нибудь может помочь мне понять, что не так и как с этим справиться?

Вот видеоссылка: ВИДЕО

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...