统一独立播放器构建中的错误转换

时间:2018-05-25 14:04:43

标签: unity3d

我正在为Unity(2018.1.0f2)开发一个本地(c ++)插件(目前只有windows)。 该插件下载纹理和网格,并将它们提供给统一。 有很多样板代码,我想不遗余力。 无论如何,渲染是这样完成的:

void RegenerateCommandBuffer(CommandBuffer buffer, List<DrawTask> tasks)
{
    buffer.Clear();
    buffer.SetProjectionMatrix(cam.projectionMatrix); // protected Camera cam; cam = GetComponent<Camera>();
    foreach (DrawTask t in tasks)
    {
        if (t.mesh == null)
            continue;
        MaterialPropertyBlock mat = new MaterialPropertyBlock();
        bool monochromatic = false;
        if (t.texColor != null)
        {
            var tt = t.texColor as VtsTexture;
            mat.SetTexture(shaderPropertyMainTex, tt.Get());
            monochromatic = tt.monochromatic;
        }
        if (t.texMask != null)
        {
            var tt = t.texMask as VtsTexture;
            mat.SetTexture(shaderPropertyMaskTex, tt.Get());
        }
        mat.SetMatrix(shaderPropertyUvMat, VtsUtil.V2U33(t.data.uvm));
        mat.SetVector(shaderPropertyUvClip, VtsUtil.V2U4(t.data.uvClip));
        mat.SetVector(shaderPropertyColor, VtsUtil.V2U4(t.data.color));
        // flags: mask, monochromatic, flat shading, uv source
        mat.SetVector(shaderPropertyFlags, new Vector4(t.texMask == null ? 0 : 1, monochromatic ? 1 : 0, 0, t.data.externalUv ? 1 : 0));
        buffer.DrawMesh((t.mesh as VtsMesh).Get(), VtsUtil.V2U44(t.data.mv), material, 0, -1, mat);
    }
}

有两种控制模式。统一摄像头由插件中的摄像头控制,或者插件摄像头由统一摄像头控制。在我目前的情况下,插件摄像头由统一摄像头控制。幕后没有特殊的魔力,但有些变换需要以双精度完成才能在没有网格跳跃的情况下工作。

void CamOverrideView(ref double[] values)
{
    Matrix4x4 Mu = mapTrans.localToWorldMatrix * VtsUtil.UnityToVtsMatrix;
    // view matrix
    if (controlTransformation == VtsDataControl.Vts)
        cam.worldToCameraMatrix = VtsUtil.V2U44(Math.Mul44x44(values, Math.Inverse44(VtsUtil.U2V44(Mu))));
    else
        values = Math.Mul44x44(VtsUtil.U2V44(cam.worldToCameraMatrix), VtsUtil.U2V44(Mu));
}

void CamOverrideParameters(ref double fov, ref double aspect, ref double near, ref double far)
{
    // fov
    if (controlFov == VtsDataControl.Vts)
        cam.fieldOfView = (float)fov;
    else
        fov = cam.fieldOfView;
    // near & far
    if (controlNearFar == VtsDataControl.Vts)
    {
        cam.nearClipPlane = (float)near;
        cam.farClipPlane = (float)far;
    }
    else
    {
        near = cam.nearClipPlane;
        far = cam.farClipPlane;
    }
}

着色器:

Shader "Vts/UnlitShader"
{
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct vIn
            {
                float4 vertex : POSITION;
                float2 uvInternal : TEXCOORD0;
                float2 uvExternal : TEXCOORD1;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uvTex : TEXCOORD0;
                float2 uvClip : TEXCOORD1;
            };

            struct fOut
            {
                float4 color : SV_Target;
            };

            sampler2D _MainTex;
            sampler2D _MaskTex;

            float4x4 _UvMat;
            float4 _UvClip;
            float4 _Color;
            float4 _Flags; // mask, monochromatic, flat shading, uv source

            v2f vert (vIn i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.uvTex = mul((float3x3)_UvMat, float3(_Flags.w > 0 ? i.uvExternal : i.uvInternal, 1.0)).xy;
                o.uvClip = i.uvExternal;
                return o;
            }

            fOut frag (v2f i)
            {
                fOut o;

                // texture color
                o.color = tex2D(_MainTex, i.uvTex);
                if (_Flags.y > 0)
                    o.color = o.color.rrra; // monochromatic texture

                // uv clipping
                if (   i.uvClip.x < _UvClip.x
                    || i.uvClip.y < _UvClip.y
                    || i.uvClip.x > _UvClip.z
                    || i.uvClip.y > _UvClip.w)
                    discard;

                // mask
                if (_Flags.x > 0)
                {
                    if (tex2D(_MaskTex, i.uvTex).r < 0.5)
                        discard;
                }

                // uniform tint
                o.color *= _Color;

                return o;
            }
            ENDCG
        }
    }
}

一切都很完美 - 在编辑器中。它也适用于独立的开发构建。但是在“部署”构建中,转换会出错。渲染的部分看起来好像是围绕错误的轴或不同的极性旋转。

你能发现一些明显的错误吗?

我的第一个怀疑是OpenGL与DirectX的差异,但“部署”和“开发”构建应该使用相同的,如果不是的话?此外,我尝试更改播放器设置以强制其中一个,但没有任何差异。

编辑:

良好形象:https://drive.google.com/open?id=1RTlVZBSAj7LIml1sBCX7nYTvMNaN0xK-

图片不好:https://drive.google.com/open?id=176ahft7En6MqT-aS2RdKXOVW68NmvK2L

注意地形如何与大气正确对齐。

重现的步骤

1)以统一的方式创建一个新项目

2)下载资产https://drive.google.com/open?id=18uKuiya5XycjGWEcsF-xjy0fn7sf-D82并将其提取到新创建的项目中

3)在编辑器中试用 - &gt;应该工作正常(它将开始从我们下载网格和纹理,所以要耐心;下载的资源缓存在例如C://users//.cache/vts-browser) 飞机由鼠标控制,按下LMB。

4)内置开发构建和运行 - &gt;应该也可以正常工作

5)在开发构建和运行中构建NOT - &gt;地形转换行为不正确。

此外,我已经发布了存储库。以下是特定于统一的代码:https://github.com/Melown/vts-browser-unity-plugin 不幸的是,我不打算很快发布它,因此存储库缺少一些正式的东西,如自述文件和构建指令。但是,大多数信息都可以在子模块中找到。

1 个答案:

答案 0 :(得分:0)

CommandBuffer.SetProjectionMatrix显然需要一个由GL.GetGPUProjectionMatrix调整的矩阵。

buffer.SetProjectionMatrix(GL.GetGPUProjectionMatrix(cam.projectionMatrix, false));

不幸的是,我仍然不明白为什么这会导致部署和开发版本之间出现不同的行为。我原以为它只能在不同的平台上有所作为。