private void ConfigureEyeDesc(OVREye eye) { Vector2 texSize = Vector2.zero; Vector2 fovSize = Vector2.zero; #if !UNITY_ANDROID || UNITY_EDITOR if (!OVRManager.instance.isVRPresent) { return; } OVRPlugin.Sizei size = OVRPlugin.GetEyeTextureSize((OVRPlugin.Eye)eye); OVRPlugin.Frustumf frustum = OVRPlugin.GetEyeFrustum((OVRPlugin.Eye)eye); texSize = new Vector2(size.w, size.h); fovSize = Mathf.Rad2Deg * new Vector2(frustum.fovX, frustum.fovY); #else texSize = new Vector2(1024, 1024) * OVRManager.instance.nativeTextureScale; fovSize = new Vector2(90, 90); #endif eyeDescs[(int)eye] = new EyeRenderDesc() { resolution = texSize, fov = fovSize }; }
// Token: 0x060037EB RID: 14315 RVA: 0x0011D018 File Offset: 0x0011B418 private void ConfigureEyeDesc(VRNode eye) { if (!OVRManager.isHmdPresent) { return; } OVRPlugin.Sizei eyeTextureSize = OVRPlugin.GetEyeTextureSize((OVRPlugin.Eye)eye); OVRPlugin.Frustumf eyeFrustum = OVRPlugin.GetEyeFrustum((OVRPlugin.Eye)eye); this.eyeDescs[(int)eye] = new OVRDisplay.EyeRenderDesc { resolution = new Vector2((float)eyeTextureSize.w, (float)eyeTextureSize.h), fov = 57.29578f * new Vector2(eyeFrustum.fovX, eyeFrustum.fovY) }; }
private bool CreateLayerTextures(bool useMipmaps, OVRPlugin.Sizei size, bool isHdr) { bool result = false; if (this.stageCount <= 0) { return(false); } if (this.layerTextures == null) { this.frameIndex = 0; this.layerTextures = new OVROverlay.LayerTexture[this.texturesPerStage]; } for (int i = 0; i < this.texturesPerStage; i++) { if (this.layerTextures[i].swapChain == null) { this.layerTextures[i].swapChain = new Texture[this.stageCount]; } if (this.layerTextures[i].swapChainPtr == null) { this.layerTextures[i].swapChainPtr = new IntPtr[this.stageCount]; } for (int j = 0; j < this.stageCount; j++) { Texture texture = this.layerTextures[i].swapChain[j]; IntPtr intPtr = this.layerTextures[i].swapChainPtr[j]; if (!(texture != null) || !(intPtr != IntPtr.Zero)) { if (intPtr == IntPtr.Zero) { intPtr = OVRPlugin.GetLayerTexture(this.layerId, j, (OVRPlugin.Eye)i); } if (!(intPtr == IntPtr.Zero)) { TextureFormat format = (!isHdr) ? TextureFormat.RGBA32 : TextureFormat.RGBAHalf; if (this.currentOverlayShape != OVROverlay.OverlayShape.Cubemap && this.currentOverlayShape != OVROverlay.OverlayShape.OffcenterCubemap) { texture = Texture2D.CreateExternalTexture(size.w, size.h, format, useMipmaps, true, intPtr); } this.layerTextures[i].swapChain[j] = texture; this.layerTextures[i].swapChainPtr[j] = intPtr; result = true; } } } } return(result); }
private void ConfigureEyeDesc(VR.VRNode eye) { if (!OVRManager.isHmdPresent) { return; } OVRPlugin.Sizei size = OVRPlugin.GetEyeTextureSize((OVRPlugin.Eye)eye); OVRPlugin.Frustumf frust = OVRPlugin.GetEyeFrustum((OVRPlugin.Eye)eye); eyeDescs[(int)eye] = new EyeRenderDesc() { resolution = new Vector2(size.w, size.h), fov = Mathf.Rad2Deg * new Vector2(frust.fovX, frust.fovY), }; }
private bool PopulateLayer(int mipLevels, bool isHdr, OVRPlugin.Sizei size, int sampleCount) { bool result = false; RenderTextureFormat format = (!isHdr) ? RenderTextureFormat.ARGB32 : RenderTextureFormat.ARGBHalf; for (int i = 0; i < this.texturesPerStage; i++) { int dstElement = (this.layout != OVRPlugin.LayerLayout.Array) ? 0 : i; int num = this.frameIndex % this.stageCount; Texture texture = this.layerTextures[i].swapChain[num]; if (!(texture == null)) { for (int j = 0; j < mipLevels; j++) { int num2 = size.w >> j; if (num2 < 1) { num2 = 1; } int num3 = size.h >> j; if (num3 < 1) { num3 = 1; } RenderTexture temporary = RenderTexture.GetTemporary(num2, num3, 0, format, RenderTextureReadWrite.Linear, sampleCount); if (!temporary.IsCreated()) { temporary.Create(); } temporary.DiscardContents(); RenderTexture renderTexture = this.textures[i] as RenderTexture; bool flag = isHdr || QualitySettings.activeColorSpace == ColorSpace.Linear; flag |= (renderTexture != null && renderTexture.sRGB); if (this.currentOverlayShape != OVROverlay.OverlayShape.Cubemap && this.currentOverlayShape != OVROverlay.OverlayShape.OffcenterCubemap) { OVROverlay.tex2DMaterial.SetInt("_linearToSrgb", (isHdr || !flag) ? 0 : 1); OVROverlay.tex2DMaterial.SetInt("_premultiply", 1); Graphics.Blit(this.textures[i], temporary, OVROverlay.tex2DMaterial); Graphics.CopyTexture(temporary, 0, 0, texture, dstElement, j); } RenderTexture.ReleaseTemporary(temporary); result = true; } } } return(result); }
private void ConfigureEyeDesc(UnityEngine.VR.VRNode eye) #endif { if (!OVRManager.isHmdPresent) { return; } OVRPlugin.Sizei size = OVRPlugin.GetEyeTextureSize((OVRPlugin.Eye)eye); eyeDescs[(int)eye] = new EyeRenderDesc(); eyeDescs[(int)eye].resolution = new Vector2(size.w, size.h); OVRPlugin.Frustumf2 frust; if (OVRPlugin.GetNodeFrustum2((OVRPlugin.Node)eye, out frust)) { eyeDescs[(int)eye].fullFov.LeftFov = Mathf.Rad2Deg * Mathf.Atan(frust.Fov.LeftTan); eyeDescs[(int)eye].fullFov.RightFov = Mathf.Rad2Deg * Mathf.Atan(frust.Fov.RightTan); eyeDescs[(int)eye].fullFov.UpFov = Mathf.Rad2Deg * Mathf.Atan(frust.Fov.UpTan); eyeDescs[(int)eye].fullFov.DownFov = Mathf.Rad2Deg * Mathf.Atan(frust.Fov.DownTan); } else { OVRPlugin.Frustumf frustOld = OVRPlugin.GetEyeFrustum((OVRPlugin.Eye)eye); eyeDescs[(int)eye].fullFov.LeftFov = Mathf.Rad2Deg * frustOld.fovX * 0.5f; eyeDescs[(int)eye].fullFov.RightFov = Mathf.Rad2Deg * frustOld.fovX * 0.5f; eyeDescs[(int)eye].fullFov.UpFov = Mathf.Rad2Deg * frustOld.fovY * 0.5f; eyeDescs[(int)eye].fullFov.DownFov = Mathf.Rad2Deg * frustOld.fovY * 0.5f; } // Symmetric Fov uses the maximum fov angle float maxFovX = Mathf.Max(eyeDescs[(int)eye].fullFov.LeftFov, eyeDescs[(int)eye].fullFov.RightFov); float maxFovY = Mathf.Max(eyeDescs[(int)eye].fullFov.UpFov, eyeDescs[(int)eye].fullFov.DownFov); eyeDescs[(int)eye].fov.x = maxFovX * 2.0f; eyeDescs[(int)eye].fov.y = maxFovY * 2.0f; if (!OVRPlugin.AsymmetricFovEnabled) { eyeDescs[(int)eye].fullFov.LeftFov = maxFovX; eyeDescs[(int)eye].fullFov.RightFov = maxFovX; eyeDescs[(int)eye].fullFov.UpFov = maxFovY; eyeDescs[(int)eye].fullFov.DownFov = maxFovY; } }
private bool PopulateLayer(int mipLevels, bool isHdr, OVRPlugin.Sizei size, int sampleCount, int stage) { if (isExternalSurface) { return(true); } bool ret = false; RenderTextureFormat rtFormat = (isHdr) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; for (int eyeId = 0; eyeId < texturesPerStage; ++eyeId) { Texture et = layerTextures[eyeId].swapChain[stage]; if (et == null) { continue; } for (int mip = 0; mip < mipLevels; ++mip) { int width = size.w >> mip; if (width < 1) { width = 1; } int height = size.h >> mip; if (height < 1) { height = 1; } #if UNITY_2017_1_1 || UNITY_2017_2_OR_NEWER RenderTextureDescriptor descriptor = new RenderTextureDescriptor(width, height, rtFormat, 0); descriptor.msaaSamples = sampleCount; descriptor.useMipMap = true; descriptor.autoGenerateMips = false; descriptor.sRGB = false; var tempRTDst = RenderTexture.GetTemporary(descriptor); #else var tempRTDst = RenderTexture.GetTemporary(width, height, 0, rtFormat, RenderTextureReadWrite.Linear, sampleCount); #endif if (!tempRTDst.IsCreated()) { tempRTDst.Create(); } tempRTDst.DiscardContents(); bool dataIsLinear = isHdr || (QualitySettings.activeColorSpace == ColorSpace.Linear); #if !UNITY_2017_1_OR_NEWER var rt = textures[eyeId] as RenderTexture; dataIsLinear |= rt != null && rt.sRGB; //HACK: Unity 5.6 and earlier convert to linear on read from sRGB RenderTexture. #endif #if UNITY_ANDROID && !UNITY_EDITOR dataIsLinear = true; //HACK: Graphics.CopyTexture causes linear->srgb conversion on target write with D3D but not GLES. #endif if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap) { tex2DMaterial.SetInt("_linearToSrgb", (!isHdr && dataIsLinear) ? 1 : 0); //Resolve, decompress, swizzle, etc not handled by simple CopyTexture. #if !UNITY_ANDROID || UNITY_EDITOR // The PC compositor uses premultiplied alpha, so multiply it here. tex2DMaterial.SetInt("_premultiply", 1); #endif Graphics.Blit(textures[eyeId], tempRTDst, tex2DMaterial); Graphics.CopyTexture(tempRTDst, 0, 0, et, 0, mip); } #if UNITY_2017_1_OR_NEWER else // Cubemap { for (int face = 0; face < 6; ++face) { cubeMaterial.SetInt("_linearToSrgb", (!isHdr && dataIsLinear) ? 1 : 0); #if !UNITY_ANDROID || UNITY_EDITOR // The PC compositor uses premultiplied alpha, so multiply it here. cubeMaterial.SetInt("_premultiply", 1); #endif cubeMaterial.SetInt("_face", face); //Resolve, decompress, swizzle, etc not handled by simple CopyTexture. Graphics.Blit(textures[eyeId], tempRTDst, cubeMaterial); Graphics.CopyTexture(tempRTDst, 0, 0, et, face, mip); } } #endif RenderTexture.ReleaseTemporary(tempRTDst); ret = true; } } return(ret); }
private OVRPlugin.LayerDesc GetCurrentLayerDesc() { OVRPlugin.Sizei textureSize = new OVRPlugin.Sizei() { w = 0, h = 0 }; if (isExternalSurface) { textureSize.w = externalSurfaceWidth; textureSize.h = externalSurfaceHeight; } else { if (textures[0] == null) { Debug.LogWarning("textures[0] hasn't been set"); } textureSize.w = textures[0] ? textures[0].width : 0; textureSize.h = textures[0] ? textures[0].height : 0; } OVRPlugin.LayerDesc newDesc = new OVRPlugin.LayerDesc() { Format = OVRPlugin.EyeTextureFormat.R8G8B8A8_sRGB, LayerFlags = isExternalSurface ? 0 : (int)OVRPlugin.LayerFlags.TextureOriginAtBottomLeft, Layout = layout, MipLevels = 1, SampleCount = 1, Shape = (OVRPlugin.OverlayShape)currentOverlayShape, TextureSize = textureSize }; var tex2D = textures[0] as Texture2D; if (tex2D != null) { if (tex2D.format == TextureFormat.RGBAHalf || tex2D.format == TextureFormat.RGBAFloat) { newDesc.Format = OVRPlugin.EyeTextureFormat.R16G16B16A16_FP; } newDesc.MipLevels = tex2D.mipmapCount; } var texCube = textures[0] as Cubemap; if (texCube != null) { if (texCube.format == TextureFormat.RGBAHalf || texCube.format == TextureFormat.RGBAFloat) { newDesc.Format = OVRPlugin.EyeTextureFormat.R16G16B16A16_FP; } newDesc.MipLevels = texCube.mipmapCount; } var rt = textures[0] as RenderTexture; if (rt != null) { newDesc.SampleCount = rt.antiAliasing; if (rt.format == RenderTextureFormat.ARGBHalf || rt.format == RenderTextureFormat.ARGBFloat || rt.format == RenderTextureFormat.RGB111110Float) { newDesc.Format = OVRPlugin.EyeTextureFormat.R16G16B16A16_FP; } } if (isProtectedContent) { newDesc.LayerFlags |= (int)OVRPlugin.LayerFlags.ProtectedContent; } if (isExternalSurface) { newDesc.LayerFlags |= (int)OVRPlugin.LayerFlags.AndroidSurfaceSwapChain; } return(newDesc); }
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); }
private bool CreateLayer(int mipLevels, int sampleCount, OVRPlugin.EyeTextureFormat etFormat, int flags, OVRPlugin.Sizei size, OVRPlugin.OverlayShape shape) { if (!layerIdHandle.IsAllocated || layerIdPtr == IntPtr.Zero) { layerIdHandle = GCHandle.Alloc(layerId, GCHandleType.Pinned); layerIdPtr = layerIdHandle.AddrOfPinnedObject(); } if (layerIndex == -1) { for (int i = 0; i < maxInstances; ++i) { if (instances[i] == null || instances[i] == this) { layerIndex = i; instances[i] = this; break; } } } bool needsSetup = ( isOverridePending || layerDesc.MipLevels != mipLevels || layerDesc.SampleCount != sampleCount || layerDesc.Format != etFormat || layerDesc.Layout != layout || layerDesc.LayerFlags != flags || !layerDesc.TextureSize.Equals(size) || layerDesc.Shape != shape); if (!needsSetup) { return(false); } OVRPlugin.LayerDesc desc = OVRPlugin.CalculateLayerDesc(shape, layout, size, mipLevels, sampleCount, etFormat, flags); OVRPlugin.EnqueueSetupLayer(desc, compositionDepth, layerIdPtr); layerId = (int)layerIdHandle.Target; if (layerId > 0) { layerDesc = desc; if (isExternalSurface) { stageCount = 1; } else { stageCount = OVRPlugin.GetLayerTextureStageCount(layerId); } } isOverridePending = false; return(true); }
private bool CreateLayer(int mipLevels, int sampleCount, OVRPlugin.EyeTextureFormat etFormat, int flags, OVRPlugin.Sizei size, OVRPlugin.OverlayShape shape) { if (!this.layerIdHandle.IsAllocated || this.layerIdPtr == IntPtr.Zero) { this.layerIdHandle = GCHandle.Alloc(this.layerId, GCHandleType.Pinned); this.layerIdPtr = this.layerIdHandle.AddrOfPinnedObject(); } if (this.layerIndex == -1) { for (int i = 0; i < 15; i++) { if (OVROverlay.instances[i] == null || OVROverlay.instances[i] == this) { this.layerIndex = i; OVROverlay.instances[i] = this; break; } } } if (!this.isOverridePending && this.layerDesc.MipLevels == mipLevels && this.layerDesc.SampleCount == sampleCount && this.layerDesc.Format == etFormat && this.layerDesc.LayerFlags == flags && this.layerDesc.TextureSize.Equals(size) && this.layerDesc.Shape == shape) { return(false); } OVRPlugin.LayerDesc desc = OVRPlugin.CalculateLayerDesc(shape, this.layout, size, mipLevels, sampleCount, etFormat, flags); OVRPlugin.EnqueueSetupLayer(desc, this.layerIdPtr); this.layerId = (int)this.layerIdHandle.Target; if (this.layerId > 0) { this.layerDesc = desc; this.stageCount = OVRPlugin.GetLayerTextureStageCount(this.layerId); } this.isOverridePending = false; return(true); }
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; } } } }
private bool PopulateLayer(int mipLevels, bool isHdr, OVRPlugin.Sizei size, int sampleCount, int stage) { if (isExternalSurface) { return(true); } bool ret = false; RenderTextureFormat rtFormat = (isHdr) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; for (int eyeId = 0; eyeId < texturesPerStage; ++eyeId) { Texture et = layerTextures[eyeId].swapChain[stage]; if (et == null) { continue; } for (int mip = 0; mip < mipLevels; ++mip) { bool dataIsLinear = isHdr || (QualitySettings.activeColorSpace == ColorSpace.Linear); var rt = textures[eyeId] as RenderTexture; #if UNITY_ANDROID && !UNITY_EDITOR dataIsLinear = true; //HACK: Graphics.CopyTexture causes linear->srgb conversion on target write with D3D but not GLES. #endif // PC requries premultiplied Alpha bool requiresPremultipliedAlpha = !Application.isMobilePlatform; bool linearToSRGB = !isHdr && dataIsLinear; // if the texture needs to be premultiplied, premultiply it unless its already premultiplied bool premultiplyAlpha = requiresPremultipliedAlpha && !isAlphaPremultiplied; bool bypassBlit = !linearToSRGB && !premultiplyAlpha && rt != null && rt.format == rtFormat; RenderTexture tempRTDst = null; if (!bypassBlit) { int width = size.w >> mip; if (width < 1) { width = 1; } int height = size.h >> mip; if (height < 1) { height = 1; } RenderTextureDescriptor descriptor = new RenderTextureDescriptor(width, height, rtFormat, 0); descriptor.msaaSamples = sampleCount; descriptor.useMipMap = true; descriptor.autoGenerateMips = false; descriptor.sRGB = false; tempRTDst = RenderTexture.GetTemporary(descriptor); if (!tempRTDst.IsCreated()) { tempRTDst.Create(); } tempRTDst.DiscardContents(); Material blitMat = null; if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap) { blitMat = tex2DMaterial; } else { blitMat = cubeMaterial; } blitMat.SetInt("_linearToSrgb", linearToSRGB ? 1 : 0); blitMat.SetInt("_premultiply", premultiplyAlpha ? 1 : 0); } if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap) { if (bypassBlit) { Graphics.CopyTexture(textures[eyeId], 0, mip, et, 0, mip); } else { if (overrideTextureRectMatrix) { BlitSubImage(textures[eyeId], tempRTDst, tex2DMaterial, GetBlitRect(eyeId)); } else { Graphics.Blit(textures[eyeId], tempRTDst, tex2DMaterial); } //Resolve, decompress, swizzle, etc not handled by simple CopyTexture. Graphics.CopyTexture(tempRTDst, 0, 0, et, 0, mip); } } else // Cubemap { for (int face = 0; face < 6; ++face) { cubeMaterial.SetInt("_face", face); if (bypassBlit) { Graphics.CopyTexture(textures[eyeId], face, mip, et, face, mip); } else { //Resolve, decompress, swizzle, etc not handled by simple CopyTexture. Graphics.Blit(textures[eyeId], tempRTDst, cubeMaterial); Graphics.CopyTexture(tempRTDst, 0, 0, et, face, mip); } } } if (tempRTDst != null) { RenderTexture.ReleaseTemporary(tempRTDst); } ret = true; } } return(ret); }
private bool PopulateLayer(int mipLevels, bool isHdr, OVRPlugin.Sizei size, int sampleCount) { bool ret = false; RenderTextureFormat rtFormat = (isHdr) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; for (int eyeId = 0; eyeId < texturesPerStage; ++eyeId) { int dstElement = (layout == OVRPlugin.LayerLayout.Array) ? eyeId : 0; int stage = frameIndex % stageCount; Texture et = layerTextures[eyeId].swapChain[stage]; if (et == null) { continue; } for (int mip = 0; mip < mipLevels; ++mip) { #if UNITY_2017_1_1 || UNITY_2017_2_OR_NEWER int width = size.w >> mip; if (width < 1) { width = 1; } int height = size.h >> mip; if (height < 1) { height = 1; } RenderTextureDescriptor descriptor = new RenderTextureDescriptor(width, height, rtFormat, 0); descriptor.msaaSamples = sampleCount; descriptor.useMipMap = true; descriptor.autoGenerateMips = false; var tempRTDst = RenderTexture.GetTemporary(descriptor); #else var tempRTDst = RenderTexture.GetTemporary(size.w >> mip, size.h >> mip, 0, rtFormat, RenderTextureReadWrite.Default, sampleCount); #endif if (!tempRTDst.IsCreated()) { tempRTDst.Create(); } tempRTDst.DiscardContents(); if (currentOverlayShape != OverlayShape.Cubemap && currentOverlayShape != OverlayShape.OffcenterCubemap) { #if UNITY_ANDROID && !UNITY_EDITOR if (((textures[eyeId] as Cubemap) != null) && ((et as Cubemap) != null) && ((textures[eyeId] as Cubemap).format == (et as Cubemap).format)) { Graphics.CopyTexture(textures[eyeId], 0, mip, et, 0, mip); } else { Graphics.Blit(textures[eyeId], tempRTDst); //Resolve, decompress, swizzle, etc not handled by simple CopyTexture. Graphics.CopyTexture(tempRTDst, 0, 0, et, dstElement, mip); } #else // The PC compositor uses premultiplied alpha, so multiply it here. Graphics.Blit(textures[eyeId], tempRTDst, premultiplyMaterial); Graphics.CopyTexture(tempRTDst, 0, 0, et, dstElement, mip); #endif } #if UNITY_2017_1_OR_NEWER else // Cubemap { var tempRTSrc = RenderTexture.GetTemporary(size.w >> mip, size.h >> mip, 0, rtFormat, RenderTextureReadWrite.Default, sampleCount); if (!tempRTSrc.IsCreated()) { tempRTSrc.Create(); } tempRTSrc.DiscardContents(); for (int face = 0; face < 6; ++face) { #if UNITY_ANDROID && !UNITY_EDITOR if ((textures[eyeId] as Cubemap).format == (et as Cubemap).format) { Graphics.CopyTexture(textures[eyeId], face, mip, et, 0, mip); } else { //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, mip, tempRTSrc, 0, 0); Graphics.Blit(tempRTSrc, tempRTDst); Graphics.CopyTexture(tempRTDst, 0, 0, et, face, mip); } #else //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, mip, tempRTSrc, 0, 0); // The PC compositor uses premultiplied alpha, so multiply it here. Graphics.Blit(tempRTSrc, tempRTDst, premultiplyMaterial); Graphics.CopyTexture(tempRTDst, 0, 0, et, face, mip); #endif } RenderTexture.ReleaseTemporary(tempRTSrc); } #endif RenderTexture.ReleaseTemporary(tempRTDst); ret = true; } } return(ret); }