我希望我的相机只渲染特定点半径范围内的物体,这一点与摄像机的位置无关,所以我应该可以绕着我世界的这个部分飞行。该中心点将作为游戏的一部分而改变。
我也希望边缘能够混合而不是立即结束(它将成为移动增强现实游戏)。
是否有现成的技术?可能是着色器还是什么?
答案 0 :(得分:0)
我玩弄了这个问题,想出了一些东西。我刚刚注意到这个问题仍然在这里,所以我想我会分享解决方案。
将以下脚本添加到相机
using UnityEngine;
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class UniverseSubSection : MonoBehaviour
{
public Shader shader;
[Header("Center of the universe")]
public Vector3 fixedCenterOfUniverse;
public Transform objectAtCenterOfUniverse;
[Header("Universe configuration")]
public float universeRadius = 2f;
public float featheringRadius = 1f;
public Color chromaKey = new Color(0, 1, 0, 0.618f);
public bool clipBelowGround = true;
[Header("Background")]
public Texture backgroundTexture;
public MonoBehaviour backgroundTextureProvider;
Material material;
new Camera camera;
void Update()
{
GetComponent<Camera>().depthTextureMode = DepthTextureMode.Depth;
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (material == null)
{
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
camera = GetComponent<Camera>();
camera.backgroundColor = chromaKey;
}
material.SetFloat("_UniverseRadius", universeRadius);
material.SetFloat("_FeatheringRadius", featheringRadius);
material.SetColor("_ChromaKey", chromaKey);
material.SetInt("_ClipBelowGround", clipBelowGround ? 1 : 0);
var matrix = camera.cameraToWorldMatrix;
material.SetMatrix("_InverseView", matrix);
Vector3 centerPosition = objectAtCenterOfUniverse != null ? objectAtCenterOfUniverse.position : fixedCenterOfUniverse;
material.SetVector("_CenterOfUniverse", centerPosition);
Texture background = null;
if (backgroundTexture != null)
background = backgroundTexture;
else if (Application.isPlaying && backgroundTextureProvider != null)
{
var provider = backgroundTextureProvider as IBackgroundTextureProvider;
Debug.Assert(provider != null, "BackgroundTextureProvider needs to be an IBackgroundTextureProvider");
background = provider.GetBackgroundTexture();
}
material.SetTexture("_BackgroundTex", background);
Graphics.Blit(source, destination, material);
}
public interface IBackgroundTextureProvider
{
Texture GetBackgroundTexture();
}
}
然后将组件的shader
属性链接到以下着色器
Shader "MrPMorris/Universe sub section"
{
Properties
{
_MainTex ("-", 2D) = ""{}
_CenterOfUniverse("Center of universe", VECTOR) = (0, 0, 0)
_UniverseRadius("Radius of the universe", float) = 2
_FeatheringRadius("Additional size to feather out edges of universe", float) = 1
_ChromaKey("Color in scene to render transparent", COLOR) = (0, 1, 0, 0.618)
_ClipBelowGround("1 = don't render below universe center, other = render it", INT) = 1
_BackgroundTex("Background texture", 2D) = ""{}
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _BackgroundTex;
half3 _CenterOfUniverse;
float _UniverseRadius;
float _FeatheringRadius;
half4 _ChromaKey;
int _ClipBelowGround;
sampler2D_float _CameraDepthTexture;
float4x4 _InverseView;
fixed4 frag (v2f_img i) : SV_Target
{
const float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
const float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._23);
const float isOrtho = unity_OrthoParams.w;
const float near = _ProjectionParams.y;
const float far = _ProjectionParams.z;
half2 upsideDownUV = half2(i.uv.x, i.uv.y);
#if UNITY_UV_STARTS_AT_TOP
upsideDownUV.y = 1 - upsideDownUV.y;
#endif
float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, upsideDownUV);
#if defined(UNITY_REVERSED_Z)
d = 1 - d;
#endif
float zOrtho = lerp(near, far, d);
float zPers = near * far / lerp(far, near, d);
float vz = lerp(zPers, zOrtho, isOrtho);
float3 vpos = float3((upsideDownUV * 2 - 1 - p13_31) / p11_22 * lerp(vz, 1, isOrtho), -vz);
float4 wpos = mul(_InverseView, float4(vpos, 1));
half4 source = tex2D(_MainTex, i.uv);
bool forceBackground =
(_ClipBelowGround == 1 && wpos.y < _CenterOfUniverse.y)
|| (source.r == _ChromaKey.r && source.g == _ChromaKey.g && source.b == _ChromaKey.b && source.a == _ChromaKey.a);
if (forceBackground)
return tex2D(_BackgroundTex, upsideDownUV);
float dist = distance(float4(_CenterOfUniverse, 0), wpos);
if (dist <= _UniverseRadius)
return source;
half4 backgroundPixel = tex2D(_BackgroundTex, upsideDownUV);
if (dist <= _UniverseRadius + _FeatheringRadius)
{
float featherDistance = dist - _UniverseRadius;
float opacity = (featherDistance / _FeatheringRadius);
return lerp(source, backgroundPixel, opacity);
}
return backgroundPixel;
}
ENDCG
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
ENDCG
}
}
}
如果您希望使用网络摄像头图像填充背景,您也可以添加此组件并在backgroundTextureProvider
属性中引用它。
using UnityEngine;
public class WebCamBackgroundTextureProvider : MonoBehaviour, UniverseSubSection.IBackgroundTextureProvider
{
WebCamTexture texture;
public Texture GetBackgroundTexture()
{
return texture;
}
// Use this for initialization
void Start()
{
if (WebCamTexture.devices.Length > 0)
{
texture = new WebCamTexture(WebCamTexture.devices[0].name);
texture.Play();
}
}
private void OnDestroy()
{
if (texture != null)
texture.Stop();
}
}