Unity5 怎么把Meshecharts 渲染完成事件成RenderTexture

2310人阅读
最近在做一个小项目,需要将模型作为UI显示在屏幕上,所以使用了RenderTexture。制作过程大概为新建一个摄像机对准模型物体,新建RenderTexture被这个摄像机引用,摄像机背景设为透明。使用NGUI,新建一个UITexture,将此RederTexture作为材质赋给它。而该模型为了实现半透明效果用了Transparent/Deffuse的Shader。设想中此时半透明的模型渲染在屏幕上了,但此时问题出现了,屏幕上空空如也!如果此时我们试着把摄像机背景从0调高的时候,物体会出现,它的透明的似乎随着摄像机的背景的透明度在变化,而尴尬的是我们不需要摄像机背景,不管是天空盒也好还是颜色也好。问题就是物体会随着摄像机的背景而隐去。排查之后问题出现在模型的材质上,也就是Transparent/Diffuse的Shader上。当我们用普通的Diffuse的Shader的时候模型完整地显示在屏幕上,摄像机背景也为透明,只是无法实现模型的半透明的效果。本人水平有限,一直百思不得其解,物体单独使用了一个材质,为什么它的半透明图像会随着摄像机背景而隐去?直到最近接触了Shader。该问题已经解决,但其中的原理还没搞清楚。解决方法是我们要实现物体的半透明效果,但不能使用Unity自带的Transparent/Diffuse的Shader。自己写一个最简单的Shader即可。新建Shader,代码如下:
Shader &Custom/Transparent&
Properties
_MainTex (&Base (RGB)&, 2D) = &white& {}
_Color(&MainColor&,Color)=(1.0,1.0,1.0,1.0)
Tags { &RenderType&=&Transparent& }
#pragma surface surf Lambert
sampler2D _MainT
struct Input
float2 uv_MainT
void surf (Input IN, inout SurfaceOutput o)
half4 c = tex2D (_MainTex, IN.uv_MainTex)*_C
o.Albedo = c.
o.Alpha = c.a;
FallBack &Diffuse&
&/pre&&p&&/p&&pre&没有加注释,相信有基础的一眼就能看懂,没有接触过的也没必要去明白,解决问题就行。这里就加了一张简单的纹理贴图,没用其他贴图。模型使用这个Shader就可以任意修改透明度,而不会受摄像机背景的影响。
为了探究原因,找到了Unity自带的Transparent/Diffuse的源码:
&span style=&font-size:18&&Shader &Transparent/Diffuse& {
Properties {
_Color (&Main Color&, Color) = (1,1,1,1)
_MainTex (&Base (RGB) Trans (A)&, 2D) = &white& {}
SubShader {
Tags {&Queue&=&Transparent& &IgnoreProjector&=&True& &RenderType&=&Transparent&}
#pragma surface surf Lambert alpha
sampler2D _MainT
struct Input {
float2 uv_MainT
void surf (Input IN, inout SurfaceOutput o)
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _C
o.Albedo = c.
o.Alpha = c.a;
Fallback &Transparent/VertexLit&
其实区别不大。问题就出现在&span style=&font-size:18&&#pragma surface surf Lambert alpha&/span&这一行。我们自己写的用的为:
&span style=&font-size:18&&#pragma surface surf Lambert&/span&
就这一点的差别。添加alpha关键字其实是告诉Unity使用Lambert光照模型并且我们将渲染一个透明的Surface。在Unity中渲染一个透明物体标准的做法是声明这两句:
Tags { &RenderType&=&Transparent& }#pragma surface surf Lambert alpha
此时这个透明材质会与其他透明材质一起渲染。而并不表明只有声明了这两句材质才带有透明通道。实际上如果我们这样声明:
&span style=&font-size: 18&&&/span&Tags { &RenderType&=&Opaque& }&span style=&font-family: Arial, Helvetica, sans-&&&/span&#pragma surface surf Lambert物体同样可以带有透明材质,但这时它是与普通非透明材质一起渲染的。非常规的做法解决了问题,而Unity内部的原理还需要研究。
个人理解,欢迎批评指正。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7657次
排名:千里之外Unity中Mesh分解与边缘高亮加上深度检测_Unity3D教程_中国AR网
&当前位置: &
一个比较简单的需求,不过遇到些坑,记录下。  房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMesh对应的Material。如一个桌子的Mesh,其实有二个材质,分别对应二个SubMesh,一个桌面和一个桌脚,点击桌面后,只有这个桌面高光,而不是整个桌子,并且能单独更换这个桌面的Material.  我们知道Unity中,Mesh和Ogre一样,也是可以有多个SubMesh,每个SubMesh有自己的Material,但是不同Ogre每个Submesh可以有不同的顶点数据,Unity中Mesh所有SubMesh共享相同顶点数据,分别使用不同的顶点索引。我原来做过一个项目,用Ogre里的Renderable与MovableObject组合形成这种格式,里面的所有模型都是用的这种格式显示,而不是Ogre本身的Entiy,当时就发现这种更容易理解,好用。  下面这个脚本文件是这个功能的具体实现,包含分解Mesh,检查具体是那个SubMesh碰撞等功能。&
&&&&&&cIndex&=&-&Material&lineMat&=&&Material&selectMat&=&
&&&&&MeshFilter&meshFilter&=&&MeshRenderer&meshRender&=&&MeshCollider&meshCollider&=&&BoxCollider&boxCollider&=&&&Transform&transform&=&&LineRenderer&lineRender&=&&HighlightableObject&hightLight&=&&&vminDist&=&&List&&&indexLay&=&&List&&&&bPreObject&=&&&preIndex&=&&Mesh&mesh&=&
&&&&&&defaultAdd&=&&RaycastHit&preHit&=&&&bHold&=&&Vector3&oldLocation&=&Dictionary&,&List&&&&matTextures&=&&Dictionary&,&List&&&=&Resources.Load&Material&(=&checkDefault&MeshFilter&=&checkDefault&MeshCollider&=&checkDefault&MeshRenderer&=&checkDefault&BoxCollider&=&checkDefault&Transform&=&checkDefault&LineRenderer&=&checkDefault&HighlightableObject&=&=,&
&&&&&&&&.gameObject.layer&=&=&,&matTextures,&XmlReader.ParseMatXml,&&&T&()&=&.gameObject.GetComponent&T&&(t&==&=&.gameObject.AddComponent&T&
&&&&&UNITY_EDITOR&&&&&&&&&(Input.GetMouseButtonDown()&&&&!&UNITY_ANDROID&||&UNITY_IPHONE&&&&&&&&&(Input.touchCount&&&&&&&Input.GetTouch().phase&==&TouchPhase.Began&&&&&!EventSystem.current.IsPointerOverGameObject(Input.GetTouch(=&bAxis&=&Physics.Raycast(ray,&&hit,&,&&&&&==&=
&&&&&&&&&&&&&(GetMinDist(ray,&&(preCollider&!=&=&
&&&&&&&&&&&&&&&&bPreObject&=&hit.collider&==&(!bPreObject&&&&preCollider&!=&=
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&(selectMat&!=&&haveTexture&=
&&&&&&&&&&&&&&&&&&&&&&&&&(defaultAdd&||&(defaultAdd&||&UNITY_EDITOR&&&&&&&&&(Input.GetMouseButtonUp(&UNITY_ANDROID&||&UNITY_IPHONE&&&&&&&&&(Input.touchCount&&&&&&&Input.GetTouch().phase&===&&&&UNITY_EDITOR&&&&&&&&&(bHold&&&&Input.GetMouseButton(&UNITY_ANDROID&||&UNITY_IPHONE&&&&&&&&&(bHold&&&&Input.touchCount&&&&&&&Input.GetTouch().phase&===&newPot&=&ray.origin&+&ray.direction&*&preHit.distance&-=&&GetMinDist(Ray&ray,&=&&hits&=&origin&=&minDist&=&&result&=&&(&hit&&(hit.collider&==&meshCollider&||&hit.collider&==&sqrLenght&=&(hit.point&-&(sqrLenght&&===&&&render&=&collider.GetComponent&Renderer&&filter&=&collider.GetComponent&MeshFilter&&(render&!=&&&&&filter&!=&
&&&&&&&&&&&&transform.position&====
&&&&&&&&&&&&&minDist&=&=&=&=&=&====
&&&&&&&&&&&&&(filter.mesh.subMeshCount&&&&(&meshIndex&=&;&meshIndex&&&filter.mesh.subMeshC&meshIndex++=&=&&indexs&=&(indexs.Length&/&&&&=&====&==&(currentCollider.Raycast(ray,&&hit,&&sqrLenght&=&(Camera.main.transform.position&-
&&&&&&&&&&&&&&&&&&&&&&&&&(Mathf.Abs(sqrLenght&-&minDist)&&&(!&(!&(sqrLenght&&===&mesh.bounds.center&-&mesh.bounds.size&/=&mesh.bounds.center&+&mesh.bounds.size&/
&&&&&&&&&&&&&(indexLay.Count&&&&&&&nIndex&==&++nIndex&%=&(cIndex&&=&&&&&render.materials.Length&&=
&&&&&&&&&&&&&&&&&indexs&==
&&&&&&&&&&&&&&&&meshRender.material&=&vertexs&=
&&&&&&&&&&&&&&&&meshRender.enabled&=&&&&=&&&&cornerDirty&=&&Vector3&min&=&Vector3&max&=&Vector3[]&mCorners&=&&Vector3[==&==&&&(cmp.x&&=&(cmp.y&&=&(cmp.z&&=&&(cmp.x&&=&(cmp.y&&=&(cmp.z&&=&=&&===&&&&&
&&&&&&&&&]&=].x&=&min.x;&mCorners[].y&=&max.y;&mCorners[].z&=].x&=&max.x;&mCorners[].y&=&max.y;&mCorners[].z&=].x&=&max.x;&mCorners[].y&=&min.y;&mCorners[].z&=]&=].x&=&min.x;&mCorners[].y&=&max.y;&mCorners[].z&=].x&=&min.x;&mCorners[].y&=&min.y;&mCorners[].z&=].x&=&max.x;&mCorners[].y&=&min.y;&mCorners[].z&=&i&=&=&&Vector3[
&&&&&&&&pos[i++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[
&&&&&&&&pos[i++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[
&&&&&&&&pos[i++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[
&&&&&&&&pos[i++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[
&&&&&&&&pos[i++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[++]&=&.Corners[=&=&=&=  需要注意的点是:  1&如果几个模型有多个SubMesh分散在各个位置,故需要把所有RaycastHit上碰撞点与眼睛求出最近点。  2 LineRender中是N点组成N-1条线,而不是N/2,如A-B-C-D,并不是显示AB,CD.而是AB,BC,CD.  3 模型的SubMesh可能边框重合,这样的话,就会导致可能永远都是选的其中一个。  4 我们根据SubMesh生成新的Mesh,并不需要在主摄像头中渲染(通过Layer与cullingMask组合),不然和原来模型的SubMesh显示不清。  5 鼠标按下,是否在UI上面,鼠标弹起,电脑与移动平台要不同的处理。  6 安卓平台下,用WWW加载资源,必需用yield return,故相应加载完成的处理可以用函数指针传入。  到这模型就差不多了,然后添加边缘高亮组件highightingSystem,这个的思路也是比较简单的。  首先在主摄像机渲染场景前,把边缘高亮的模型给一个单独的层,并且修改相应材质为我们需要高亮的颜色,然后复制主摄像头新生成一个摄像头,新摄像头的cullingMask只渲染前面边缘高亮模型的层的那些模型到一张Stencil的RTT中保存,然后把原来的边缘高亮的模型的层和材质换回来。  然后是主摄像头正常渲染,渲染完后,在OnRenderImage中先把在上面的那张RTT进行简单的Blur模糊,保存为Blur的RTT。最后把上面的Stencil的RTT,Blur的RTT,主摄像头渲染的source,我们并不渲染stencil本身,只渲染stencil模糊后的边缘部分。  嗯,现在有个麻烦,老大要在看不到的部分不显示高亮,如下这样:  &  第一张图是现在的显示效果,老大要的是第二张,说实话,我最开始以为很简单,好吧,做完后就加了点东东,确实不复杂,但是因为对Unity的相关理解有误,把采过的坑说下。  说实话,这个需求就是加个深度检测就行了,那么在原来基础上添加如下一些代码。=&refCam.projectionM&&&&&&&&shaderCamera.cullingMask&==&==&=&=&==shaderCamera.depthTextureMode&=depthBuffer&=&RenderTexture.GetTemporary(()GetComponent&Camera&().pixelWidth,&()GetComponent&Camera&().pixelHeight,&=);  Shader.Shader&&=&&vertex&vert&&&&&&&&&&&&&fragment&frag
&&&&&&&&&&&&
&&&&&&&&&&&&==&v.texcoord.&
&&&&&&&&&&&&&&&&o.depth&=
&&&&&&&&&&&&&&&&&float4(i.depth,,,  在这我进行一次尝试,结果不对,在shaderCamera.Render()渲染之前,设定depthTextureMode为Depth,我在Shader开始应用_CameraDepthTexture,发现结果不对,网上查找说是这个RTT一直是主摄像头的,后面使用_LastCameraDepthTexture,结果很奇怪,和后面主摄像头的_CameraDepthTexture比对结果完全对不上,深度值不是0或1,但是渲染出来看,深度值又没看到变化,后来仔细想了下,应该是主摄像头Graphics.Blit后的值,因为这个只是渲染一个正方形,深度显示出来就会这样。  最后去Unity5Shader里面找_CameraDepthTexture这个RTT是如何渲染的,我们找到这个值COMPUTE_DEPTH_01是放入深度RTT中的,具体意思大家去unityCG.cginc里去找就行了,因为这个值就是根据当前顶点的位置算出来的,所以在这我们放入顶点着色器就行。  然后就是在第一张Blur模糊图上比较上一张深度RTT的深度值,相应DEPTH_COMP_ON位置为新增加的。&&&&
&&&&&&off&=Shader&,&2D)&=&,&Range(,))&=&,&2D)&=&&vertex&vert&&&&&&&&&&&&&fragment&frag&&&&&&&&&&&&&fragmentoption&ARB_precision_hint_fastest&&&&&&&&&&&&&multi_compile&__&DEPTH_COMP_ON&
&&&&&&&&&defined(DEPTH_COMP_ON)
&&&&&&&&&&&&==&_MainTex_TexelSize.xy&*].x&=&v.texcoord.x&-].y&=&v.texcoord.y&-].x&=&v.texcoord.x&+].y&=&v.texcoord.y&-].x&=&v.texcoord.x&+].y&=&v.texcoord.y&+].x&=&v.texcoord.x&-].y&=&v.texcoord.y&+=&(_MainTex_TexelSize.y&&&=&&-=&tex2D(_MainTex,&i.uv[=&tex2D(_MainTex,&i.uv[=&tex2D(_MainTex,&i.uv[=&tex2D(_MainTex,&i.uv[====&(color1.a&+&color2.a&+&color3.a&+&color4.a)&*&defined(DEPTH_COMP_ON)&&&&&&&&&&&&&&&&&cDepth&=&oDepth&=
&&&&&&&&&&&&&&&&&(abs(oDepth&-&cDepth)&&&=&fixed4(,,,  注意:  1 我们只需要比较第一张模糊图的深度,后面的模糊都是根据这张再重新模糊,因此我们在着色器定义编译符,使之第一次与后面几次根据编译符不同的执行。  2 在深度比较的Shader中,我们其实已经取不到原顶点pos相应的值了,因为我们并不是渲染原来的模型,而是相当于Ogre中的后处理PassQuad(只渲染一个正方形),因此,在这之前,需要将主摄像根据情况,先把设定主摄像头的depthTextureMode为Depth,这样在OnPreRender之后,主摄像头正常渲染前,先调用UpdateDepthTexture,渲染场景内所有模型的深度到_CameraDepthTexture上,这样在后面的OnRenderImage中,我们才能取到正常的深度值。  3 在这,二张深度图里默认的精度都只有16位,因此需要定义一个范围。  有几次试错,都在于没搞清Unity里的执行过程,后来结合Untiy提供的Frame Debugger,才搞定这个简单的修改。
中国AR网()为更好的服务国内AR技术爱好者 ,现已推出“AR那些事”官方公众号,请在微信公众账号中搜索「AR网」或者加QQ群:,即可获得每日内容推送和最新的AR开发教程及AR H游戏资源哦!
上一篇: 下一篇:
有话您说 访客日VR虚拟现实AR日VR虚拟现实AR日VR虚拟现实AR日VR虚拟现实AR日Unity3D学习笔记——组件之Mesh(网格) - 有情怀的人 - 推酷
Unity3D学习笔记——组件之Mesh(网格) - 有情怀的人
:网格组件。主要用于设置外形和外表。
Mesh Filter
:网格过滤器。就是为游戏对象添加一个外形。
例:设置外形为Sphere
如果获取的网格拥有蒙皮信患,Unity将自动创建一个sknned Mesh Renderer。
注意:在使用Mesh Filter的时候必须同时提供一个Mesh Renderer组件,因为需要将其渲染出来,否则你不见他。
:文件过滤器,用于显示3D文字的。
例:文字内容为TT
其中的Font属性用于设置文字的字体,字体可以自己导入使用。
注意:同Mesh Filter一样,在使用的时候必须同时提供一个Mesh Renderer组件,因为需要将其渲染出来,否则你不见他。
Mesh Renderer
:网格渲染器。用于渲染网格显示游戏对象。
例:添加了两个贴图的渲染器。
其中的Use Light Probes用于
Materials可以放置多张贴图,用于显示在游戏对象的外表。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 angular 渲染完成事件 的文章

 

随机推荐