UGUI—RawImage

作者:追风剑情 发布于:2020-9-29 12:38 分类:Unity3d

示例一:通过Texture内存指针显示画面

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 通过Texture内存指针显示画面
/// </summary>
public class IntPtrRawImage : RawImage
{
    public int textureWidth = 640;
    public int textureHeight = 360;
    private Texture2D m_Texture2D;
    private IntPtr m_TexturePtr = IntPtr.Zero;
    private bool m_Started = false;

    protected override void Awake()
    {
        base.Awake();
        m_Texture2D = new Texture2D(textureWidth, textureHeight, TextureFormat.RGB24, false);
        this.texture = m_Texture2D;
    }

    protected override void Start()
    {
        base.Start();
        m_Started = true;
        if (m_TexturePtr != IntPtr.Zero)
            UpdateExternalTexture(m_TexturePtr);
    }

    public void UpdateExternalTexture(IntPtr ptr)
    {
        m_TexturePtr = ptr;
        if (ptr == IntPtr.Zero)
            return;
        if (!m_Started)
            return;
        m_Texture2D.UpdateExternalTexture(ptr);
    }

    public void Show()
    {
        gameObject.SetActive(true);
    }

    public void Hide()
    {
        gameObject.SetActive(false);
    }
}


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
///  通过内存指针显示视频
/// </summary>
public class VideoRawImage : MonoBehaviour
{
    public int videoWidth = 640;    //视频宽度
    public int videoHeight = 360;   //视频高度
    public bool localVideo = false; //true:显示本地摄像头画面

    private Texture2D m_Texture2D;  //视频图像
    private RawImage m_RawImage;    //显示视频图像的RawImage
    [SerializeField]
    private Material m_VideoMat;
    public IntPtr ExternalPtr { get; private set; }

    private void Awake()
    {
        m_Texture2D = new Texture2D(videoWidth, videoHeight, TextureFormat.RGB24, false);
        m_RawImage = this.GetComponent<RawImage>();
        m_RawImage.texture = m_Texture2D;
        m_RawImage.color = Color.white;
        ExternalPtr = IntPtr.Zero;
        if (m_VideoMat != null)
            m_RawImage.material = m_VideoMat;
    }

    public void SetMaterial(Material material)
    {
        m_RawImage.material = material;
    }

    public void UpdateExternalTexture(IntPtr texPtr)
    {
        ExternalPtr = texPtr;
        if (texPtr != IntPtr.Zero)
        {
            m_RawImage.enabled = true;
            m_Texture2D.UpdateExternalTexture(texPtr);
        }
        else
            Debug.LogError("Video Texture ptr is IntPtr.Zero");
    }

    public void Show(bool value=true)
    {
        gameObject.SetActive(value);
    }

    public void Hide()
    {
        gameObject.SetActive(false);
    }

    public void SetPosZ(float z)
    {
        RectTransform rt = this.GetComponent<RectTransform>();
        Vector3 anchoredPosition3D = rt.anchoredPosition3D;
        anchoredPosition3D.z = z;
        rt.anchoredPosition3D = anchoredPosition3D;
    }

    public Texture2D CloneTexture()
    {
        Texture2D newTex = new Texture2D(videoWidth, videoHeight, TextureFormat.RGB24, false);
        if (m_Texture2D.isReadable) {
            //通过指针渲染的Texture,无法读取像素数据
            Color[] colors = m_Texture2D.GetPixels();
            newTex.SetPixels(colors);
            newTex.Apply();
        } else {
            Debug.LogError("Not Read Texture Data.(m_Texture2D.isReadable=false)");
        }
        return newTex;
    }

    public Texture2D ConvertTexture()
    {
        int w = m_Texture2D.width;
        int h = m_Texture2D.height;
        Texture2D destTex = new Texture2D(w, h, TextureFormat.ARGB32, false);
        //通过指针渲染的Texture,无法读取像素数据
        Graphics.ConvertTexture(m_Texture2D, destTex);
        destTex.Apply();
        return destTex;
    }
}


旋转图片Shader

Shader "Custom/RotationImageShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Toggle(CONTRAROTATE_90)]
        _Clockwise90("顺时针(90)", Float) = 1
        [Toggle(CONTRAROTATE_180)]
        _Clockwise180("顺时针(180)", Float) = 0
        [Toggle(CONTRAROTATE_270)]
        _Clockwise270("逆时针(90)", Float) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma multi_compile __ CONTRAROTATE_90 CONTRAROTATE_180 CONTRAROTATE_270
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed2 uv = i.uv;

                //旋转画面
                #ifdef CONTRAROTATE_90
                uv = fixed2(1 - i.uv.y, i.uv.x); //顺时针 (90)
                #endif
                
                #ifdef CONTRAROTATE_180
                uv = fixed2(1 - i.uv.x, 1 - i.uv.y); //顺时针 (180)
                #endif

                #ifdef CONTRAROTATE_270
                uv = fixed2(i.uv.y, 1 - i.uv.x); //逆时针 (-90)
                #endif

                fixed4 col = tex2D(_MainTex, uv);
                return col;
            }
            ENDCG
        }
    }
}

如果图片放在ScrollView中,需要考虑裁剪区


//当图像处于ScrollView中时,超出viewport区的像素需要裁剪掉。
Shader "Custom/RotationImageClip"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Toggle(CONTRAROTATE)]
        _Clockwise("顺时针(90)", Float) = 1
        //记录裁剪框的四个边界的值
        _ClipArea("ClipArea", Vector) = (0,0,1,1)
        //----end----
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #pragma multi_compile __ CONTRAROTATE
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float2 worldPos : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _ClipArea;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                //模型坐标转世界坐标
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xy;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //画面旋转90度
                #ifdef CONTRAROTATE
                fixed2 uv = fixed2(1 - i.uv.y, i.uv.x); //顺时针
                #else
                fixed2 uv = fixed2(i.uv.y, 1 - i.uv.x); //逆时针
                #endif
                fixed4 col = tex2D(_MainTex, uv);

                bool inArea = i.worldPos.x >= _ClipArea.x && i.worldPos.x <= _ClipArea.z && i.worldPos.y >= _ClipArea.y && i.worldPos.y <= _ClipArea.w;
                clip(inArea-0.5);//丢掉小于0的像素
                return col;
            }
            ENDCG
        }
    }
}


标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号