public static int CreateExternalTexture_s(IntPtr l)
    {
        int result;

        try
        {
            int size;
            LuaObject.checkType(l, 1, out size);
            TextureFormat format;
            LuaObject.checkEnum <TextureFormat>(l, 2, out format);
            bool mipmap;
            LuaObject.checkType(l, 3, out mipmap);
            IntPtr nativeTex;
            LuaObject.checkType(l, 4, out nativeTex);
            Cubemap o = Cubemap.CreateExternalTexture(size, format, mipmap, nativeTex);
            LuaObject.pushValue(l, true);
            LuaObject.pushValue(l, o);
            result = 2;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
示例#2
0
        /// <summary>
        /// Create a new <c>Cubemap</c> texture object with the given native texture object.
        /// </summary>
        /// <param name="textureDescriptor">The <c>XRTextureDescriptor</c> wrapping a native texture object.
        /// </param>
        /// <returns>
        /// The <c>Cubemap</c> object created from the given native texture object.
        /// </returns>
        Cubemap CreateEnvironmentTexture(XRTextureDescriptor textureDescriptor)
        {
            Debug.Assert(textureDescriptor.valid,
                         "cannot create a cubemap with an invalid native texture object");

            Cubemap cubemap = Cubemap.CreateExternalTexture(textureDescriptor.width,
                                                            textureDescriptor.format,
                                                            (textureDescriptor.mipmapCount != 0),
                                                            textureDescriptor.nativeTexture);

            cubemap.filterMode = m_EnvironmentTextureFilterMode;

            return(cubemap);
        }
        static void _ar_session_get_environment_texture_completion_handler(IntPtr callbackPtr, IntPtr texturePtr)
        {
            GCHandle handle             = GCHandle.FromIntPtr(callbackPtr);
            var      completionCallback = (Action <Cubemap>)handle.Target;

            if (texturePtr == IntPtr.Zero)
            {
                completionCallback(null);
            }
            else
            {
                completionCallback(Cubemap.CreateExternalTexture(0, TextureFormat.R8, false, texturePtr));
            }

            handle.Free();
        }
        /// <summary>
        /// Create the texture object for the native texture wrapped by the valid descriptor.
        /// </summary>
        /// <param name="descriptor">The texture descriptor wrapping a native texture object.</param>
        /// <returns>
        /// If the descriptor is valid, the <c>Texture</c> object created from the texture descriptor. Otherwise,
        /// <c>null</c>.
        /// </returns>
        static Texture CreateTexture(XRTextureDescriptor descriptor)
        {
            if (!descriptor.valid)
            {
                return(null);
            }

            switch (descriptor.dimension)
            {
#if UNITY_2020_2_OR_NEWER
            case TextureDimension.Tex3D:
                return(Texture3D.CreateExternalTexture(descriptor.width, descriptor.height,
                                                       descriptor.depth, descriptor.format,
                                                       (descriptor.mipmapCount != 0), descriptor.nativeTexture));
#endif
            case TextureDimension.Tex2D:
                var texture = Texture2D.CreateExternalTexture(descriptor.width, descriptor.height,
                                                              descriptor.format, (descriptor.mipmapCount != 0),
                                                              k_TextureHasLinearColorSpace,
                                                              descriptor.nativeTexture);
                // NB: SetWrapMode needs to be the first call here, and the value passed
                //     needs to be kTexWrapClamp - this is due to limitations of what
                //     wrap modes are allowed for external textures in OpenGL (which are
                //     used for ARCore), as Texture::ApplySettings will eventually hit
                //     an assert about an invalid enum (see calls to glTexParameteri
                //     towards the top of ApiGLES::TextureSampler)
                // reference: "3.7.14 External Textures" section of
                // https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
                // (it shouldn't ever matter what the wrap mode is set to normally, since
                // this is for a pass-through video texture, so we shouldn't ever need to
                // worry about the wrap mode as textures should never "wrap")
                texture.wrapMode   = TextureWrapMode.Clamp;
                texture.filterMode = FilterMode.Bilinear;
                texture.hideFlags  = HideFlags.HideAndDontSave;
                return(texture);

            case TextureDimension.Cube:
                return(Cubemap.CreateExternalTexture(descriptor.width,
                                                     descriptor.format,
                                                     (descriptor.mipmapCount != 0),
                                                     descriptor.nativeTexture));

            default:
                return(null);
            }
        }
示例#5
0
        public Cubemap GetReflectionCubemap(IntPtr sessionHandle, IntPtr lightEstimateHandle)
        {
            // Cubemap.CreateExternalTexture only exists in Unity 2017 above.
#if UNITY_2017_2_OR_NEWER
            int           textureId  = 0;
            int           size       = 0;
            bool          usingGLES3 = SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3;
            TextureFormat format     = usingGLES3 ? TextureFormat.RGBAHalf : TextureFormat.RGBA32;

            if (!m_PluginInitialized)
            {
                ExternApi.ARCoreRenderingUtils_SetGLESContext(usingGLES3);
                m_PluginInitialized = true;
            }

            ExternApi.ARCoreRenderingUtils_GetCubemapTexture(ref textureId, ref size);
            if (textureId != 0)
            {
                if (m_HDRCubemap == null || textureId != m_CubemaptextureId)
                {
                    m_HDRCubemap = Cubemap.CreateExternalTexture(size, format, true,
                                                                 new IntPtr(textureId));
                }
            }

            long timestamp = GetTimestamp(sessionHandle, lightEstimateHandle);
            if (m_CubemapTimestamp != timestamp)
            {
                ExternApi.ARCoreRenderingUtils_SetARCoreLightEstimation(sessionHandle,
                                                                        lightEstimateHandle);
                m_CubemapTimestamp = timestamp;
            }

            // Issue plugin event to update cubemap texture.
            GL.IssuePluginEvent(ExternApi.ARCoreRenderingUtils_GetRenderEventFunc(), 1);

            return(m_HDRCubemap);
#else
            return(null);
#endif
        }
示例#6
0
    private bool CreateLayerTextures(bool useMipmaps, OVRPlugin.Sizei size, bool isHdr)
    {
        if (isExternalSurface)
        {
            if (externalSurfaceObject == System.IntPtr.Zero)
            {
                externalSurfaceObject = OVRPlugin.GetLayerAndroidSurfaceObject(layerId);
                if (externalSurfaceObject != System.IntPtr.Zero)
                {
                    Debug.LogFormat("GetLayerAndroidSurfaceObject returns {0}", externalSurfaceObject);
                    if (externalSurfaceObjectCreated != null)
                    {
                        externalSurfaceObjectCreated();
                    }
                }
            }
            return(false);
        }

        bool needsCopy = false;

        if (stageCount <= 0)
        {
            return(false);
        }

        // For newer SDKs, blit directly to the surface that will be used in compositing.

        if (layerTextures == null)
        {
            layerTextures = new LayerTexture[texturesPerStage];
        }

        for (int eyeId = 0; eyeId < texturesPerStage; ++eyeId)
        {
            if (layerTextures[eyeId].swapChain == null)
            {
                layerTextures[eyeId].swapChain = new Texture[stageCount];
            }

            if (layerTextures[eyeId].swapChainPtr == null)
            {
                layerTextures[eyeId].swapChainPtr = new IntPtr[stageCount];
            }

            for (int stage = 0; stage < stageCount; ++stage)
            {
                Texture sc    = layerTextures[eyeId].swapChain[stage];
                IntPtr  scPtr = layerTextures[eyeId].swapChainPtr[stage];

                if (sc != null && scPtr != IntPtr.Zero && size.w == sc.width && size.h == sc.height)
                {
                    continue;
                }

                if (scPtr == IntPtr.Zero)
                {
                    scPtr = OVRPlugin.GetLayerTexture(layerId, stage, (OVRPlugin.Eye)eyeId);
                }

                if (scPtr == IntPtr.Zero)
                {
                    continue;
                }

                var txFormat = (isHdr) ? TextureFormat.RGBAHalf : TextureFormat.RGBA32;

                if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap)
                {
                    sc = Texture2D.CreateExternalTexture(size.w, size.h, txFormat, useMipmaps, true, scPtr);
                }
#if UNITY_2017_1_OR_NEWER
                else
                {
                    sc = Cubemap.CreateExternalTexture(size.w, txFormat, useMipmaps, scPtr);
                }
#endif

                layerTextures[eyeId].swapChain[stage]    = sc;
                layerTextures[eyeId].swapChainPtr[stage] = scPtr;

                needsCopy = true;
            }
        }

        return(needsCopy);
    }
示例#7
0
        public Cubemap GetReflectionCubemap(IntPtr sessionHandle, IntPtr lightEstimateHandle)
        {
            int  size = 0;
            bool usingGammaWorkflow = QualitySettings.activeColorSpace == ColorSpace.Gamma;

#if UNITY_2017_2_OR_NEWER
            // Cubemap.CreateExternalTexture only exists in Unity 2017 above.
            int textureId = 0;
            ApiTextureDataType dataType =
                SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3 ?
                ApiTextureDataType.Half : ApiTextureDataType.Byte;
            TextureFormat format = dataType == ApiTextureDataType.Half ?
                                   TextureFormat.RGBAHalf : TextureFormat.RGBA32;

            if (!m_PluginInitialized)
            {
                ExternApi.ARCoreRenderingUtils_SetTextureDataType(dataType, true);
                ExternApi.ARCoreRenderingUtils_SetActiveColorSpace(usingGammaWorkflow);
                m_PluginInitialized = true;
            }

            ExternApi.ARCoreRenderingUtils_GetCubemapTexture(ref textureId, ref size);
            if (textureId != 0 && (m_HDRCubemap == null || textureId != m_CubemapTextureId))
            {
                m_HDRCubemap = Cubemap.CreateExternalTexture(size, format, true,
                                                             new IntPtr(textureId));
                m_CubemapTextureId = textureId;
            }

            long timestamp = GetTimestamp(sessionHandle, lightEstimateHandle);
            if (m_CubemapTimestamp != timestamp)
            {
                ExternApi.ARCoreRenderingUtils_SetARCoreLightEstimation(sessionHandle,
                                                                        lightEstimateHandle);
                m_CubemapTimestamp = timestamp;
            }

            // Issue plugin event to update cubemap texture.
            GL.IssuePluginEvent(ExternApi.ARCoreRenderingUtils_GetRenderEventFunc(), 1);
#else
            // Gets raw color data from native plugin then update cubemap textures by
            // Cubemap.SetPixel().
            // Note, no GL texture will be created in this scenario.
            if (!m_PluginInitialized)
            {
                ExternApi.ARCoreRenderingUtils_SetTextureDataType(
                    ApiTextureDataType.Float, false);
                ExternApi.ARCoreRenderingUtils_SetActiveColorSpace(usingGammaWorkflow);
                m_PluginInitialized = true;
            }

            ExternApi.ARCoreRenderingUtils_GetCubemapTexture(ref m_CubemapTextureId, ref size);
            if (size > 0)
            {
                if (m_HDRCubemap == null)
                {
                    m_HDRCubemap = new Cubemap(size, TextureFormat.RGBAHalf, true);
                }

                if (m_TempCubemapFacePixels.Length != size)
                {
                    Array.Resize(ref m_TempCubemapFacePixels, size * size);
                }
            }

            long timestamp = GetTimestamp(sessionHandle, lightEstimateHandle);
            if (m_CubemapTimestamp != timestamp)
            {
                ExternApi.ARCoreRenderingUtils_SetARCoreLightEstimation(sessionHandle,
                                                                        lightEstimateHandle);
                m_CubemapTimestamp = timestamp;

                if (m_HDRCubemap != null)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        ExternApi.ARCoreRenderingUtils_GetCubemapRawColors(i,
                                                                           m_TempCubemapFacePixels);
                        m_HDRCubemap.SetPixels(m_TempCubemapFacePixels, CubemapFace.PositiveX + i);
                    }

                    // This operation is very expensive, only update cubemap texture when
                    // the light estimate is updated in this frame.
                    m_HDRCubemap.Apply();
                }
            }
#endif

            return(m_HDRCubemap);
        }
示例#8
0
    void Awake()
    {
        Debug.Log("Overlay Awake");

        if (premultiplyMaterial == null)
        {
            premultiplyMaterial = new Material(Shader.Find("Oculus/Alpha Premultiply"));
        }

        rend = GetComponent <Renderer>();

        if (textures.Length == 0)
        {
            textures = new Texture[] { null }
        }
        ;

        // Backward compatibility
        if (rend != null && textures[0] == null)
        {
            textures[0] = rend.material.mainTexture;
        }

        if (textures[0] != null)
        {
            cachedTextures[0] = textures[0];
            texNativePtrs[0]  = textures[0].GetNativeTexturePtr();
        }

#if UNITY_ANDROID && !UNITY_EDITOR
        if (textures.Length == 2 && textures[1] != null)
        {
            layout = (isMultiviewEnabled) ? OVRPlugin.LayerLayout.Array : OVRPlugin.LayerLayout.Stereo;
        }
        texturesPerStage = (layout == OVRPlugin.LayerLayout.Stereo) ? 2 : 1;
#endif
    }

    void OnEnable()
    {
        if (!OVRManager.isHmdPresent)
        {
            enabled = false;
            return;
        }

        OnDisable();

        for (int i = 0; i < maxInstances; ++i)
        {
            if (instances[i] == null || instances[i] == this)
            {
                layerIndex   = i;
                instances[i] = this;
                break;
            }
        }

        layerIdHandle = GCHandle.Alloc(layerId, GCHandleType.Pinned);
        layerIdPtr    = layerIdHandle.AddrOfPinnedObject();
    }

    void OnDisable()
    {
        if (layerIndex != -1)
        {
            // Turn off the overlay if it was on.
            OVRPlugin.EnqueueSubmitLayer(true, false, IntPtr.Zero, IntPtr.Zero, -1, 0, OVRPose.identity.ToPosef(), Vector3.one.ToVector3f(), layerIndex, (OVRPlugin.OverlayShape)_prevOverlayShape);
            instances[layerIndex] = null;
        }

        if (layerIdPtr != IntPtr.Zero)
        {
            OVRPlugin.EnqueueDestroyLayer(layerIdPtr);
            layerIdPtr = IntPtr.Zero;
            layerIdHandle.Free();
        }

        layerIndex = -1;
    }

    int prevFrameIndex = -1;

    void OnRenderObject()
    {
        // The overlay must be specified every eye frame, because it is positioned relative to the
        // current head location.  If frames are dropped, it will be time warped appropriately,
        // just like the eye buffers.
        if (!Camera.current.CompareTag("MainCamera") || Camera.current.cameraType != CameraType.Game || layerIndex == -1 || currentOverlayType == OverlayType.None || textures.Length < texturesPerStage)
        {
            return;
        }


        // Don't submit the same frame twice.
        if (Time.frameCount <= prevFrameIndex)
        {
            return;
        }
        prevFrameIndex = Time.frameCount;

#if !UNITY_ANDROID || UNITY_EDITOR
        if (currentOverlayShape == OverlayShape.OffcenterCubemap)
        {
            Debug.LogWarning("Overlay shape " + currentOverlayShape + " is not supported on current platform");
        }
#endif

        for (int i = 0; i < texturesPerStage; ++i)
        {
            if (textures[i] != cachedTextures[i])
            {
                cachedTextures[i] = textures[i];
                if (cachedTextures[i] != null)
                {
                    texNativePtrs[i] = cachedTextures[i].GetNativeTexturePtr();
                }
            }

            if (currentOverlayShape == OverlayShape.Cubemap)
            {
                if (textures[i] != null && textures[i].GetType() != typeof(Cubemap))
                {
                    Debug.LogError("Need Cubemap texture for cube map overlay");
                    return;
                }
            }
        }

        if (cachedTextures[0] == null || texNativePtrs[0] == IntPtr.Zero)
        {
            return;
        }

        bool overlay    = (currentOverlayType == OverlayType.Overlay);
        bool headLocked = false;
        for (var t = transform; t != null && !headLocked; t = t.parent)
        {
            headLocked |= (t == Camera.current.transform);
        }

        OVRPose pose  = (headLocked) ? transform.ToHeadSpacePose() : transform.ToTrackingSpacePose();
        Vector3 scale = transform.lossyScale;
        for (int i = 0; i < 3; ++i)
        {
            scale[i] /= Camera.current.transform.lossyScale[i];
        }
#if !UNITY_ANDROID
        if (currentOverlayShape == OverlayShape.Cubemap)
        {
            pose.position = Camera.current.transform.position;
        }
#endif
        // Pack the offsetCenter directly into pose.position for offcenterCubemap
        if (currentOverlayShape == OverlayShape.OffcenterCubemap)
        {
            pose.position = transform.position;
            if (pose.position.magnitude > 1.0f)
            {
                Debug.LogWarning("your cube map center offset's magnitude is greater than 1, which will cause some cube map pixel always invisible .");
            }
        }
        // Cylinder overlay sanity checking
        if (currentOverlayShape == OverlayShape.Cylinder)
        {
            float arcAngle = scale.x / scale.z / (float)Math.PI * 180.0f;
            if (arcAngle > 180.0f)
            {
                Debug.LogError("Cylinder overlay's arc angle has to be below 180 degree, current arc angle is " + arcAngle + " degree.");
                return;
            }
        }

        OVRPlugin.Sizei size = new OVRPlugin.Sizei()
        {
            w = textures[0].width, h = textures[0].height
        };
        int           flags                 = (int)OVRPlugin.LayerFlags.TextureOriginAtBottomLeft;
        int           mipLevels             = 1;
        int           sampleCount           = 1;
        TextureFormat txFormat              = TextureFormat.BGRA32;
        OVRPlugin.EyeTextureFormat etFormat = OVRPlugin.EyeTextureFormat.B8G8R8A8_sRGB;
        RenderTextureFormat        rtFormat = RenderTextureFormat.BGRA32;

        var tex2D = textures[0] as Texture2D;
        if (tex2D != null)
        {
            if (tex2D.format == TextureFormat.RGBAHalf || tex2D.format == TextureFormat.RGBAFloat)
            {
                txFormat = TextureFormat.RGBAHalf;
                etFormat = OVRPlugin.EyeTextureFormat.R16G16B16A16_FP;
                rtFormat = RenderTextureFormat.ARGBHalf;
            }
        }

        var rt = textures[0] as RenderTexture;
        if (rt != null)
        {
            sampleCount = rt.antiAliasing;

            if (rt.format == RenderTextureFormat.ARGBHalf)
            {
                txFormat = TextureFormat.RGBAHalf;
                etFormat = OVRPlugin.EyeTextureFormat.R16G16B16A16_FP;
                rtFormat = RenderTextureFormat.ARGBHalf;
            }
        }

        bool needsSetup = (
            !layerDesc.TextureSize.Equals(size) ||
            layerDesc.SampleCount != sampleCount ||
            layerDesc.LayerFlags != flags ||
            layerDesc.Shape != (OVRPlugin.OverlayShape)currentOverlayShape ||
            layerDesc.Layout != layout ||
            layerDesc.Format != etFormat);

        OVRPlugin.LayerDesc desc = new OVRPlugin.LayerDesc();

        if (layerIdPtr != IntPtr.Zero && needsSetup)
        {
            if ((int)layerIdHandle.Target != 0)
            {
                OVRPlugin.EnqueueDestroyLayer(layerIdPtr);
            }

            desc = OVRPlugin.CalculateLayerDesc((OVRPlugin.OverlayShape)currentOverlayShape, layout, size, mipLevels, sampleCount, etFormat, flags);
            OVRPlugin.EnqueueSetupLayer(desc, layerIdPtr);
            layerId = (int)layerIdHandle.Target;

            if (layerId > 0)
            {
                layerDesc = desc;
            }
        }

        if (layerId > 0)
        {
            // For newer SDKs, blit directly to the surface that will be used in compositing.

            int stageCount = OVRPlugin.GetLayerTextureStageCount(layerId);

            if (externalTextures == null)
            {
                frameIndex       = 0;
                externalTextures = new Texture[texturesPerStage][];
            }

            for (int eyeId = 0; eyeId < texturesPerStage; ++eyeId)
            {
                if (externalTextures[eyeId] == null)
                {
                    externalTextures[eyeId] = new Texture[stageCount];
                }

                int stage = frameIndex % stageCount;

                IntPtr externalTex = OVRPlugin.GetLayerTexture(layerId, stage, (OVRPlugin.Eye)eyeId);

                if (externalTex == IntPtr.Zero)
                {
                    continue;
                }

                bool needsCopy = isDynamic;

                Texture et = externalTextures[eyeId][stage];
                if (et == null)
                {
                    bool isSrgb = (etFormat == OVRPlugin.EyeTextureFormat.B8G8R8A8_sRGB || etFormat == OVRPlugin.EyeTextureFormat.R8G8B8A8_sRGB);

                    if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap)
                    {
                        et = Texture2D.CreateExternalTexture(size.w, size.h, txFormat, mipLevels > 1, isSrgb, externalTex);
                    }
#if UNITY_2017_1_OR_NEWER
                    else
                    {
                        //et = Cubemap.CreateExternalTexture(size.w, size.h, txFormat, mipLevels > 1, isSrgb, externalTex);
                        et = Cubemap.CreateExternalTexture(size.w, txFormat, isSrgb, externalTex);
                    }
#endif

                    externalTextures[eyeId][stage] = et;
                    needsCopy = true;
                }

                if (needsCopy)
                {
                    // The compositor uses premultiplied alpha, so multiply it here.
                    if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap)
                    {
                        var tempRT = RenderTexture.GetTemporary(size.w, size.h, 0, rtFormat, RenderTextureReadWrite.Default, sampleCount);
#if UNITY_ANDROID && !UNITY_EDITOR
                        Graphics.Blit(textures[eyeId], tempRT);                         //Resolve, decompress, swizzle, etc not handled by simple CopyTexture.
#else
                        Graphics.Blit(textures[eyeId], tempRT, premultiplyMaterial);
#endif
                        Graphics.CopyTexture(tempRT, 0, 0, et, 0, 0);
                        RenderTexture.ReleaseTemporary(tempRT);
                    }
#if UNITY_2017_1_OR_NEWER
                    else
                    {
                        var tempRTSrc = RenderTexture.GetTemporary(size.w, size.h, 0, rtFormat, RenderTextureReadWrite.Default, sampleCount);
                        var tempRTDst = RenderTexture.GetTemporary(size.w, size.h, 0, rtFormat, RenderTextureReadWrite.Default, sampleCount);

                        for (int face = 0; face < 6; ++face)
                        {
                            //HACK: It would be much more efficient to blit directly from textures[eyeId] to et, but Unity's API doesn't support that.
                            //Suggest using a native plugin to render directly to a cubemap layer for 360 video, etc.
                            Graphics.CopyTexture(textures[eyeId], face, 0, tempRTSrc, 0, 0);
                            Graphics.Blit(tempRTSrc, tempRTDst, premultiplyMaterial);
                            Graphics.CopyTexture(tempRTDst, 0, 0, et, face, 0);
                        }
                        RenderTexture.ReleaseTemporary(tempRTSrc);
                        RenderTexture.ReleaseTemporary(tempRTDst);
                    }
#endif
                }
            }

            bool isOverlayVisible = OVRPlugin.EnqueueSubmitLayer(overlay, headLocked, texNativePtrs[0], texNativePtrs[1], layerId, frameIndex, pose.flipZ().ToPosef(), scale.ToVector3f(), layerIndex, (OVRPlugin.OverlayShape)currentOverlayShape);
            if (isDynamic)
            {
                ++frameIndex;
            }
            _prevOverlayShape = currentOverlayShape;
            if (rend)
            {
                rend.enabled = !isOverlayVisible;
            }
        }
    }
}