Unity 法线贴图不适用于 Android 设备
Unity Normal Maps don't work on Android device
我是一名经验丰富的本地 iOS 开发人员,我通过 Unity 首次涉足 Android。我正在尝试设置自定义着色器,但我在使用法线贴图时遇到了一些问题。我已经让它们在我计算机上的 Unity 模拟器中完美运行,但是当我构建到实际设备(Samsung Galaxy S8+)时,法线贴图根本不起作用。
我正在使用火星作为我的测试用例。这是我计算机上模拟器中的模型 运行:
这是我设备的屏幕截图,运行 完全相同的代码。
我做了很多研究,显然使用 Unity 在 Android 上使用法线贴图并不是一件容易的事。有很多人问这个问题,但我找到的几乎每个答案都说诀窍是覆盖纹理导入设置,并强制它成为 "Truecolor" ,这似乎是 "RGBA 32 Bit" 根据至 Unity's documentation。不过,这对我没有帮助。
另一个帖子建议将 Asino 级别降低到零,另一个建议关闭 Mip 贴图。我不知道这两个是什么,但都没有帮助。
这是我的着色器代码,经过简化但包含对法线贴图的所有引用:
void surf (Input IN, inout SurfaceOutputStandard o) {
half4 d = tex2D (_MainTex , IN.uv_MainTex);
half4 n = tex2D (_BumpMap , IN.uv_BumpMap);
o.Albedo = d.rgb;
o.Normal = UnpackNormal(n);
o.Metallic = 0.0;
o.Smoothness = 0.0;
}
我看到一些线程建议替换着色器代码中的 "UnpackNormal()" 函数,这表明它可能不是一般在 Android 或移动设备上要做的事情,但是 none 的建议替换项改变了任何东西:法线贴图在模拟器中继续工作,但在设备上不工作。
我什至尝试过从灰度高度图以编程方式制作我自己的法线贴图,以尝试规避我可能做错的任何导入设置。这是我使用的代码,它再次在模拟器中工作但在设备上不工作。
public Texture2D NormalMap(Texture2D source, float strength = 10.0f) {
Texture2D normalTexture;
float xLeft;
float xRight;
float yUp;
float yDown;
float yDelta;
float xDelta;
normalTexture = new Texture2D (source.width, source.height, TextureFormat.RGBA32, false, true);
for (int y=0; y<source.height; y++) {
for (int x=0; x<source.width; x++) {
xLeft = source.GetPixel (x - 1, y).grayscale * strength;
xRight = source.GetPixel (x + 1, y).grayscale * strength;
yUp = source.GetPixel (x, y - 1).grayscale * strength;
yDown = source.GetPixel (x, y + 1).grayscale * strength;
xDelta = ((xLeft - xRight) + 1) * 0.5f;
yDelta = ((yUp - yDown) + 1) * 0.5f;
normalTexture.SetPixel(x,y,new Color(xDelta,yDelta,1.0f,yDelta));
}
}
normalTexture.Apply();
return normalTexture;
}
最后,在构建设置中,我将平台设置为 Android,并尝试将纹理压缩设置为 "Don't Override" 和 "ETC (default)"。前者是原始设置,后者无论从名字还是文档上看都是Unity的建议。
我确定只有一些标志我没有检查或一些开关我没有翻转,但我终究无法弄清楚我在这里做错了什么,或者为什么那里做错了模拟器和设备之间会有如此顽固的差异。
谁能帮助 Unity 新手,告诉我这些该死的法线贴图应该如何在 Android 上工作?
检查下:
Edit -> Project Settings -> Quality
Android 通常设置为最快。
我是一名经验丰富的本地 iOS 开发人员,我通过 Unity 首次涉足 Android。我正在尝试设置自定义着色器,但我在使用法线贴图时遇到了一些问题。我已经让它们在我计算机上的 Unity 模拟器中完美运行,但是当我构建到实际设备(Samsung Galaxy S8+)时,法线贴图根本不起作用。
我正在使用火星作为我的测试用例。这是我计算机上模拟器中的模型 运行:
这是我设备的屏幕截图,运行 完全相同的代码。
我做了很多研究,显然使用 Unity 在 Android 上使用法线贴图并不是一件容易的事。有很多人问这个问题,但我找到的几乎每个答案都说诀窍是覆盖纹理导入设置,并强制它成为 "Truecolor" ,这似乎是 "RGBA 32 Bit" 根据至 Unity's documentation。不过,这对我没有帮助。
另一个帖子建议将 Asino 级别降低到零,另一个建议关闭 Mip 贴图。我不知道这两个是什么,但都没有帮助。
这是我的着色器代码,经过简化但包含对法线贴图的所有引用:
void surf (Input IN, inout SurfaceOutputStandard o) {
half4 d = tex2D (_MainTex , IN.uv_MainTex);
half4 n = tex2D (_BumpMap , IN.uv_BumpMap);
o.Albedo = d.rgb;
o.Normal = UnpackNormal(n);
o.Metallic = 0.0;
o.Smoothness = 0.0;
}
我看到一些线程建议替换着色器代码中的 "UnpackNormal()" 函数,这表明它可能不是一般在 Android 或移动设备上要做的事情,但是 none 的建议替换项改变了任何东西:法线贴图在模拟器中继续工作,但在设备上不工作。
我什至尝试过从灰度高度图以编程方式制作我自己的法线贴图,以尝试规避我可能做错的任何导入设置。这是我使用的代码,它再次在模拟器中工作但在设备上不工作。
public Texture2D NormalMap(Texture2D source, float strength = 10.0f) {
Texture2D normalTexture;
float xLeft;
float xRight;
float yUp;
float yDown;
float yDelta;
float xDelta;
normalTexture = new Texture2D (source.width, source.height, TextureFormat.RGBA32, false, true);
for (int y=0; y<source.height; y++) {
for (int x=0; x<source.width; x++) {
xLeft = source.GetPixel (x - 1, y).grayscale * strength;
xRight = source.GetPixel (x + 1, y).grayscale * strength;
yUp = source.GetPixel (x, y - 1).grayscale * strength;
yDown = source.GetPixel (x, y + 1).grayscale * strength;
xDelta = ((xLeft - xRight) + 1) * 0.5f;
yDelta = ((yUp - yDown) + 1) * 0.5f;
normalTexture.SetPixel(x,y,new Color(xDelta,yDelta,1.0f,yDelta));
}
}
normalTexture.Apply();
return normalTexture;
}
最后,在构建设置中,我将平台设置为 Android,并尝试将纹理压缩设置为 "Don't Override" 和 "ETC (default)"。前者是原始设置,后者无论从名字还是文档上看都是Unity的建议。
我确定只有一些标志我没有检查或一些开关我没有翻转,但我终究无法弄清楚我在这里做错了什么,或者为什么那里做错了模拟器和设备之间会有如此顽固的差异。
谁能帮助 Unity 新手,告诉我这些该死的法线贴图应该如何在 Android 上工作?
检查下:
Edit -> Project Settings -> Quality
Android 通常设置为最快。