unity3D 涂涂乐使用shader实现上色效果

之前我博文里面发过一个简单的通过截图方式来实现的模型上色方法,但是那个方法不合适商用,因为你需要对的很准确才可以把贴图完美截取下来,只要你手抖了一下就会发现贴歪了。那么有没有更好的方法来实现这个效果呢,这就需要使用Shader的方式来实现这个效果。

刚好看到了一篇有关于涂涂乐原理的实现方法,EsayAR的官方案例里面就是使用的这个方法,EsayAR的官方案例其实基本完成这个涂涂乐的效果在看过涂涂乐原理,结合案例的是用Vuforia实现的一个效果,发现利用Shader的方式来实现涂涂乐UV图片的修正这个方式比利用对准框的方法要好,而且也避免了UV在位置偏移的问题。(PS:点击打开链接 Vuforia的案例,注意PC上是没有问题的,但是移动端UV会出现破面的问题)

这里要注意PC上实现的效果并不代表手机上能实现涂涂了得效果,就如Vuforia的案例一样PC上是没有任何问题,但是在移动端就会出现一些问题。(PS:这里我使用的EsayAR的来实现Vuforia的方法)

注意这里提供的源码是使用EsayAR来写的(PS:移动端是有问题)

  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using EasyAR;
  5.  
  6. public class Coloring3D : MonoBehaviour
  7. {
  8.  
  9. public MeshRenderer realityPlane;
  10. public Camera rendercamera;
  11. private Vector3[] marks;
  12. private Material cubeMat;
  13. private Vector2 sizeVector2;
  14. private Vector2 webcamTex2ScreenScale;
  15. private ImageTargetBehaviour imageTargetBehaviour;
  16. private Texture2D scanTexture2D;
  17. private bool isSetupScale = false;
  18.  
  19. // Use this for initialization
  20. void Start ()
  21. {
  22. Init();
  23. }
  24.  
  25. public void Init()
  26. {
  27. marks = new Vector3[4];
  28. sizeVector2 = new Vector2();
  29. imageTargetBehaviour = transform.GetComponentInParent<ImageTargetBehaviour>();
  30. sizeVector2 = imageTargetBehaviour.Size;
  31.  
  32. //计算识别Plane的4个角的位置
  33. for (int i = 0; i < marks.Length; i++)
  34. {
  35. float x = -1, y = -1;
  36. if ((i + 1) % 2 == 0)
  37. x = 1;
  38. else
  39. x = -1;
  40. if (i >= 2)
  41. y = 1;
  42. marks[i] = new Vector3(sizeVector2.x / 2 * x, 0, sizeVector2.y / 2 * y);
  43. }
  44.  
  45. }
  46.  
  47. void SetupScale()
  48. {
  49. //if (!imageTargetBehaviour.GetIsShow())//判断模型是不是显示出来,可以注释掉
  50. //return;
  51. if (!isSetupScale)
  52. {
  53. cubeMat = this.transform.GetComponent<MeshRenderer>().material;
  54.  
  55. var texture = realityPlane.material.mainTexture;//获取摄像头照到的纹理图片
  56. cubeMat.mainTexture = texture;//将纹理赋值到材质球上
  57.  
  58. //计算屏幕和整张图片的比例
  59. var maxScale = Mathf.Max((float)Screen.width / texture.width, (float)Screen.height / texture.height);
  60.  
  61. var t2sWidth = texture.width * maxScale;
  62. var t2sHeight = texture.height * maxScale;
  63.  
  64. webcamTex2ScreenScale.x = Screen.width / t2sWidth;
  65. webcamTex2ScreenScale.y = Screen.height / t2sHeight;
  66. isSetupScale = true;
  67. }
  68.  
  69. for (int i = 0; i < marks.Length; i++)
  70. {
  71. marks[i] = marks[i] + this.transform.parent.position;
  72. var pos =
  73. AdjustUV(rendercamera.WorldToViewportPoint(marks[i]));
  74. string posName = String.Format("p{0}", i);
  75. cubeMat.SetVector(posName, pos);//传入到shader进行纹理的拉伸
  76. }
  77.  
  78. }
  79.  
  80. Vector4 AdjustUV(Vector3 v)
  81. {
  82. //识别图在屏幕的位置
  83. var webcamX = FixWebcamTextureToScreenUV(v.x, webcamTex2ScreenScale.x);
  84. var webcamY = FixWebcamTextureToScreenUV(v.y, webcamTex2ScreenScale.y);
  85. return new Vector4(webcamX*v.z, (1 - webcamY)*v.z, v.z, 1.0f);
  86. }
  87.  
  88. float FixWebcamTextureToScreenUV(float value, float scale)
  89. {
  90. return (1.0f - scale) * 0.5f + value * scale;
  91. }
  92.  
  93. // Update is called once per frame
  94. void OnWillRenderObject()
  95. {
  96. SetupScale();
  97. }
  98. }

接下来是shader:

  1. Shader "Unlit/PaintingShader"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", 2D) = "white" {}
  6. }
  7. SubShader
  8. {
  9. Tags { "RenderType"="Opaque" }
  10. LOD 100
  11.  
  12. Pass
  13. {
  14. CGPROGRAM
  15. #pragma vertex vert
  16. #pragma fragment frag
  17.  
  18. #include "UnityCG.cginc"
  19. struct appdata
  20. {
  21. float4 vertex : POSITION;
  22. float2 uv : TEXCOORD0;
  23. };
  24.  
  25. struct v2f
  26. {
  27. float2 uv : TEXCOORD0;
  28. float4 vertex : SV_POSITION;
  29. };
  30.  
  31. sampler2D _MainTex;
  32. float4 p0;
  33. float4 p1;
  34. float4 p2;
  35. float4 p3;
  36.  
  37. v2f vert (appdata v)
  38. {
  39. v2f o;
  40. o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
  41. o.uv.x = v.uv.x;
  42. o.uv.y = v.uv.y;
  43. return o;
  44. }
  45.  
  46. fixed4 frag (v2f i) : SV_Target
  47. {
  48. float2 mid;
  49. float3 newUV;
  50.  
  51. //计算纹理的位置
  52. if (i.uv.x + i.uv.y >= 1) {
  53. mid = i.uv;
  54. newUV = p0 * (1 - mid.x - mid.y) + p1 * mid.x + p2 * mid.y;
  55. } else {
  56. mid = float2(1 - i.uv.y, i.uv.x + i.uv.y - 1);
  57. newUV = p2 * (1 - mid.x - mid.y) + p1 * mid.x + p3 * mid.y;
  58. }
  59. //返回计算好的纹理位置
  60. return tex2D(_MainTex, newUV.xy / newUV.zz);
  61. }
  62.  
  63. ENDCG
  64. }
  65. }
  66. }

这里看看效果PC的效果图片吧!

(PS:这里要注意移动端是会出现问题的,但是PC端是没有问题的)

最后附上一张移动端的涂涂乐效果图出来

功能有实时渲染,点击屏幕后就取消实时渲染然后上色到模型上。(PS:移动端的和PC端的代码编写差异挺大的,但是还是离不上面用到的源码)

Vuforia的移动端问题有待解决,如果解决这个问题我会第一时间写博客告诉大家。

(如果想交流一下涂涂乐的问题,可以加我QQ:245076259)

unity3D 涂涂乐使用shader实现上色效果的更多相关文章

  1. unity3D AR涂涂乐制作浅谈

    unity3D AR涂涂乐制作浅谈 AR为现在是虚拟现实较为火爆的一个技术,其中有个比较炫酷的就是AR涂涂乐的玩法,这个技术可以把扫描到的图片上的纹理 粘贴到模型上实现为模型上色的功能,但是我们需要怎 ...

  2. 手把手教你做个AR涂涂乐

    前段时间公司有一个AR涂涂乐的项目,虽然之前接触过AR也写过小Demo,但是没有完整开发过AR项目.不过经过1个多星期的学习,现在已经把项目相关的技术都学会了,在此向互联网上那些乐于分享的程序员前辈们 ...

  3. AR涂涂乐

    <1> 涂涂乐着色 https://blog.csdn.net/begonia__z/article/details/51282932 http://www.manew.com/blog- ...

  4. 涂涂影院APP-免费VIP电影观看「安卓APP」

    最新下载链接:https://www.lanzous.com/u/niceyoo 2019年基本就没推广过这款APP,很失败,从第一版发布到现在涂涂影院已经做了2年了, 由于没有官网,所以基本百度能搜 ...

  5. Unity Shader实现描边效果

    http://gad.qq.com/article/detail/28346 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果.本篇文章和大家介绍下利用S ...

  6. pixijs shader 制作百叶窗效果

    pixijs shader 制作百叶窗效果 直接贴代码了 const app = new PIXI.Application({ transparent: true }); document.body. ...

  7. Unity3d 镜面反射 vertex and frag Shader源代码

    Unity3d 镜面反射 网上能找到的基本上是固定管道或表面渲染的shader. 特此翻译为顶点.片段渲染的Shader, 本源代码仅仅涉及shader与cs部分. Editor部分使用NGUI绘制的 ...

  8. Unity3D 屏幕空间雪场景Shader渲染

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  9. Unity3D之高级渲染-Shader Forge增强版

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑.畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

随机推荐

  1. js创建对象 object.create()用法

    Object.create()方法是ECMAScript 5中新增的方法,这个方法用于创建一个新对象.被创建的对象继承另一个对象的原型,在创建新对象时可以指定一些属性. 语法: Object.crea ...

  2. Q&As:1.cocos2d-html5如何获得鼠标划过事件

    不喜欢按部就班学东西,感觉各种框架各种技术就应该是拿到手用的,这应该是导致我现在学了这么多却没一样精通的缘故吧. 发现自己喜欢在QQ群回答一些菜鸟的问题,就算自己不清楚也会乐意看代码帮助解决╮(╯_╰ ...

  3. 如何写一个简单的HTTP服务器(重做版)

    最近几天用C++重新写了之前的HTTP服务器,对以前的代码进行改进.新的HTTP服务器采用Reactor模式,有多个线程并且每个线程有一个EventLoop,主程序将任务分发到每个线程,其中采用的是轮 ...

  4. 修改索引名称(mysql)

    MySQL修改索引名称. 对于MySQL 5.7及以上版本,可以执行以下命令: ALTER TABLE tbl_name RENAME INDEX old_index_name TO new_inde ...

  5. JS Windows.document对象

    四中选择器:class ,id , name , 标签 通过选择器获取对象: ...................................ClassName('');  -- class选择 ...

  6. ubuntn 安装软件

    安装输入法 一.Ctrl+Alt+T打开终端,输入sudo apt-get install fcitx,安装fcitx插件. 二.打开input method,选择fcitx. 三.打开system ...

  7. win7升级到win10,出现算术运算溢出问题

    前台winform,后台java代码是: OutputStream ou=(OutputStream)response.getOutputStream(); ou.write(rightSet.get ...

  8. 二、Django快速安装

    一.安装Python 作为一个Python Web框架,Django依赖Python.从Django适用于哪些版本的Python可以获取更多信息.较新版本的Python内置一个轻量级的数据库SQLit ...

  9. python终端计算器,还有没其他方法?

    import sysdef lt(a, b, c ): if b == "+": return int(a)+int(c) elif b == "-": ret ...

  10. 【ZABBIX】SNMPtrap实现主动监控的原理与安装配置

    工欲善其事,必先利其器.作为一款强大的开源软件,Zabbix号称“Monitor Everything”,其所依赖的,很大程度上便是SNMP的数据采集支持.SNMP 协议是用来管理设备的协议,目前SN ...