using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
public class CreateCameraPhoto : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
[Header("拍照相机")]
public Camera renderCamera;
[Header("拍照对象")]
public GameObject go;
#region =====================================
[Header("测试接受贴图的对象")]
public Image image;
public GameObject Plane;
[Button]
public void TestCreatePhoto()
{
if (renderCamera != null)
{
SetLayer();
//renderCamera是我们的拍摄照片用的相机,一般情况下给它关闭,防止它对我们主要的渲染结果造成影响。
//renderCamera.gameObject.SetActive(true);
//创建一个Texture2D 的纹理output ,作为一个临时纹理用于接收相机拍摄到的纹理
//这里使用大小是512x385和TextureFormat.RGB24类型的纹理格式,并关闭minmap,这里并不需要开启多级渐远纹理。(关于纹理格式和多级渐远纹理会在以后的文章补充)
//Texture2D output = new Texture2D(512, 358, TextureFormat.RGB24, false);
//如果需要在代码中将该带有透明通道的rt转为texture2D,需要使用类型为ARGB32或者RGBAFloat:
Texture2D output = new Texture2D(256, 179, TextureFormat.ARGB32, false);
//同样创建一个渲染纹理
RenderTexture renderTexture = new RenderTexture(256, 179, 32, RenderTextureFormat.ARGB32);
//RenderTexture renderTexture = new RenderTexture(512, 358, 32, RenderTextureFormat.ARGBFloat);
//这行代码将相机的渲染目标设置为上面创建的 renderTexture。这意味着,当相机进行渲染时,它的渲染结果将被保存到 renderTexture 中,而不是直接显示在屏幕上。
renderCamera.targetTexture = renderTexture;
//强制执行一次渲染,将渲染结果更新
renderCamera.Render();
//这行代码设置当前活动的渲染纹理为 renderTexture。这是为了确保接下来的 ReadPixels 操作读取的是 renderTexture 中的像素数据。
RenderTexture.active = renderTexture;
//rect_renderTexture 是一个矩形区域参数,用于定义要读取的区域。
Rect picture_renderTexture = new Rect(0, 0, 512, 512);
//这行代码从当前活动的渲染纹理(即renderTexture)中读取像素数据,并将其存储到 output 纹理对象中
output.ReadPixels(picture_renderTexture, 0, 0);
//这行代码应用了纹理的修改。在Unity中,ReadPixels 操作会修改纹理数据,但是这些修改不会立即生效,需要调用 Apply 方法来应用这些修改,使其生效。
output.Apply();
Sprite sprite = Sprite.Create(output, new Rect(0, 0, output.width, output.height), new Vector2(0.5f, 0.5f));
Material material = Plane.GetComponent<Renderer>().material;
//将生成的纹理覆盖到背景板上
material.mainTexture = output;
//操作完毕后关闭渲染相机
// renderCamera.gameObject.SetActive(false);
image.sprite = sprite;
renderCamera.targetTexture = null;
renderTexture.Release();
Destroy(renderTexture);
ReSetLayer();
}
}
#endregion ===============================================
#region=======判断和动态调整使物体在相机视角内(这里以两个3d ui为例计算bounds边界和中心)==================
public RectTransform BgImage;
public RectTransform IcoImage;
public Vector3 center = Vector3.zero;
[Button]
public void GetCenterPoint()
{
float BgImage_Up = (BgImage.localPosition.y + (BgImage.sizeDelta.y * BgImage.localScale.y) / 2);
float BgImage_Down = (BgImage.localPosition.y - (BgImage.sizeDelta.y * BgImage.localScale.y) / 2);
float BgImage_Left = (BgImage.localPosition.x - (BgImage.sizeDelta.x * BgImage.localScale.x) / 2);
float BgImage_Right = (BgImage.localPosition.x + (BgImage.sizeDelta.x * BgImage.localScale.x) / 2);
float IcoImage_Up = (IcoImage.localPosition.y + (IcoImage.sizeDelta.y * IcoImage.localScale.y) / 2);
float IcoImage_Down = (IcoImage.localPosition.y - (IcoImage.sizeDelta.y * IcoImage.localScale.y) / 2);
float IcoImage_Left = (IcoImage.localPosition.x - (IcoImage.sizeDelta.x * IcoImage.localScale.x) / 2);
float IcoImage_Right = (IcoImage.localPosition.x + (IcoImage.sizeDelta.x * IcoImage.localScale.x) / 2);
if (!IcoImage.gameObject.activeSelf)
{
IcoImage_Up = BgImage_Up;
IcoImage_Down = BgImage_Down;
IcoImage_Left = BgImage_Left;
IcoImage_Right = BgImage_Right;
}
float Bounds_Up;
float Bounds_Down;
float Bounds_Left;
float Bounds_Right;
if (BgImage_Up > IcoImage_Up)
Bounds_Up = BgImage_Up;
else
Bounds_Up = IcoImage_Up;
if (BgImage_Down < IcoImage_Down)
Bounds_Down = BgImage_Down;
else
Bounds_Down = IcoImage_Down;
if (BgImage_Right > IcoImage_Right)
Bounds_Right = BgImage_Right;
else
Bounds_Right = IcoImage_Right;
if (BgImage_Left < IcoImage_Left)
Bounds_Left = BgImage_Left;
else
Bounds_Left = IcoImage_Left;
//下移边界
if (Bounds_Down > 0)
Bounds_Down = -30;
float x = (Bounds_Right - Bounds_Left) / 2 + Bounds_Left;
float y = (Bounds_Up - Bounds_Down) / 2 + Bounds_Down;
//center = Vector3.zero;
center = new Vector3(x, y);
//center = new Vector3 (Bounds_Right, Bounds_Up);
Debug.Log(Bounds_Up + "_" + Bounds_Down + "_" + Bounds_Left + "_" + Bounds_Right);
renderCamera.transform.localPosition = center;
float h = (Bounds_Up - Bounds_Down) / 2;
float w = (Bounds_Right - Bounds_Left) / 2;
if (h > w)
maxHeight = h;
else
maxHeight = w;
}
public float maxHeight = 0;
[Button]
public void DebugAngle()
{
Vector2 V1 = new Vector2(transform.localPosition.z, 0);
Vector2 V2 = new Vector2(transform.localPosition.z, maxHeight);
float angleDifference = Vector3.Angle(V1, V2);
Debug.Log(angleDifference);
}
float CameraPositionZ = -50;
Vector2 V1;
Vector2 V2;
float angleDifference;
[Button]
//计算相机最近拍摄位置
public void SetPositionZ()
{
//CameraPositionZ = -10;
while (true)
{
V1 = new Vector2(CameraPositionZ, 0);
V2 = new Vector2(CameraPositionZ, maxHeight);
angleDifference = Vector3.Angle(V1, V2);
// Debug.Log(angleDifference);
if (angleDifference > 31)
CameraPositionZ--;
else
{
renderCamera.transform.localPosition = new Vector3(center.x, center.y, CameraPositionZ);
break;
}
}
}
#endregion
GameObject CameraGo;
public void CreatePhotoCamera()
{
CameraGo = Instantiate(Resources.Load<GameObject>("CreatePhotoCamera"));
CameraGo.transform.SetParent(IcoImage.parent);
CameraGo.transform.localEulerAngles =Vector3.zero;
CameraGo.transform.localPosition = Vector3.zero;
renderCamera = CameraGo.GetComponent<Camera>();
}
public Image bg;
public void SetCenterPosition()
{
CreatePhotoCamera();
//float y = bg.rectTransform.sizeDelta.y/2-20;
//renderCamera.transform.localPosition = new Vector3(bg.rectTransform.localPosition.x, bg.rectTransform.localPosition.y, -200);
GetCenterPoint();
SetPositionZ();
}
public Texture2D CreatePhoto()
{
SetCenterPosition();
if (renderCamera != null)
{
// SetLayer();
//renderCamera是我们的拍摄照片用的相机,一般情况下给它关闭,防止它对我们主要的渲染结果造成影响。
//renderCamera.gameObject.SetActive(true);
//创建一个Texture2D 的纹理output ,作为一个临时纹理用于接收相机拍摄到的纹理
//这里使用大小是512x385和TextureFormat.RGB24类型的纹理格式,并关闭minmap,这里并不需要开启多级渐远纹理。(关于纹理格式和多级渐远纹理会在以后的文章补充)
//Texture2D output = new Texture2D(512, 358, TextureFormat.RGB24, false);
//如果需要在代码中将该带有透明通道的rt转为texture2D,需要使用类型为ARGB32或者RGBAFloat:
Texture2D output = new Texture2D(512, 512, TextureFormat.ARGB32, false);
//同样创建一个渲染纹理
RenderTexture renderTexture = new RenderTexture(512, 512, 32, RenderTextureFormat.ARGB32);
//RenderTexture renderTexture = new RenderTexture(512, 358, 32, RenderTextureFormat.ARGBFloat);
//这行代码将相机的渲染目标设置为上面创建的 renderTexture。这意味着,当相机进行渲染时,它的渲染结果将被保存到 renderTexture 中,而不是直接显示在屏幕上。
renderCamera.targetTexture = renderTexture;
//强制执行一次渲染,将渲染结果更新
renderCamera.Render();
//这行代码设置当前活动的渲染纹理为 renderTexture。这是为了确保接下来的 ReadPixels 操作读取的是 renderTexture 中的像素数据。
RenderTexture.active = renderTexture;
//rect_renderTexture 是一个矩形区域参数,用于定义要读取的区域。
Rect picture_renderTexture = new Rect(0, 0, 512, 512);
//这行代码从当前活动的渲染纹理(即renderTexture)中读取像素数据,并将其存储到 output 纹理对象中
output.ReadPixels(picture_renderTexture, 0, 0);
//这行代码应用了纹理的修改。在Unity中,ReadPixels 操作会修改纹理数据,但是这些修改不会立即生效,需要调用 Apply 方法来应用这些修改,使其生效。
output.Apply();
// Sprite sprite = Sprite.Create(output, new Rect(0, 0, output.width, output.height), new Vector2(0.5f, 0.5f));
// Material material = Plane.GetComponent<Renderer>().material;
//将生成的纹理覆盖到背景板上
// material.mainTexture = output;
//操作完毕后关闭渲染相机
// renderCamera.gameObject.SetActive(false);
// image.sprite = sprite;
renderCamera.targetTexture = null;
renderTexture.Release();
Destroy(renderTexture);
//ReSetLayer();
Destroy(CameraGo);
return output;
}
return null;
}
List<int> layerList = new List<int>();
[Button]
public void SetLayer()
{
layerList.Clear();
layerList.Add(go.layer);
// 设置游戏对象的层级
go.layer = LayerMask.NameToLayer("PointMarker");
// 遍历并设置所有子物体的层级
Transform[] transforms = go.GetComponentsInChildren<Transform>(true);
foreach (Transform child in transforms)
{
// 跳过父物体本身
if (child == go.transform) continue;
layerList.Add(child.gameObject.layer);
// 设置子物体的层级
child.gameObject.layer = go.layer;
}
}
[Button]
public void ReSetLayer()
{
go.layer = layerList[0];
int i = 0;
// 遍历并设置所有子物体的层级
Transform[] transforms = go.GetComponentsInChildren<Transform>(true);
foreach (Transform child in transforms)
{
// 跳过父物体本身
if (child == go.transform) continue;
i++;
// 设置子物体的层级
child.gameObject.layer = layerList[i];
}
}
}
相机RenderTexture拍照相关
于 2024-10-12 10:41:56 首次发布