我正在为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 不幸的是,我不打算很快发布它,因此存储库缺少一些正式的东西,如自述文件和构建指令。但是,大多数信息都可以在子模块中找到。
答案 0 :(得分:0)
CommandBuffer.SetProjectionMatrix显然需要一个由GL.GetGPUProjectionMatrix调整的矩阵。
buffer.SetProjectionMatrix(GL.GetGPUProjectionMatrix(cam.projectionMatrix, false));
不幸的是,我仍然不明白为什么这会导致部署和开发版本之间出现不同的行为。我原以为它只能在不同的平台上有所作为。