我如何仅在特定点的半径内渲染对象



我希望我的相机仅渲染在特定点半径内的对象,这一点将独立于相机的位置,因此我应该能够绕过我的小节。世界。该中心点将作为游戏的一部分变化。

我还希望边缘将Alpha-Blend淘汰而不是立即结束(这是移动设备的增强现实游戏)。

是否有现有技术可以做到这一点?也许是着色器之类的?

我有一个问题,并提出了一些东西。我刚刚注意到这个问题仍在这里,所以我认为我会分享解决方案。

将以下脚本添加到您的相机

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
        }
    }
}

如果您希望背景填充Web Cam Image。

,也可以在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();
    }
}

相关内容

  • 没有找到相关文章

最新更新