ImageTracking_Coloring3D¶
演示如何创建“AR涂涂乐”,使绘图书中的图像实时“转换”成3D
sample可以捕捉相机画面作为模型贴图,达到即画即贴的效果。
用法¶
FindBear/Freeze/Thaw:未找到bear图像时会显示FindBear。Freeze表示点击button将会固定熊的贴图。当显示Thaw表示点击button将会固定熊的贴图恢复为动态抓取相机图像状态。
详解¶
映射target区域的相机图像到模型上¶
使用 CameraImageRenderer.RequestTargetTexture 来注册获取纹理的handler来获取camera图像的纹理并在shader中使用它。
CameraRenderer.RequestTargetTexture((camera, texture) => { renderTexture = texture; });
获取当前场景中识别图四个角点的world transform。
var halfWidth = 0.5f;
var halfHeight = 0.5f / imageTarget.Target.aspectRatio();
Matrix4x4 points = Matrix4x4.identity;
Vector3 targetAnglePoint1 = imageTarget.transform.TransformPoint(new Vector3(-halfWidth, halfHeight, 0));
Vector3 targetAnglePoint2 = imageTarget.transform.TransformPoint(new Vector3(-halfWidth, -halfHeight, 0));
Vector3 targetAnglePoint3 = imageTarget.transform.TransformPoint(new Vector3(halfWidth, halfHeight, 0));
Vector3 targetAnglePoint4 = imageTarget.transform.TransformPoint(new Vector3(halfWidth, -halfHeight, 0));
points.SetRow(0, new Vector4(targetAnglePoint1.x, targetAnglePoint1.y, targetAnglePoint1.z, 1f));
points.SetRow(1, new Vector4(targetAnglePoint2.x, targetAnglePoint2.y, targetAnglePoint2.z, 1f));
points.SetRow(2, new Vector4(targetAnglePoint3.x, targetAnglePoint3.y, targetAnglePoint3.z, 1f));
points.SetRow(3, new Vector4(targetAnglePoint4.x, targetAnglePoint4.y, targetAnglePoint4.z, 1f));
material.SetMatrix("_UvPints", points);
...
为了使用这块区域的图像作为模型贴图,需要在shader中计算像素的屏幕位置并获取纹理数值。
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
float4 top = lerp(_UvPints[0], _UvPints[2], o.uv.x);
float4 bottom = lerp(_UvPints[1], _UvPints[3], o.uv.x);
float4 fixedPos = lerp(bottom, top, o.uv.y);
float4x4 Rendering_Matrix_VP = mul(_RenderingProjectMatrix, _RenderingViewMatrix);
o.fixedPos = ComputeGrabScreenPos(mul(Rendering_Matrix_VP, fixedPos));
return o;
}
float4 frag (v2f i) : COLOR
{
float2 coord = i.fixedPos.xy / i.fixedPos.w;
...
return tex2D(_MainTex, coord);
}
这里还有一个特殊问题需要处理。Unity在使用插件创建的RenderTexture时无法隐藏不同平台的不同,因此在渲染管线中使用这个纹理时,你需要正确处理不同渲染API下 render texture坐标的不同 。
float4 frag (v2f i) : COLOR
{
float2 coord = i.fixedPos.xy / i.fixedPos.w;
#if SHADER_API_METAL
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0.0)
coord.y = 1.0 - coord.y;
#endif
coord.x = 1.0 - coord.x;
#else
#if UNITY_UV_STARTS_AT_TOP
coord.y = 1.0 - coord.y;
#endif
#endif
return tex2D(_MainTex, coord);
}
停止实时纹理更新¶
某些情况下,可能会需要使用在某些视角或特定时间点的图像作为模型贴图。
freezedTexture = new RenderTexture(renderTexture.width, renderTexture.height, 0);
Graphics.Blit(renderTexture, freezedTexture);
material.SetTexture("_MainTex", freezedTexture);