当前位置:网站首页>Unity 截取3D图像 与 画中画PIP的实现
Unity 截取3D图像 与 画中画PIP的实现
2022-08-03 23:11:00 【长江很多号】
1 前言
在Unity中要得到某些3D游戏对象的截图,是比较容易的,本文来讨论一下。
实现的核心方案,是新建一个Camera,Camera指向目标对象。Camera有个参数是TargetTexture,叫目标渲染纹理,提取该纹理的像素,生成图片
。
来看一下Camera的属性:
一般情况下,摄像机直接渲染到屏幕,即,当 targetTexture 为 null 时,摄像机渲染到屏幕。但如果创建一个 RenderTexture 对象, 在摄像机上将其设置为 targetTexture,则摄像机就会渲染到 该纹理。当渲染到纹理时,摄像机始终渲染到整个纹理中。 这有一种离屏渲染FBO
的味道了^^
再补充一下RenderTexture
的知识。RenderTexture即,渲染纹理
,是指可对其进行动态渲染的纹理。
它们可用于实现基于图像的渲染特效、动态阴影、 投影器、反射或监视摄像机。
渲染纹理的一个典型用法是将其设置为 摄像机的“目标纹理”属性 (Camera.targetTexture),这将使摄像机渲染到纹理, 而不是渲染到屏幕。
2 具体实现
背景
:有如下一个简单的3D世界,包括一个Cube正方体,一个Plane 绿色平板,一个Plane白色平板。目标
:把Cube和绿色平板一起截取下来。
2.1 新建离屏渲染Camera
新建一个Camera,视锥Projection
设置为正交投影Orthographic
,位置放在3D对象的后方,使其可以照射到目标游戏对象,具体如下:
选中Camera对象,会有个小窗口,如图中的箭头,可以看到Camera所得到的实际视图,方便你的调试位置,大小。
如果要调整Camera的视锥范围,可以修改参数中的Size
。
接下来,就可以写代码,去截图了。
2.2 代码实现
具体如下:
using Assets.Scripts;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Get3DImage : MonoBehaviour
{
private RenderTexture shortcutRenderTexture;
private Camera cutImageCamera;
// Start is called before the first frame update
void Start()
{
cutImageCamera = GameObject.Find("CutImageCamera").GetComponent<Camera>();
init();
}
// Update is called once per frame
void Update()
{
}
private void init()
{
shortcutRenderTexture = RenderTexture.GetTemporary(600, 600, 16, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
shortcutRenderTexture.enableRandomWrite = true;
cutImageCamera.targetTexture = shortcutRenderTexture;
}
public void StartCutImage()
{
// Create a new Texture2D and read the RenderTexture image into it
RenderTexture.active = shortcutRenderTexture;
Texture2D drawTexture2D = new Texture2D(shortcutRenderTexture.width, shortcutRenderTexture.height, TextureFormat.RGB24, false);
drawTexture2D.ReadPixels(new Rect(0, 0, shortcutRenderTexture.width, shortcutRenderTexture.height), 0, 0);
drawTexture2D.Apply();
TextureUtils.saveTextureToFile(drawTexture2D, "SaveShortcut");
}
private void OnDestroy()
{
RenderTexture.ReleaseTemporary(shortcutRenderTexture);
}
}
核心代码
RenderTexture.active = shortcutRenderTexture;
上面的核心代码,表示设置当前的激活态的RenderTexture
为 Camera所指向的RenderTexture(同样游戏场景中可能有多个RenderTexture)。此时可以新建一个Texture2D
,调用ReadPixels
,即会读取激活态的RenderTexture的内容。
接下来就简单了,把Texture2D保存即可。代码如下:
using System.IO;
using UnityEngine;
namespace Assets.Scripts
{
class TextureUtils
{
public static Texture2D DeCompress(Texture2D source)
{
RenderTexture renderTex = RenderTexture.GetTemporary(
source.width,
source.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
Graphics.Blit(source, renderTex);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTex;
Texture2D readableText = new Texture2D(source.width, source.height);
readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
readableText.Apply();
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTex);
return readableText;
}
public static string saveTextureToFile(Texture2D texture, string fileName)
{
if (texture == null)
{
return "";
}
byte[] bytes = TextureUtils.DeCompress(texture).EncodeToPNG();
string filename = Application.persistentDataPath + "/" + fileName + ".png";
Debug.Log("DrawManager::saveTextureToFile = " + filename);
File.WriteAllBytes(filename, bytes);
return filename;
}
}
}
3 用RenderTexture实现画中画
本文使用到了RenderTexture
,且是代码动态创建的。我们也可以在菜单中创建,甚至还可以做一个画中画PIP的功能,比较有意思,顺着思路,我们来聊一下画中画的实现。
3.1 建RenderTexture
在Assets目录下,右键,Create – RenderTexture,新建一个渲染纹理。
然后,把Size参数设置为和屏幕宽高一样,例如1920x1080.
3.2 建材质
接着,右键,Create – Material,新建一个材质。Shader选为Unlit/Texture
。然后,如下右边箭头,把材质所使用的纹理,选择为上面新建的RenderTexture。
有了材质,就可以用在游戏场景中了!
3.3 建Image作为PIP窗口
新建一个2D Image,然后把Image的材质,设置为3.2所建的材质。
好了,运行起来,效果如下:
最后,上代码:
TestGet3DImage
边栏推荐
- Websocket multi-threaded sending message error TEXT_PARTIAL_WRITING--Use case of spin lock replacing synchronized exclusive lock
- 2022/8/3 考试总结
- 代码随想录笔记_动态规划_416分割等和子集
- 举一个 web worker 的例子
- P1996 约瑟夫问题
- 使用tf.image.resize() 和tf.image.resize_with_pad()调整图像大小
- Creo 9.0二维草图的诊断:加亮开放端点
- 获国际权威认可 | 云扩科技入选《RPA全球市场格局报告,Q3 2022》
- log4j-slf4j-impl cannot be present with log4j-to-slf4j
- 单例模式使用饿汉式和懒汉式创建一定安全?很多人不知
猜你喜欢
End-to-End Lane Marker Detection via Row-wise Classification
node连接mysql数据库报错:Client does not support authentication protocol requested by server
Recognized by International Authorities | Yunzhuang Technology was selected in "RPA Global Market Pattern Report, Q3 2022"
易观分析:2022年Q2中国网络零售B2C市场交易规模达23444.7亿元
complete binary tree problem
rosbridge-WSL2 && carla-win11
密码学基础以及完整加密通讯过程解析
用栈实现队列
BMN: Boundary-Matching Network for Temporal Action Proposal Generation阅读笔记
射频芯片(RFIC)的协议之5G及其调制
随机推荐
Binary search tree to solve the fallen leaves problem
Code Casual Recording Notes_Dynamic Programming_416 Segmentation and Subsetting
CAS:178744-28-0,mPEG-DSPE,DSPE-mPEG,甲氧基-聚乙二醇-磷脂酰乙醇胺供应
V8中的快慢数组(附源码、图文更易理解)
Zilliz 2023 Fall Campus Recruitment Officially Launched!
Work Subtotal QT Packing
工作小计 QT打包
Research status of target detection at home and abroad
设置工作模式与环境(下):探查和收集信息
Quickly build a website with static files
Pytest学习-setup/teardown
With the rise of concepts such as metaverse and web3.0, many digital forms such as digital people and digital scenes have begun to appear.
物联网新零售模式,引领购物新潮流
Recognized by International Authorities | Yunzhuang Technology was selected in "RPA Global Market Pattern Report, Q3 2022"
MiniAPI of .NET6 (14): Cross-domain CORS (Part 1)
What is the difference between the generator version and the viewer version?
关于IDO预售系统开发技术讲解丨浅谈IDO预售合约系统开发原理分析
Summary bug 】 【 Elipse garbled solution project code in Chinese!
OPC UA 与IEC61499 深度融合(1)
用队列模拟实现栈