游戏仿真实验使用Unity仿真电视机光学三原色显示画面,致敬袁隆平爷爷
Posted 林新发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏仿真实验使用Unity仿真电视机光学三原色显示画面,致敬袁隆平爷爷相关的知识,希望对你有一定的参考价值。
本文效果如下
一、前言
嗨,大家好,我是新发。
最近我在尝试用Unity
制作非游戏的场景,做一些数学、物理的仿真实验,比如上一篇文章我做了一个《蒲丰投针仿真实验》(点击查看),今天,我又要做另一个实验,模拟电视机光学三原色的原理来显示画面,话不多说,我们开始吧~
二、光学三原色
光学三原色分别为红、绿、蓝,这三个颜色通道色各分为256
阶亮度,在0
时最弱,而在255
时最亮。也就是说,一共可以表现256 x 256 x 256 = 16777216
种颜色。
我们早期的彩色电视机显示器就是利用三原色的叠加来显示不同的色彩的,如果你用放大镜仔细观察电视机的屏幕,就会发现画面其实是由很多很多红绿蓝的小色块排列组合而成的,
三、Unity制作红绿蓝色块
创建一个Unity
工程,在Hierarchy
面板空白处右键鼠标,点击菜单3D Object / Quad
,创建一个四边形,
如下:
调整四边形的Scale
的x
缩放为0.33
,
如下,
为它创建一个材质球,shader
使用Unlit/Color
,颜色设置为红色,
把材质球赋值给四边形,
如下
同理,制作蓝色和绿色,排在一起,如下:
层级结构如下,一个block
就等价于一个像素,一个像素包括r
、g
、b
三个三原色,
可以分别对r
、g
、b
进行调整,
四、克隆像素块
接下来我们只需要进行克隆,排列好,理论上就可以做成一个光学三原色显示器了,
写个函数来执行:
// 创建N个像素块,WIDTH是宽,HEIGHT是高
private IEnumerator CreateBlocks()
{
int counter = 0;
for (int j = HEIGHT; j >= 0; --j)
{
for (int i = 0; i < WIDTH; ++i)
{
CreateBlockItem(i, j, Color.white);
++counter;
if (counter > 100)
{
counter = 0;
yield return new WaitForSeconds(0.3f);
}
}
}
}
// 创建一个像素块
private void CreateBlockItem(int i, int j, Color color)
{
var obj = Instantiate(block);
var trans = obj.transform;
trans.SetParent(blockRoot, false);
trans.localPosition = new Vector3(i, j, 0);
trans.Find("r").GetComponent<MeshRenderer>().material.color = new Color(color.r, 0, 0);
trans.Find("g").GetComponent<MeshRenderer>().material.color = new Color(0, color.g, 0);
trans.Find("b").GetComponent<MeshRenderer>().material.color = new Color(0, 0, color.b);
}
比如创建一个宽100
,高50
的屏幕,效果如下:
五、显示图像
我们找一张图片,比如袁隆平爷爷的图片,
导入到Unity
工程中,勾选图片可读,
我们可以看到图片的尺寸为501x324
,
我们使用160x103
的分辨率来显示,我们对图像进行采样,可以使用Texture2D
的GetPixel
接口,
public Color GetPixel(int x, int y);
完整代码如下:
using System.Collections;
using UnityEngine;
public class BlockMgr : MonoBehaviour
{
/// <summary>
/// 原图像
/// </summary>
public Texture2D texture;
/// <summary>
/// 三原色像素块
/// </summary>
public GameObject block;
/// <summary>
/// 像素块父节点
/// </summary>
private Transform blockRoot;
/// <summary>
/// 宽
/// </summary>
private const int WIDTH = 160;
/// <summary>
/// 高
/// </summary>
private const int HEIGHT = 103;
void Start()
{
blockRoot = block.transform.parent;
StartCoroutine(CreateCreenBlocks());
}
private IEnumerator CreateCreenBlocks()
{
int counter = 0;
var width = texture.width;
var height = texture.height;
for (int j = HEIGHT; j >= 0; --j)
{
for (int i = 0; i < WIDTH; ++i)
{
// 对原图像进行采样
Color color = texture.GetPixel(width * i / WIDTH, height * j / HEIGHT);
CreateBlockItem(i, j, color);
++counter;
if (counter > 100)
{
counter = 0;
yield return null;
}
}
}
}
private void CreateBlockItem(int i, int j, Color color)
{
var obj = Instantiate(block);
var trans = obj.transform;
trans.SetParent(blockRoot, false);
trans.localPosition = new Vector3(i, j, 0);
trans.Find("r").GetComponent<MeshRenderer>().material.color = new Color(color.r, 0, 0);
trans.Find("g").GetComponent<MeshRenderer>().material.color = new Color(0, color.g, 0);
trans.Find("b").GetComponent<MeshRenderer>().material.color = new Color(0, 0, color.b);
}
}
脚本挂在screen
节点上,
六、运行效果
运行Unity
,执行效果如下:
亮度有点暗,
我们加上屏幕后处理,加上Bloom
效果,
最终效果,致敬袁隆平爷爷!
七、工程源码
本文工程已上传到CODE CHINA
,刚兴趣的同学可自行下载学习,地址:https://codechina.csdn.net/linxinfa/UnityTVScreenSimulation
注:我使用的Unity
版本为Unity 2020.1.14f1c1 (64-bit)
八、完毕
好了,今天就到这里吧。
我是林新发:https://blog.csdn.net/linxinfa
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,如果有什么技术上的疑问,欢迎留言或私信,我们下期见~
以上是关于游戏仿真实验使用Unity仿真电视机光学三原色显示画面,致敬袁隆平爷爷的主要内容,如果未能解决你的问题,请参考以下文章
游戏仿真实验Unity仿真蒲丰投针实验,丢针计算圆周率,丢了一百万次针得出的结果是...
游戏仿真实验Unity仿真蒲丰投针实验,丢针计算圆周率,丢了一百万次针得出的结果是...
光学基于matlab相互垂直的光波叠加仿真含Matlab源码 2071期