前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity3D-优化设置

Unity3D-优化设置

作者头像
孙寅
发布2020-06-02 15:19:49
8500
发布2020-06-02 15:19:49
举报
文章被收录于专栏:宜达数字宜达数字
01-网格合并
  • 使用gameobject的static属性设置 注意的是,所谓静态就是静止的,你如果要改变它位置,就不是静态了,静态物体在脚本加载的时候就开始渲染,不随着update 每侦更新,你如果要移动物体,就必然要重新刷新,就是动态了 。

所有被勾选了“Static”的GameObject,其中的Mesh Filter中的mesh都会被合并到 "Combined Mesh (root: scene)" 中。

Static

  • 使用代码合并

合并网格有利于性能最优化。如果mergeSubMeshes为true,所有的网格会被结合成一个单个子网格。否则每一个网格都将变成单个不同的子网格。如果所有的网格共享同一种材质,设定它为真。如果useMatrices为false,在CombineInstance结构中的变换矩阵将被忽略。

代码语言:javascript
复制
using UnityEngine;

public class MashTest : MonoBehaviour {

    
    void Start () {
        MeshFilter[] meshfies = GetComponentsInChildren<MeshFilter>();
        CombineInstance[] combine = new CombineInstance[meshfies.Length];
        int i = 0;
        while (i < meshfies.Length)
        {
            combine[i].mesh = meshfies[i].sharedMesh;
            combine[i].transform = meshfies[i].transform.localToWorldMatrix;
            meshfies[i].gameObject.SetActive(false);
            i++;
        }

        transform.GetComponent<MeshFilter>().mesh = new Mesh();
        transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
        transform.gameObject.SetActive(true);
    }
}
代码语言:javascript
复制
using UnityEditor;
using UnityEngine;

public class MashTool : MonoBehaviour {

    
    [MenuItem("Tools/Save Combine Mesh")]
    public static void SaveMesh()
    {
        Mesh m = Selection.activeGameObject.GetComponent<MeshFilter>().sharedMesh;
        AssetDatabase.CreateAsset(m, "Assets/Test/cmbMesh.asset");
        AssetDatabase.SaveAssets();
    }
}

保存后的mash

使用Linear还是Gamma

官方文档

概述

线性渲染就是渲染场景所有输入都是线性的。一般来说存在的纹理都是经过Gamma矫正了的,也就是说当纹理被采样到一个材质上时,颜色值已经不是线性的了。如果这些纹理用通常的计算方式去计算光照和图片效果,在非线性空间计算,这将导致轻微的偏差。(而这种偏差就是需要Gamma矫正的原因)

线性渲染保证了在shader中输入与输出都是在正确的颜色空间得出更正确的结果。

Gamma矫正

所谓伽玛校正就是对图像的伽玛曲线进行编辑,以对图像进行非线性色调编辑的方法,检出图像信号中的深色部分和浅色部分,并使两者比例增大,从而提高图像对比度效果。计算机绘图领域惯以此屏幕输出电压与对应亮度的转换关系曲线,称为伽玛曲线(Gamma Curve)。以传统CRT(Cathode Ray Tube)屏幕的特性而言,它的输入电压和显示出来的亮度关系不是线性的,而是一个类似幂律(pow-law)曲线的关系,而这个关系又恰好跟人眼对光的敏感度是相反的。这个巧合意味着,虽然CRT显示关系是非线性的,但对人类来说感知上很可能是一致的。

Gamma 校正补偿了不同输出设备存在的颜色显示差异,从而使图像在不同的监视器上呈现出相同的效果。

保存颜色信息本身矫正称为encoding gamma,显示器对颜色的矫正称为display gamma,所以一个完整的图形系统中需要两个Gamma值,两次矫正刚好在一定程度上抵消(但一般不是完全抵消)。

Gamma管线(Gamma Pipeline)

在Gamma渲染管线中,所有颜色和纹理在Gamma空间被采样,在shader应用了之后前,不会对shader输入做任何处理。即使这些值是在Gamma空间中的,所有shader计算对待他们输入都当做在线性空间,此外,当把shader输出写到内存中时,没有对最终像素应用Gamma矫正。很多时候是可以接受两次偏差一定程度上相互抵消。但是这是不正确的。

两种情况:

  1. 线性输入 输入颜色值在线性空间下,而在shader中按照线性空间下的计算,这些都是正确的,但最终输出的时候也没有做任何处理(主要Gamma矫正),所以在屏幕显示时,屏幕进行了一次display gamma,这样的转换后得到非预期的亮度,通常表现为整个场景比较昏暗。
  2. 非线性输入 输入颜色值在非线性空间下(通常表现为纹理),而在shader中把该值当成是线性空间下计算的(产生了偏差),这是不正确的,在最终输出的时候也没有做任何处理,但在屏幕显示时,进行了display gamma,虽然这样产生两次偏差会在一定程度上进行抵消,但这样的抵消是不正确的。

为了直接显示时可以正确显示,大多数图像文件都进行了提前的校正,即已经使用了一个encoding gamma对像素值编码。

线性管线(Linear Pipeline)

如果开启了线性渲染(Linear Rendering),Unity会背地里把输入纹理设置为sRGB模式,这种模式下硬件在对纹理进行采样时会自动将其转换到线性空间中;并且,也会设置一个sRGB格式的buffer,此时GPU会在shader写入color buffer前自动进行伽马校正。如果此时开启了混合(像我们之前的那样),在每次混合是,之前buffer中存储的颜色值会先重新转换回线性空间中,然后再进行混合,完成后再进行伽马校正,最后把校正后的混合结果写入color buffer中。这里需要注意,Alpha通道是不会参与伽马校正的。

sRGB模式是在近代的GPU上才有的东西。如果不支持sRGB,我们就需要自己在shader中进行伽马校正。 对非线性输入纹理的校正通常代码如下:

代码语言:javascript
复制
float3 diffuseCol = pow(tex2D(diffTex, texCoord), 2.2);

在最后输出前,对输出像素值的校正代码通常长下面这样:

代码语言:javascript
复制
fragColor.rgb = pow(fragColor.rgb, 1.0/2.2);
return fragColor;

但是,手工对输出像素进行伽马校正在使用混合的时候会出现问题。这是因为,校正后导致写入color buffer的颜色是非线性的,这样混合就发生在非线性空间中。一种解决方法时,在中间计算时不要对输出进行伽马校正,在最后进行一个屏幕后处理操作对最后的输出进行伽马校正,但很显然这会造成性能问题。 还有一些细节问题,例如在进行屏幕后处理的时候,要小心我们目前正在处理的图像到底是不是已经伽马校正后的。

总之,一切工作都是为了“保证所有的输入都转换到线性空间,并在线性空间下做各种光照计算,最后的输出(最最最最后的输出)进行伽马校正后再显示”。

Linear Rendering 和 Gamma Rendering的区别

Linear Rendering就是在shader中所有计算会在线性空间下进行,Gamma Rendering就是在shader中不进行转换到线性空间下,直接计算。然就是计算方程式不同,也就意味例如光照表面会有不同的响应曲线和图片效果,表现不相同。

  • Light Falloff 光照表现一般受光源的距离和法线两个因素影响(在同等光强下)。首先当我们用Linear Rendering时,执行Gamma矫正将会使光照范围变大。第二种会使边缘模糊,分不清界限。这更准确的表现了表面光照强度下降。
  • 表面响应强度

随着光强的增加,非线性方式计算的表面会更亮一些。这导致了光照在表面很多地方曝光过度,而且给场景模型一个褪色(变白色了)的感觉。当你用线性渲染时,表面颜色仍然随着光照强度线性增加的,这样就使表面材质和颜色更接近现实

Linear与Gamma

  • 混合

混合是在帧缓冲区发生的,当使用Gamma Rendering,这表示颜色之间混合是在非线性空间下计算的。然而这是不正确的。 下图在Linear Space中混合结果,颜色之间过度不是很明显。

下图在Gamma Space中混合结果,颜色交界处出现了明显的其它颜色,颜色更亮,出现褪色的现象。

  • Mipmaps

计算纹理Mipmap是种线性计算,需要对某个方形区域内像素取平均值,如果纹理存储在非线性空间,那么计算时也是在非线性空间里计算,这样就会得到错误的结果。正确的做法是先转换到线性空间在计算mipmap。

  • Lightmapping

切换linear 和gamma方式,需要重新烘焙相关的Lightmapping。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01-网格合并
  • 使用Linear还是Gamma
  • 概述
    • Gamma矫正
    • Gamma管线(Gamma Pipeline)
    • 线性管线(Linear Pipeline)
    • Linear Rendering 和 Gamma Rendering的区别
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档