当前位置:   article > 正文

Unity实时涂鸦绘画插件:RealTime Painting_unity 纹理绘画

unity 纹理绘画

Unity新手入门进阶之路(群内各种入门资源资料大神):721559786 (加群下载插件资源学习资料)

                                           

介绍:

游戏越来越多地被用户每天定制。关于这个因素有很多选择。

我发现特别有趣,很容易做动画画一个网格纹理,并保留它以备后用。

您可以使用这个纹理,如示例中所示,用于完全自定义,或者将选定的预制作为贴图或具有某些可选功能的模板。

先决条件:
  • 统一处理3D模型及其纹理。
  • 什么是UV贴图和渲染纹理。
  • Unity 5.XUnity 4.X Pro
解决问题:

解决这个问题时面临的主要情况是:

  1. UV地图交互点之间的关系
  2. 如何动态地绘制这个新的纹理。
  3. 如何保存纹理以备后用。
指向UV地图:

要模拟绘制网格,我们必须找到一种方法来实时绘制网格材质的纹理。

要做到这一点,我们将使用渲染纹理。渲染纹理的相机将使用我们模型的uv贴图查看四边形。

                       

                                                                                       

基地纹理。

 



背景中的四边形应该在其材质中使用“未照明纹理”作为着色器,以避免着色错误。

这样,放在我们相机前的任何东西都会被添加到纹理中。

现在,我们将创建一个材质来使用纹理,我们会将这个材质命名为canvasMaterial。

这种材料被我们的网格所使用,并且它可以对它有任何影响,唯一的要求是当然我们绘制纹理的一个插槽,在这个例子中,我们将使用标准着色器。

                                

                                                                                  

帆布材质应用于模型。

 

在将材料添加到我们的网格物体后,接下来的部分将会弄清楚如何在这个相机前面放置材料来模拟绘制它。为此,我们将使用Raycasting和一个美妙的统一功能:

bool HitTestUVPosition(ref Vector3 uvWorldPosition){ 
RaycastHit命中;
Vector3 mousePos =输入 .mousePosition;
Vector3 cursorPos = new Vector3(mousePos.x,mousePos.y,0.0f); 
Ray cursorRay = sceneCamera.ScreenPointToRay(cursorPos);   如果(物理 .Raycast(cursorRay,出命中,200)){      MeshCollider meshCollider = hit.collider作为MeshCollider ;    if(meshCollider == null || meshCollider.sharedMesh == null)       return false ;    Vector2 pixelUV =新的Vector2 




(hit.textureCoord.x,hit.textureCoord.y); 
   uvWorldPosition.x = pixelUV.x; 
   uvWorldPosition.y = pixelUV.y; 
   uvWorldPosition.z = 0.0F; 
   返回true ; 
  } 
  else { 
   return false ; 
  } 
}

有了这个功能,我们可以确定哪个部分的UV贴图是我们用RayCast打的,所以现在我们可以将东西放入我们的动态贴图中!

动态绘画:

现在,如果您还没有弄清楚,我们将在渲染相机前实例化模拟绘画,现在这个窍门将以一种干净的方式进行,并且能够在绘画时融合我们的颜色。

首先要注意的是我们将要实例化哪些内容,如下图所示

                                                      

为了避免有太多的绘制调用,我们将使用精灵,通过这种方式,我们可以改变我们的笔刷实例颜色,而无需创建一个材质实例,以允许统一将这些精灵分组在一起。

我们的笔刷实例褪色且透明的事实允许我们在绘画时模拟颜色合并

为了避免在我们的场景中出现太多这种画笔的情况,当事情变得有点棘手时,主要的问题是,在完成这一步后无法撤消我们的网状画

首先,我们将确定在我们的场景中允许的一定数量的画笔实例(在此示例中,我们有1000个画笔),当达到实例化画笔的数量时,我们将合并当前纹理和迄今为止绘制的内容,合并后我们将不得不清理我们的刷子。

公共RenderTexture canvasTexture ;
int brushCounter = 0; //增加每个画笔的实例化
 
void MergeTexture(){ 
   RenderTexture .active = canvasTexture;
  int width = canvasTexture.width;
  int height = canvasTexture.height;
  Texture2D tex = 新的Texture2D(宽度,高度,TextureFormat.RGB24,false);
  tex.ReadPixels(new Rect(0,0,width,height),0,0);
  tex.Apply();
  RenderTexture .active = null;
  baseMaterial.mainTexture = tex; //将绘制的纹理作为基础
  foreach在brushContainer.transform中变换小孩){//清除画笔
     Destroy(child.gameObject);
  }
  brushCounter = 0; //重置场景中的多少个画笔
}

生成的画笔合并到我们的基本纹理(包括贴图)。

 这个过程只需要很少的时间,但它有时会被注意到(主要取决于我们的纹理分辨率),但是这将允许uss 无限期继续绘画

保存纹理:

在我们画完了我们的绘画之后,我们的纹理得到了正确的合并,下一个可选步骤就是将这个纹理保存到一个文件中供以后使用。

由于我们有一个Texture2D,我们可以使用下一个方法将它保存到一个文件中:

IEnumerator SaveTextureToFile(Texture2D savedTexture){ 
     string fullPath = SystemIO目录 .GetCurrentDirectory();
    System.DateTime date = System.DateTime.Now ;
    string fileName =“CanvasTexture.png”;
    如果(!System.IO.Directory .Exists(fullPath)) 
        System.IO.Directory .CreateDirectory(fullPath);
    var bytes = savedTexture.EncodeToPNG();
    System.IO.File .WriteAllBytes(fullPath + fileName,bytes);
    产量返回null ;
 }

将该函数调用为corutine(用于将其保存在背景上):

StartCoroutine(“SaveTextureToFile”);

技巧和窍门:

  • 您可以将光标放置在网格上(如演示中),将其放置在UV地图上,只需小心在保存之前将其隐藏起来!
  • 您可以将您的画笔实例添加到父对象以更容易地清除并拥有更清晰的场景
  • 为了放置贴花,您可以使用贴花替换投影的光标,而不是刷子实例放置贴花。
  • 您可以使用与网格的初始基底相同的颜色进行绘制来模拟删除
  • 此方法旨在供最终用户使用,或生成与绘制元素相匹配的图像文件。
  • 任何模型都可以被绘制,只要它有一个网格碰撞器和一个正确的UV映射,您只需要网格就可以使用我们将要创建的材质。
  • 当物体的UV 没有被镜像并且元素之间很大的空间时,这种方法效果最好(为了防止绘画时颜色重叠)

结论:

以这种方式绘制我们的网格将使我们有很大的自由度,并且对于最终用户来说会有非常干净的结果,但是效率不高,所以它主要集中在成为主要特征时出现。

合并我们的纹理后,它也不允许我们回滚到目前为止所做的更改。

然而,我们可以在我们的纹理中放置任何类型的贴图或精灵,这样可以非常有趣地定制我们的网格,并且还可以将这些更改保存在其他场景中,以便将其用作更复杂系统的工具。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/117081
推荐阅读
相关标签
  

闽ICP备14008679号