【问题标题】:Split Texture using a Curved Line in Unity3D C#在 Unity3D C# 中使用曲线分割纹理
【发布时间】:2018-05-03 21:37:35
【问题描述】:

我有一个纹理,我想使用 Vector2 数组将其切成两部分。 我有曲线的所有 Vector2 点。

问题

如何使用曲线点将纹理分成两部分。

替代解决方案/问题

如何“像素”填充 Vector2[] 形状以创建纹理?


我的尝试

1) 生成 Vector2 点以创建一个正方形,顶部为曲线边缘。看起来很有希望,但是当我尝试生成网格时,点排序不正确。

2) 动态创建 Polygon2D Collider - 模拟切片纹理的底部 - 这与尝试 1 有相同的问题,即点排序。所以当将 Collider 转换为 Mesh 时,显然和尝试的结果是一样的


如下图:

  1. 红线模拟了我的 Vector2 数组
  2. 灰色+绿色方块是纹理 1024 x 1024 像素
  3. 绿色区域是我想要的目标区域

【问题讨论】:

  • 到目前为止,您在 Unity 文档中寻找了什么,一般来说,但没有找到任何结果? (主要是因为您的问题似乎错过了解释您迄今为止搜索/研究和尝试的内容的部分)
  • 所以...你需要两个新的纹理,你可以用原始纹理的像素数据或透明度写入......
  • @Mike'Pomax'Kamermans 将编辑我的问题以包含我的尝试,谢谢
  • @Draco18s 只需要1个纹理,然后,使用Vector2数组去除'line'上方的像素。
  • 我会选择使用 Mesh。我将通过从您的 2D 曲线填充其顶点数组以及正方形顶部(或底部)边缘的 2 个顶点来生成一个网格。然后对这个新网格上的纹理进行 UV 映射,就好像我在整个方形网格上进行映射一样。然后将其渲染为 RenderTexture。我的意思是这不是最佳解决方案,您可能会遇到分辨率问题,它可能不是像素完美等,但它很强大。

标签: c# unity3d textures curve texture2d


【解决方案1】:

这会生成您想要的形状的网格(但顶部有锯齿状边缘),希望这是朝着正确方向迈出的一步。 Vector2 points[] 数组包含您的红线。它应该按 x 坐标排序,所有数字都应该在 0 和 1 之间。需要一个网格过滤器和一个带有纹理的网格渲染器。

using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class createMesh : MonoBehaviour {

    void Start () {
        Vector2[] points = new Vector2[4];
        points [0] = new Vector2 (0, .5f);
        points [1] = new Vector2 (.33f, 1f);
        points [2] = new Vector2 (.66f, .5f);
        points [3] = new Vector2 (1, 1f);

        MeshFilter mf = GetComponent<MeshFilter> ();
        Mesh mesh = new Mesh();


        Vector3[] verticies = new Vector3[points.Length * 2];
        int[] triangles = new int[(points.Length - 1)*6];
        Vector3[] normals = new Vector3[points.Length * 2];
        Vector2[] uv = new Vector2[points.Length * 2];

        int vIndex = 0;
        int tIndex = 0;
        int nIndex = 0;
        int uvIndex = 0;

        for (int i = 0; i< points.Length; i++) {
            Vector3 topVert = points[i];
            Vector3 bottomVert = topVert;
            bottomVert.y = 0;
            verticies[vIndex++]= bottomVert;
            verticies[vIndex++]=topVert;

            //uv
            uv[uvIndex++] = bottomVert;
            uv[uvIndex++] = topVert;

            //normals
            normals[nIndex++] = -Vector3.forward;
            normals[nIndex++] = -Vector3.forward;

            if (i<points.Length - 1) {
                //triangles
                triangles[tIndex++] = (i)*2;
                triangles[tIndex++] = (i)*2+1;
                triangles[tIndex++] = (i)*2+2;
                triangles[tIndex++] = (i)*2+2;
                triangles[tIndex++] = (i)*2+1;
                triangles[tIndex++] = (i)*2+3;

            }
        }

        mesh.vertices = verticies;
        mesh.triangles = triangles;
        mesh.normals = normals;
        mesh.uv = uv;

        mf.mesh = mesh;
    }
}

奖励:这是一种仅使用纹理的方法。要使用此位图,必须将其设置为高级,并在导入设置中启用读/写。此方法使用 0 到 1023(或纹理大小)作为坐标,并且也适用于超出该范围的数字。

using UnityEngine;
using System.Collections;


public class tex2d : MonoBehaviour {

    public Vector2[] points;

    void Start () {
        MeshRenderer mr;
        Texture2D t2d;
        Texture2D newTex = new Texture2D (1024, 1024);

        mr = GetComponent<MeshRenderer> ();
        t2d = mr.material.GetTexture (0) as Texture2D;
        MakeTex (points, t2d, ref newTex, 1024);
        mr.material.SetTexture (0, newTex);
    }


    void MakeTex(Vector2[] pnts, Texture2D inputTex, ref Texture2D outputTex, int size){

        Color bgcolor = new Color (1, 0, 1, 1);
        for (int i=0; i<(pnts.Length-1); i++) {
            Vector2 p1=pnts[i];
            Vector2 p2=pnts[i+1];

            //skip points that are out of range
            if ((p1.x <0 && p2.x <0) || (p1.x > size && p2.x>size)) continue;

            for (int x =(int)p1.x; x<(int)p2.x; x++) {
                if (x<0) continue;
                if (x>=size) break;

                float interpX = (x-p1.x)/(p2.x-p1.x);
                int interpY = (int) ((p2.y-p1.y)*interpX + p1.y);

                for (int y=0; y<interpY; y++) {
                    outputTex.SetPixel(x,y,inputTex.GetPixel(x,y));
                }
                for (int y= interpY; y<size; y++) {
                    outputTex.SetPixel(x,y,bgcolor);
                }

            }

        }
        outputTex.Apply ();
    }
}

【讨论】:

  • 感谢您的回答。值应该在 0 和 1 之间的原因是什么?
  • 这样编程对我来说更容易,因为这是 uv 坐标所需要的。如果您的数字更大,只需将它们除以最大数字即可。左下坐标为0,0,右上坐标为1,1
  • 太棒了!一旦我有时间我会试一试 - 会及时通知你。谢谢
  • 我也添加了第二种方法。
  • 能否请你奖励这个问题?
猜你喜欢
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多