• Unity中Mesh分解与边缘高亮加上深度检测


      一个比较简单的需求,不过遇到些坑,记录下。

      房间有多个模型,每个模型可能多个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碰撞等功能。

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using System;
    using UnityEngine.EventSystems;
    
    public class RayCheck : MonoBehaviour
    {
        //public MaterialUI ui;
        public NewUIControl ui;
    
        private Collider preCollider;
        private int cIndex = -1;
        private Material lineMat = null;
        private Material selectMat = null;
        //private Material showMat = null;
        private MeshFilter meshFilter = null;
        private MeshRenderer meshRender = null;
        private MeshCollider meshCollider = null;
        private BoxCollider boxCollider = null;
        private new Transform transform = null;
        private LineRenderer lineRender = null;
        private HighlightableObject hightLight = null;
    
        private float vminDist = 1.0f;
        private List<int> indexLay = new List<int>();
        private bool bPreObject = false;
        private int preIndex = 0;
        private Mesh mesh = null;
        //如果为true,所有模型都能切换texture
        public bool defaultAdd = true;
    
        private RaycastHit preHit = new RaycastHit();
        private bool bHold = false;
        private Vector3 oldLocation = Vector3.zero;
    
        private Dictionary<string, List<string>> matTextures = new Dictionary<string, List<string>>();
        void Start()
        {
            lineMat = Resources.Load<Material>("LineMat");
            //showMat = Resources.Load<Material>("ShowMat");
    
            meshFilter = checkDefault<MeshFilter>();
            meshCollider = checkDefault<MeshCollider>();
            meshRender = checkDefault<MeshRenderer>();
            boxCollider = checkDefault<BoxCollider>();
            transform = checkDefault<Transform>();
            lineRender = checkDefault<LineRenderer>();
            hightLight = checkDefault<HighlightableObject>();
    
            lineRender.useWorldSpace = false;
            lineRender.sharedMaterial = lineMat;
            lineRender.SetWidth(0.01f, 0.01f);
            //meshRender.sharedMaterial = showMat;
            //单独添加层,在正常渲染时,让摄像机不渲染这个模型,我们只需要在高光时渲染
            this.gameObject.layer = 4;
            mesh = new Mesh();
    
            StartCoroutine(XmlReader.GetXML("materialtextures.xml", matTextures, XmlReader.ParseMatXml, this.InitUiMatTextures));
            //ui.onApply = ApplyMaterial;      
        }
    
        public void InitUiMatTextures()
        {
            ui.SetMatTextures(matTextures);
        }
    
        T checkDefault<T>() where T : Component
        {
            T t = this.gameObject.GetComponent<T>();
            if (t == null)
            {
                t = this.gameObject.AddComponent<T>();
            }
            return t;
        }
    
        // Update is called once per frame
        void Update()
        {
            //!ui.isActiveAndEnabled &&
    #if UNITY_EDITOR
            if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
    #elif UNITY_ANDROID || UNITY_IPHONE
            if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began  && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
    #endif
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                var bAxis = Physics.Raycast(ray, out hit, 10000.0f, 2 << 7);
                if (bAxis)
                {
                    preHit = hit;
                    bHold = true;
                    oldLocation = preCollider.transform.position;
                    return;
                }
                //与当前camera最近交点
                if (GetMinDist(ray, out hit))
                {
                    if (preCollider != null)
                    {
                        lineRender.enabled = false;
                    }
                    //如果不是同一个模型,indexLay清空
                    bPreObject = hit.collider == preCollider;
                    if (!bPreObject && preCollider != null)
                    {
                        preCollider.gameObject.SetActive(true);
                        indexLay.Clear();
                    }
                    preCollider = hit.collider;
                    //得到选择的gameObject模型
                    if (checkIsRender(hit.collider, ray))
                    {
                        //preCollider.gameObject.SetActive(false);
                        if (selectMat != null)
                        {
                            var haveTexture = ui.SetSelectMat(selectMat);
                            //当前材质有对应能够更新的纹理
                            if (defaultAdd || haveTexture)
                                ui.gameObject.SetActive(true);
                            else
                                ui.gameObject.SetActive(false);
                            //显示高亮
                            hightLight.ReinitMaterials();
                            hightLight.FlashingOn(2f);
                            if (defaultAdd || haveTexture)
                                hightLight.On();
                            else
                                hightLight.Off();
                        }
                    }
                }
            }
    #if UNITY_EDITOR
            if (Input.GetMouseButtonUp(0))
    #elif UNITY_ANDROID || UNITY_IPHONE
            if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
    #endif
            {
                bHold = false;
            }
        }
    
        public void FixedUpdate()
        {
            DragAxis();
        }
    
        public void DragAxis()
        {
    #if UNITY_EDITOR
            if (bHold && Input.GetMouseButton(0))
    #elif UNITY_ANDROID || UNITY_IPHONE
            if (bHold && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
    #endif
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                var newPot = ray.origin + ray.direction * preHit.distance - preHit.point;
                preCollider.transform.position = newPot;
            }
        }
    
        public bool GetMinDist(Ray ray, out RaycastHit rayHit)
        {
            rayHit = new RaycastHit();
            var hits = Physics.RaycastAll(ray);
            var origin = Camera.main.transform.position;
            float minDist = float.MaxValue;
            bool result = false;
            foreach (var hit in hits)
            {
                if (hit.collider == meshCollider || hit.collider == boxCollider)
                    continue;
                var sqrLenght = (hit.point - origin).sqrMagnitude;
                if (sqrLenght < minDist)
                {
                    minDist = sqrLenght;
                    rayHit = hit;
                    result = true;
                }
            }
            return result;
        }
    
        public bool checkIsRender(Collider collider, Ray ray)
        {
            var render = collider.GetComponent<Renderer>();
            var filter = collider.GetComponent<MeshFilter>();
            if (render != null && filter != null)
            {
                //设置成当成位置
                transform.position = render.transform.position;
                transform.rotation = render.transform.rotation;
                transform.localScale = render.transform.localScale;
                transform.parent = render.transform.parent;
    
                //初始化信息
                float minDist = float.MaxValue;
                AABB minAABB = new AABB();
                cIndex = 0;
                selectMat = null;
    
                mesh.Clear();
                Collider currentCollider = null;
                mesh.vertices = filter.mesh.vertices;
                mesh.normals = filter.mesh.normals;
                mesh.uv = filter.mesh.uv;
                mesh.uv2 = filter.mesh.uv2;
    
                //使用如下语句,颜色包含GI能正确使用,描边不能用,可能与UV有关。
                //不使用,模型对应GI颜色不对,但是描边能用。
                //解决方法: 定义raycheck自己的gameObject的层为单独一层,这样当前模型不渲染,只渲染描边
                //meshRender.useLightProbes = render.useLightProbes;
                //meshRender.lightmapIndex = render.lightmapIndex;
                //meshRender.lightmapScaleOffset = render.lightmapScaleOffset;
                //meshRender.realtimeLightmapIndex = render.realtimeLightmapIndex;
                //meshRender.realtimeLightmapScaleOffset = render.realtimeLightmapScaleOffset;
    
                //如果有多个SubMesh,重新分割每个SubMesh,并重新验证相交,取最近subMesh
                if (filter.mesh.subMeshCount > 1)
                {
                    for (int meshIndex = 0; meshIndex < filter.mesh.subMeshCount; meshIndex++)
                    {
                        meshCollider.enabled = false;
                        boxCollider.enabled = false;
                        var indexs = filter.mesh.GetIndices(meshIndex);
                        mesh.SetIndices(indexs, filter.mesh.GetTopology(meshIndex), 0);
    
                        if (indexs.Length / 3 > 255)
                        {
                            boxCollider.enabled = true;
                            boxCollider.center = mesh.bounds.center;
                            boxCollider.size = mesh.bounds.size;
                            currentCollider = boxCollider;
                        }
                        else
                        {
                            meshCollider.enabled = true;
                            meshCollider.sharedMesh = mesh;
                            currentCollider = meshCollider;
                        }
                        RaycastHit hit;
                        if (currentCollider.Raycast(ray, out hit, 10000))
                        {
                            float sqrLenght = (Camera.main.transform.position - hit.point).sqrMagnitude;
                            //模型有多个subMesh,但是无论怎么点击,其中一个subMesh总是最近。
                            if (Mathf.Abs(sqrLenght - minDist) < vminDist)
                            {
                                if (!indexLay.Contains(cIndex))
                                {
                                    indexLay.Add(cIndex);
                                }
                                if (!indexLay.Contains(meshIndex))
                                {
                                    indexLay.Add(meshIndex);
                                }
                            }
                            if (sqrLenght < minDist)
                            {
                                minDist = sqrLenght;
                                cIndex = meshIndex;
                                minAABB.Min = mesh.bounds.center - mesh.bounds.size / 2f;
                                minAABB.Max = mesh.bounds.center + mesh.bounds.size / 2f;
                            }
                        }
                    }
                }
                //一个模型有多个SubMesh,并且每个SubMesh边框相重。
                if (indexLay.Count > 1 && preCollider)
                {
                    if (indexLay.Contains(preIndex))
                    {
                        var nIndex = indexLay.IndexOf(preIndex);
                        cIndex = ++nIndex % indexLay.Count;
                    }
                    preIndex = cIndex;
                }
    
                if (cIndex >= 0 && render.materials.Length > cIndex)
                {
                    selectMat = render.materials[cIndex];
                    //显示自己的Mesh
                    var indexs = filter.mesh.GetIndices(cIndex);
                    mesh.SetIndices(indexs, filter.mesh.GetTopology(cIndex), 0);
                    meshFilter.mesh = mesh;
                    //重新设置材质
                    meshRender.material = selectMat;
                    var vertexs = minAABB.LinePositions();
                    lineRender.SetVertexCount(vertexs.Length);
                    lineRender.SetPositions(vertexs);
                    //重置状态
                    //lineRender.enabled = true;
                    meshRender.enabled = true;
                    return true;
                }
            }
            return false;
        }
    
        public void ApplyMaterial()
        {
            meshRender.enabled = false;
            ui.gameObject.SetActive(false);
        }
    }
    
    public class AABB
    {
        private bool cornerDirty = true;
        private Vector3 min = Vector3.zero;
        private Vector3 max = Vector3.zero;
    
        public Vector3[] mCorners = new Vector3[8];
    
        public Vector3[] Corners
        {
            get
            {
                if (cornerDirty)
                {
                    GetAllCorners();
                }
                return mCorners;
            }
        }
    
        public Vector3 Min
        {
            get
            {
                return min;
            }
            set
            {
                min = value;
                cornerDirty = true;
            }
        }
    
        public Vector3 Max
        {
            get
            {
                return max;
            }
            set
            {
                max = value;
                cornerDirty = true;
            }
        }
    
        private void makeFloor(Vector3 cmp)
        {
            if (cmp.x < min.x)
                min.x = cmp.x;
            if (cmp.y < min.y)
                min.y = cmp.y;
            if (cmp.z < min.z)
                min.z = cmp.z;
        }
    
        private void makeCeil(Vector3 cmp)
        {
            if (cmp.x > max.x)
                max.x = cmp.x;
            if (cmp.y > max.y)
                max.y = cmp.y;
            if (cmp.z > max.z)
                max.z = cmp.z;
        }
    
        public void Merge(Vector3 cmp)
        {
            makeCeil(cmp);
            makeFloor(cmp);
            cornerDirty = true;
        }
    
        public void SetNull()
        {
            min = Vector3.zero;
            max = Vector3.zero;
            cornerDirty = true;
        }
    
        /// <summary>   
        ///
        private void GetAllCorners()
        {
            mCorners[0] = min;
            mCorners[1].x = min.x; mCorners[1].y = max.y; mCorners[1].z = min.z;
            mCorners[2].x = max.x; mCorners[2].y = max.y; mCorners[2].z = min.z;
            mCorners[3].x = max.x; mCorners[3].y = min.y; mCorners[3].z = min.z;
    
            mCorners[4] = max;
            mCorners[5].x = min.x; mCorners[5].y = max.y; mCorners[5].z = max.z;
            mCorners[6].x = min.x; mCorners[6].y = min.y; mCorners[6].z = max.z;
            mCorners[7].x = max.x; mCorners[7].y = min.y; mCorners[7].z = max.z;
        }
    
        public Vector3[] LinePositions()
        {
            int i = 0;
            Vector3[] pos = new Vector3[16];
            //前面
            pos[i++] = this.Corners[0];
            pos[i++] = this.Corners[1];
            pos[i++] = this.Corners[2];
            //下边
            pos[i++] = this.Corners[3];
            pos[i++] = this.Corners[0];
            pos[i++] = this.Corners[6];
            //右边  
            pos[i++] = this.Corners[7];
            pos[i++] = this.Corners[3];
            pos[i++] = this.Corners[2];
            //后面
            pos[i++] = this.Corners[4];
            pos[i++] = this.Corners[7];
            pos[i++] = this.Corners[6];
            //左边 上边
            pos[i++] = this.Corners[5];
            pos[i++] = this.Corners[1];
            pos[i++] = this.Corners[5];
            pos[i++] = this.Corners[4];
            return pos;
        }
    
        public AABB Clone()
        {
            AABB ab = new AABB();
            ab.min = this.min;
            ab.max = this.max;
            ab.cornerDirty = true;
            return ab;
        }
    }
    RayCheck

      需要注意的点是:

      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的相关理解有误,把采过的坑说下。

      说实话,这个需求就是加个深度检测就行了,那么在原来基础上添加如下一些代码。

    shaderCamera.CopyFrom(refCam);
    shaderCamera.projectionMatrix = refCam.projectionMatrix;        // Uncomment this line if you have problems using Highlighting System with custom projection matrix on your camera
    shaderCamera.cullingMask = layerMask;
    shaderCamera.rect = new Rect(0f, 0f, 1f, 1f);
    shaderCamera.renderingPath = RenderingPath.Forward;
    shaderCamera.hdr = false;
    shaderCamera.useOcclusionCulling = false;
    shaderCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
    shaderCamera.clearFlags = CameraClearFlags.Color;
    shaderCamera.targetTexture = stencilBuffer;
    //我们因为直接在渲染highlight object,故可以直接算出深度,并不需要在前面多渲染一次
    shaderCamera.depthTextureMode = DepthTextureMode.None;
    //通过culling mask(layerMask),只渲染highlight object       
    shaderCamera.Render();
    
    //渲染深度
    depthBuffer = RenderTexture.GetTemporary((int)GetComponent<Camera>().pixelWidth, (int)GetComponent<Camera>().pixelHeight, 16, RenderTextureFormat.RHalf);
    shaderCamera.targetTexture = depthBuffer;
    shaderCamera.RenderWithShader(DepthShader, null);
    添加渲染深度。

      Shader.

    Shader "Custom/Render depth buffer" {
        SubShader
        {
            Tags{ "RenderType" = "Opaque" }
            Pass
            {
                ZWrite Off
                ZTest Always
                Lighting Off
                Fog{ Mode Off }
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                //sampler2D_float _LastCameraDepthTexture;
                //sampler2D_float _CameraDepthTexture;
                struct v2f {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float depth : TEXCOORD1;
                };
                v2f vert(appdata_img v) {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.uv = v.texcoord.xy; //float2(v.texcoord.x, 1 - v.texcoord.y); //v.texcoord.xy;
                    o.depth = COMPUTE_DEPTH_01;
                    return o;
                }
                float4 frag(v2f i) : COLOR
                {
                    //float depth = SAMPLE_DEPTH_TEXTURE(_LastCameraDepthTexture, i.uv);
                    //float depthSample = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_LastCameraDepthTexture, i.uv));//_CameraDepthTexture _LastCameraDepthTexture
                    //return float4(depthSample, 0, 0, 0);
                    return float4(i.depth,0,0,0);
                }
                ENDCG
            }
        }
        FallBack Off
    }
    Render depth buffer

      在这我进行一次尝试,结果不对,在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位置为新增加的。

        // Downsamples source texture
        private void DownSample4x(RenderTexture source, RenderTexture dest)
        {
            float off = 1.0f;
            blurMaterial.SetFloat("_OffsetScale", off);
            blurMaterial.SetTexture("_DepthTex", depthBuffer);
            if (bBlueDepthTest)
            {
                blurMaterial.EnableKeyword("DEPTH_COMP_ON");
            }
            //blurMaterial.DisableKeyword("DEPTH_COMP_OFF");
            Graphics.Blit(source, dest, blurMaterial);
        }
    渲染第一次Blur.
    Shader "Hidden/Highlighted/Blur"
    {
        Properties
        {
            _MainTex("", 2D) = "" {}
            _Intensity("", Range(0.25,0.5)) = 0.3
            _DepthTex("", 2D) = "" {}
        }
    
            SubShader
        {
            Pass
            {
                ZTest Always
                Cull Off
                ZWrite Off
                Lighting Off
                Fog { Mode Off }
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #pragma multi_compile __ DEPTH_COMP_ON 
            //DEPTH_COMP_OFF
    
            #include "UnityCG.cginc"
    
            uniform sampler2D _MainTex;
            uniform half4 _MainTex_TexelSize;
            uniform half _OffsetScale;
            uniform fixed _Intensity;
    #if defined(DEPTH_COMP_ON)
                uniform sampler2D _DepthTex;
                sampler2D_float _CameraDepthTexture;
    #endif
                struct v2f
                {
                    float4 pos : POSITION;
                    half2 duv : TEXCOORD0;
                    half2 uv[4] : TEXCOORD1;
                };
    
                v2f vert(appdata_img v)
                {
                    // Shader code optimized for the Unity shader compiler
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    
                    half2 offs = _MainTex_TexelSize.xy * _OffsetScale;
    
                    o.uv[0].x = v.texcoord.x - offs.x;
                    o.uv[0].y = v.texcoord.y - offs.y;
    
                    o.uv[1].x = v.texcoord.x + offs.x;
                    o.uv[1].y = v.texcoord.y - offs.y;
    
                    o.uv[2].x = v.texcoord.x + offs.x;
                    o.uv[2].y = v.texcoord.y + offs.y;
    
                    o.uv[3].x = v.texcoord.x - offs.x;
                    o.uv[3].y = v.texcoord.y + offs.y;
    
                    o.duv = v.texcoord.xy;
                    if (_MainTex_TexelSize.y < 0)
                        o.duv.y = 1 - o.duv.y;
                    return o;
                }
    
                fixed4 frag(v2f i) : COLOR
                {
                    fixed4 color1 = tex2D(_MainTex, i.uv[0]);
                    fixed4 color2 = tex2D(_MainTex, i.uv[1]);
                    fixed4 color3 = tex2D(_MainTex, i.uv[2]);
                    fixed4 color4 = tex2D(_MainTex, i.uv[3]);
                    fixed4 color;
                    color.rgb = max(color1.rgb, color2.rgb);
                    color.rgb = max(color.rgb, color3.rgb);
                    color.rgb = max(color.rgb, color4.rgb);
                    color.a = (color1.a + color2.a + color3.a + color4.a) * _Intensity;
                    
    #if defined(DEPTH_COMP_ON)
                    float cDepth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.duv));
                    float oDepth = tex2D(_DepthTex, i.duv).r;
                    //当Blur桢的深度 大于 当前桢的深度
                    if (abs(oDepth - cDepth) > 0.001)
                    {
                        color.rgba = fixed4(0,0,0,0);
                    }
    #endif
                    return color;
                }
    
                ENDCG
            }
        }
    
    
            Fallback off
    }
    Blur 添加深度比较

      注意:

      1 我们只需要比较第一张模糊图的深度,后面的模糊都是根据这张再重新模糊,因此我们在着色器定义编译符,使之第一次与后面几次根据编译符不同的执行。

      2 在深度比较的Shader中,我们其实已经取不到原顶点pos相应的值了,因为我们并不是渲染原来的模型,而是相当于Ogre中的后处理PassQuad(只渲染一个正方形),因此,在这之前,需要将主摄像根据情况,先把设定主摄像头的depthTextureMode为Depth,这样在OnPreRender之后,主摄像头正常渲染前,先调用UpdateDepthTexture,渲染场景内所有模型的深度到_CameraDepthTexture上,这样在后面的OnRenderImage中,我们才能取到正常的深度值。

      3 在这,二张深度图里默认的精度都只有16位,因此需要定义一个范围。

      有几次试错,都在于没搞清Unity里的执行过程,后来结合Untiy提供的Frame Debugger,才搞定这个简单的修改。

      

  • 相关阅读:
    C#图片存到资源文件,以及调用图片
    error C2039: “create”: 不是“cocos2d::GLView”的成员,出错解决办法
    error LNK2038: 检测到“_MSC_VER”的不匹配项: 值“1600”不匹配值“1800”
    vs2013激活码
    AppDelegate.h文件
    AppDelegate.cpp文件详解
    【最终版】Cocos2d-x&JS v3.7 发布!
    cocos2d-x 3.0 示例代码分析3:BaseTest
    vue li click
    me
  • 原文地址:https://www.cnblogs.com/zhouxin/p/5534150.html
Copyright © 2020-2023  润新知