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

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

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

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

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

using System;
using UnityEngine;
using System.Collections;
using EasyAR; public class Coloring3D : MonoBehaviour
{ public MeshRenderer realityPlane;
public Camera rendercamera;
private Vector3[] marks;
private Material cubeMat;
private Vector2 sizeVector2;
private Vector2 webcamTex2ScreenScale;
private ImageTargetBehaviour imageTargetBehaviour;
private Texture2D scanTexture2D;
private bool isSetupScale = false; // Use this for initialization
void Start ()
{
Init();
} public void Init()
{
marks = new Vector3[4];
sizeVector2 = new Vector2();
imageTargetBehaviour = transform.GetComponentInParent<ImageTargetBehaviour>();
sizeVector2 = imageTargetBehaviour.Size; //计算识别Plane的4个角的位置
for (int i = 0; i < marks.Length; i++)
{
float x = -1, y = -1;
if ((i + 1) % 2 == 0)
x = 1;
else
x = -1;
if (i >= 2)
y = 1;
marks[i] = new Vector3(sizeVector2.x / 2 * x, 0, sizeVector2.y / 2 * y);
} } void SetupScale()
{
//if (!imageTargetBehaviour.GetIsShow())//判断模型是不是显示出来,可以注释掉
//return;
if (!isSetupScale)
{
cubeMat = this.transform.GetComponent<MeshRenderer>().material; var texture = realityPlane.material.mainTexture;//获取摄像头照到的纹理图片
cubeMat.mainTexture = texture;//将纹理赋值到材质球上 //计算屏幕和整张图片的比例
var maxScale = Mathf.Max((float)Screen.width / texture.width, (float)Screen.height / texture.height); var t2sWidth = texture.width * maxScale;
var t2sHeight = texture.height * maxScale; webcamTex2ScreenScale.x = Screen.width / t2sWidth;
webcamTex2ScreenScale.y = Screen.height / t2sHeight;
isSetupScale = true;
} for (int i = 0; i < marks.Length; i++)
{
marks[i] = marks[i] + this.transform.parent.position;
var pos =
AdjustUV(rendercamera.WorldToViewportPoint(marks[i]));
string posName = String.Format("p{0}", i);
cubeMat.SetVector(posName, pos);//传入到shader进行纹理的拉伸
} } Vector4 AdjustUV(Vector3 v)
{
//识别图在屏幕的位置
var webcamX = FixWebcamTextureToScreenUV(v.x, webcamTex2ScreenScale.x);
var webcamY = FixWebcamTextureToScreenUV(v.y, webcamTex2ScreenScale.y);
return new Vector4(webcamX*v.z, (1 - webcamY)*v.z, v.z, 1.0f);
} float FixWebcamTextureToScreenUV(float value, float scale)
{
return (1.0f - scale) * 0.5f + value * scale;
} // Update is called once per frame
void OnWillRenderObject()
{
SetupScale();
}
}

接下来是shader:

Shader "Unlit/PaintingShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100 Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
}; sampler2D _MainTex;
float4 p0;
float4 p1;
float4 p2;
float4 p3; v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv.x = v.uv.x;
o.uv.y = v.uv.y;
return o;
} fixed4 frag (v2f i) : SV_Target
{
float2 mid;
float3 newUV; //计算纹理的位置
if (i.uv.x + i.uv.y >= 1) {
mid = i.uv;
newUV = p0 * (1 - mid.x - mid.y) + p1 * mid.x + p2 * mid.y;
} else {
mid = float2(1 - i.uv.y, i.uv.x + i.uv.y - 1);
newUV = p2 * (1 - mid.x - mid.y) + p1 * mid.x + p3 * mid.y;
}
//返回计算好的纹理位置
return tex2D(_MainTex, newUV.xy / newUV.zz);
} ENDCG
}
}
}

这里看看效果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. 函数parseQuery用于解析url查询参数

    在百度上找的,以后忘了再看. 语法如下: var obj = parseQuery(query) query是被解析的查询参数,函数返回解析后的对象. 使用范例如下: var jerry = pars ...

  2. linux下各文件夹的结构说明及用途介绍(转载)

    详细介绍文档 转载文章路径 /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户 ...

  3. 如何在Ubuntu 18.04上安装Go

    如何在Ubuntu 18.04上安装Go 谢鸢发表于云计算教程系列订阅98 介绍 课程准备 第1步 - 安装Go 第2步 - 设置Go路径 第3步 - 测试您的安装 结论 介绍 Go是Google开发 ...

  4. 如何成为优秀评级卖家(Top-rated seller)?与超级卖家的区别是

    以eBay美国站点为例,要成为优秀评级卖家(Top-rated seller),需满足如下条件: ● 先成为 eBay超级卖家 ● Low DSR (US buyers) <= 0.50% 或 ...

  5. 手机上Uncaught ReferenceError: __WEBPACK_AMD_DEFINE_ARRAY__ is not defined的错误

    问题: vue2.0和webpack2.X的写的项目在电脑的浏览器上打开正常,在手机浏览器中访问页面的时候不能正常显示,空白. 通过chrome的真机调试chrome://inspect/#devic ...

  6. Beta版软件使用说明

    1引言 1 .1编写目的 编写本使用说明的目的是充分叙述本软件所能实现的功能及其运行环境,以便使用者了解本软件的使用范围和使用方法,并为软件的维护和更新提供必要的信息. 1 .2参考资料 1 .3术语 ...

  7. 第一次c++团队合作作业期间第一篇随笔

    分析了自己分到的任务,我的理解是这样的:首先要生成程序主框架,在主框架中进行地图的描绘.我应该是先进行地图的拼接,把建筑物和地面都拼接好.然后再在地图上显示出英雄和小兵.同时还要在主框架中分析了自己分 ...

  8. PAT L1-032 Left-pad

    https://pintia.cn/problem-sets/994805046380707840/problems/994805100684361728 根据新浪微博上的消息,有一位开发者不满NPM ...

  9. WOL*LAN远程换醒命令行方法

    wol远程唤醒需要网卡的支持,现在一般的网卡也都支持,只有有线网络能实现. 这里介绍Wake On Lan Command Line的使用 下载地址 https://www.depicus.com/w ...

  10. 移植spdylay到libcurl

    Libcurl是第三方网络库,支持各种网络协议 SPDY是Google提出的用来替代HTTP1.1的网络协议, 目前google.com, facebook.com, twitter.com服务器端都 ...