Unity RGBA16 + Dither
游戏开发中有些场合,ETC或者说PVRTC压缩质量不满足的情况下,RGBA32(原图)对美术而言肯定可以满足的,但是RGBA32是不管是对内存占用内存太厉害. RGBA16/RGB16会减少内存的占用,但是Unity中并没有处理色阶的问题,看起来会使这样:
之前有文章提到过使用对图片预先进行Dither(抖动)处理之后,再使用RGBA16压缩,就会消除或者说减少色阶问题,不过作者使用的是TexturePacker进行的处理,而对于不采用TexturePacker进行UI Atlas打包的Unity项目就要换种思路实现。
Image Dither
图像抖动的基本原理是误差扩散,也就是将减少色阶后的误差扩散到周边像素,减少相邻像素点整体的误差,从而使肉眼在观察图片时没有那么明显的色阶问题,如下图:
更多详细描述可以阅读:http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/,里面对几种dither算法了详细描述,并给出了处理后的效果。具体的实现可以参考github:
https://github.com/minhhh/unity-texture-dither。对比了几种效果,我最后采用Floyd–Steinberg抖动算法。
Unity 图片预处理
具体实现中,可以在Unity导入图片时通过unity AssetPostprocessor对需要进行压缩的图片进行Dither处理,具体代码:
using UnityEngine;
using UnityEditor;
using System.Collections;
class TextureModifier : AssetPostprocessor
{
void OnPreprocessTexture()
{
var importer = (assetImporter as TextureImporter);
importer.textureType = TextureImporterType.GUI;
if (assetPath.EndsWith ("Dither.png")) {
importer.textureFormat = TextureImporterFormat.RGBA32;
}
}
// Floyd–Steinberg dithering实现参考:https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering
void OnPostprocessTexture (Texture2D texture)
{
if (!assetPath.EndsWith ("Dither.png")) {
return;
}
var texw = texture.width;
var texh = texture.height;
var pixels = texture.GetPixels ();
var offs = 0;
var k1Per15 = 1.0f / 15.0f;
var k1Per16 = 1.0f / 16.0f;
var k3Per16 = 3.0f / 16.0f;
var k5Per16 = 5.0f / 16.0f;
var k7Per16 = 7.0f / 16.0f;
for (var y = 0; y < texh; y++) {
for (var x = 0; x < texw; x++) {
float a = pixels [offs].a;
float r = pixels [offs].r;
float g = pixels [offs].g;
float b = pixels [offs].b;
var a2 = Mathf.Clamp01 (Mathf.Floor (a * 16) * k1Per15);
var r2 = Mathf.Clamp01 (Mathf.Floor (r * 16) * k1Per15);
var g2 = Mathf.Clamp01 (Mathf.Floor (g * 16) * k1Per15);
var b2 = Mathf.Clamp01 (Mathf.Floor (b * 16) * k1Per15);
var ae = a - a2;
var re = r - r2;
var ge = g - g2;
var be = b - b2;
pixels [offs].a = a2;
pixels [offs].r = r2;
pixels [offs].g = g2;
pixels [offs].b = b2;
var n1 = offs + 1; // (x+1,y)
var n2 = offs + texw - 1; // (x-1 , y+1)
var n3 = offs + texw; // (x, y+1)
var n4 = offs + texw + 1; // (x+1 , y+1)
if (x < texw - 1) {
pixels [n1].a += ae * k7Per16;
pixels [n1].r += re * k7Per16;
pixels [n1].g += ge * k7Per16;
pixels [n1].b += be * k7Per16;
}
if (y < texh - 1) {
pixels [n3].a += ae * k5Per16;
pixels [n3].r += re * k5Per16;
pixels [n3].g += ge * k5Per16;
pixels [n3].b += be * k5Per16;
if (x > 0) {
pixels [n2].a += ae * k3Per16;
pixels [n2].r += re * k3Per16;
pixels [n2].g += ge * k3Per16;
pixels [n2].b += be * k3Per16;
}
if (x < texw - 1) {
pixels [n4].a += ae * k1Per16;
pixels [n4].r += re * k1Per16;
pixels [n4].g += ge * k1Per16;
pixels [n4].b += be * k1Per16;
}
}
offs++;
}
}
texture.SetPixels (pixels);
EditorUtility.CompressTexture (texture, TextureFormat.RGBA4444, TextureCompressionQuality.Best);
}
}
效果对比
Unity RGBA16 + Dither的更多相关文章
- Unity游戏开发图片纹理压缩方案
Unity3D引擎对纹理的处理是智能的:不论你放入的是PNG,PSD还是TGA,它们都会被自动转换成Unity自己的Texture2D格式. 在Texture2D的设置选项中,你可以针对不同的平台,设 ...
- Unity加载模块深度解析(纹理篇)
在游戏和VR项目的研发过程中,加载模块所带来的效率开销和内存占用(即“加载效率”.“场景切换速度”等)经常是开发团队非常头疼的问题,它不仅包括资源的加载耗时,同时也包含场景物件的实例化和资源卸载等.在 ...
- 给The Lab Renderer for Unity中地形添加阴影
The Lab Renderer for Unity是Valve针对VR在Unity的体验渲染器,提高VR的渲染效率,更多的大家可以查相应资料,在这,说个The Lab Renderer for Un ...
- Unity优化之贴图
默认情况下当你把图片导入到unity中时,unity会自动把图片转换成最适合当前平台的压缩格式.如果你有一些特殊的需求,unity也提供了覆盖默认压缩格式的方法,如下图 在图片的Inspector窗口 ...
- Unity -----一些可能存在的错误
关于Unity中的资源管理,你可能遇到这些问题 张鑫 8 个月前 原文链接:关于Unity中的资源管理,你可能遇到这些问题 - Blog 在优化Unity项目时,对资源的管理可谓是个系统纷繁的大工程. ...
- transparent shadow caster unity
https://forum.unity.com/threads/semitransparent-shadows.276490/ semitransparent shadows dither 类似alp ...
- Unity使用 16bit 压缩 Texture 颜色能均匀过渡
下面是unity自带 16bit 图 的效果,可以看到颜色过度的很不均匀,占用内存 0.5M 如果调成 truecolor 后 颜色过渡很均匀,而内存却占到 1.1 M 讲图片 后缀名改成 ...
- Unity 与 Android (Android Studio)的交互
http://blog.csdn.net/kuerjinjin/article/details/50177633 1.大体思路: 在Android Studio 中编译导出Jar库,提供函数供 Uni ...
- Unity移动游戏加载性能和内存管理-学习笔记
前言 正在学习Doctor 张.鑫大佬的移动游戏加载性能和内存管理,内容非常非常的干,所以我烧了很多开水,边喝边看,一边拿小本几做好笔记 本文只是关于前2章的内容笔记,关于各种资源的加载耗时 纹理资源 ...
随机推荐
- 深度学习之PyTorch实战(3)——实战手写数字识别
上一节,我们已经学会了基于PyTorch深度学习框架高效,快捷的搭建一个神经网络,并对模型进行训练和对参数进行优化的方法,接下来让我们牛刀小试,基于PyTorch框架使用神经网络来解决一个关于手写数字 ...
- Vxlan学习笔记——原理
1. 为什么需要Vxlan 普通的VLAN数量只有4096个,无法满足大规模云计算IDC的需求,而IDC为何需求那么多VLAN呢,因为目前大部分IDC内部结构主要分为两种L2,L3.L2结构里面,所有 ...
- JavaScript防抖节流函数
1.直接上码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...
- HAProxy(三):Keeplived+HAProxy搭建高可用负载均衡动静分离架构基础配置示例
一.安装环境 1.软件版本 HAProxy:1.5.18 Keepalived:1.3.5 Nginx:1.12.2 PHP:7.2 系统版本:CentOS 7.4 2.IP分配与架构图 3.安装软件 ...
- SQL Server新建登录名,实现SQL Server身份验证模式
一.如果是默认安装,没有选择SQL Server和Windows身份验证模式,需要重新设置. 1.右击服务器,属性,常规项中点选“SQL Server和Windows身份验证模式” 2.点击“确定”按 ...
- [翻译]EntityFramework Core 2.2 发布
原文来源 TechViews 今天我们将推出EF Core 2.2的最终版本,以及ASP.NET Core 2.2和.NET Core 2.2 .这是我们的开源和跨平台对象数据库映射技术的最新版本. ...
- (整理)Sublime Text 3 安装、破解、安装Package Control、汉化、添加到右键菜单、代码格式化、禁止更新
Sublime Text 3好用,但是每次安装到最后用着顺手,得在网上找半天安装.破解.安装Package Control.汉化.添加到右键菜单.代码格式化等等的教程,今天有空给自己整理一下吧. 一. ...
- JavaScript 变量作用域 详解
变量作用域要点 - 在JavaScript中没有块级作用域,只有函数作用域 - 在函数体内,局部变量的优先级高于同名的全局变量 - 在全局作用域编写代码时可以不写var语句,但声明局部变量时必须使用v ...
- 设计模式之责任链模式(Chain of Responsibility )
责任链的目的是通过特定的设计对请求者和接收者之间进行解耦,请求者调用操作的对象,接收者接收请求并执行相关操作,通过解耦请求者不需要关心接收者的接口,同时也可增强职责的灵活性,通过改变链内的成员或调用次 ...
- vue项目导入外部css样式和js文件
<template> <div id="app" > </div> </template> <script src=" ...