Fix mobile render texture black screens

This commit is contained in:
2026-06-29 16:34:26 +08:00
parent 5efb2ff157
commit a36dc7c003
2 changed files with 210 additions and 1 deletions
@@ -1,10 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using Yarn.Unity;
using AibisDream.Framework;
using Cinemachine;
using UnityEngine.Rendering;
using UnityEngine.UI;
using AibisDream.Kit;
using UnityEngine.ResourceManagement.AsyncOperations;
@@ -64,12 +66,14 @@ namespace AibisDream.FixSystem
[SerializeField] private Material fadeMaterial;
private Material runtimeMemoryMaterial;
private readonly List<RenderTexture> runtimeRenderTextures = new();
public void OpenMemoryView()
{
memoryGroup.SetActive(true);
memoryView.gameObject.SetActive(true);
EnsureMemoryRenderTargets();
StartCoroutine(PrimeMemoryRenderTargets());
}
public IEnumerator DropMemoryProjector()
@@ -176,6 +180,114 @@ namespace AibisDream.FixSystem
{
if (runtimeMemoryMaterial != null)
Destroy(runtimeMemoryMaterial);
foreach (var renderTexture in runtimeRenderTextures)
{
if (renderTexture == null)
continue;
renderTexture.Release();
Destroy(renderTexture);
}
runtimeRenderTextures.Clear();
}
private void EnsureMemoryRenderTargets()
{
if (memoryGroup == null || memoryView == null)
return;
var cameras = memoryGroup.GetComponentsInChildren<Camera>(true);
foreach (var renderCamera in cameras)
{
if (renderCamera == null || renderCamera.targetTexture == null)
continue;
renderCamera.allowHDR = false;
renderCamera.allowMSAA = false;
var originalTexture = renderCamera.targetTexture;
var targetTexture = originalTexture;
if (ShouldReplaceRenderTexture(originalTexture))
{
targetTexture = CreateCompatibleRenderTexture(originalTexture);
renderCamera.targetTexture = targetTexture;
RebindMemoryRawImages(originalTexture, targetTexture);
}
if (!targetTexture.IsCreated())
{
targetTexture.Create();
}
}
}
private static bool ShouldReplaceRenderTexture(RenderTexture renderTexture)
{
if (renderTexture == null)
return true;
if (!SystemInfo.SupportsRenderTextureFormat(renderTexture.format))
return true;
var maxSize = Mathf.Min(SystemInfo.maxTextureSize, 2048);
return renderTexture.width > maxSize || renderTexture.height > maxSize;
}
private RenderTexture CreateCompatibleRenderTexture(RenderTexture source)
{
var maxSize = Mathf.Min(SystemInfo.maxTextureSize, 2048);
var sourceWidth = source != null ? source.width : Screen.width;
var sourceHeight = source != null ? source.height : Screen.height;
var scale = Mathf.Min(1f, maxSize / (float)Mathf.Max(sourceWidth, sourceHeight));
var width = Mathf.Max(1, Mathf.RoundToInt(sourceWidth * scale));
var height = Mathf.Max(1, Mathf.RoundToInt(sourceHeight * scale));
var renderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32)
{
name = source != null ? $"{source.name}_RuntimeCompatible" : "Memory_RuntimeCompatible",
antiAliasing = 1,
useMipMap = false,
autoGenerateMips = false
};
renderTexture.Create();
runtimeRenderTextures.Add(renderTexture);
return renderTexture;
}
private void RebindMemoryRawImages(Texture oldTexture, Texture newTexture)
{
var rawImages = memoryView.GetComponentsInChildren<RawImage>(true);
foreach (var rawImage in rawImages)
{
if (rawImage != null && rawImage.texture == oldTexture)
{
rawImage.texture = newTexture;
}
}
}
private IEnumerator PrimeMemoryRenderTargets()
{
yield return null;
ForceRenderMemoryTargets();
yield return new WaitForEndOfFrame();
ForceRenderMemoryTargets();
}
private void ForceRenderMemoryTargets()
{
if (memoryGroup == null || !memoryGroup.activeInHierarchy)
return;
var cameras = memoryGroup.GetComponentsInChildren<Camera>(true);
foreach (var renderCamera in cameras)
{
if (renderCamera != null && renderCamera.enabled && renderCamera.targetTexture != null)
{
renderCamera.Render();
}
}
}
private void CheckAllFound()
@@ -32,6 +32,7 @@ namespace AibisDream
private EyeData _eyeData = new();
private Tween hsvShiftTween;
private MouseFollowAndZoom mouseFollowAndZoom;
private RenderTexture runtimeEyeRenderTexture;
/// <summary>
/// 眼睛 RawImage 的故障/色相/饱和度等效果依赖 AllIn1SpriteShader(或兼容)材质上的属性。
@@ -82,6 +83,88 @@ namespace AibisDream
return true;
}
private bool EnsureEyeViewRenderTarget()
{
if (eyeImage == null)
{
Debug.LogError("[EyeSystem] eyeImage 未赋值,无法显示视觉模块画面。", this);
return false;
}
if (cameraManager == null)
{
Debug.LogError("[EyeSystem] cameraManager 未赋值,无法渲染视觉模块画面。", this);
return false;
}
var viewCamera = cameraManager.GetComponent<Camera>();
if (viewCamera == null)
{
Debug.LogError("[EyeSystem] cameraManager 上未找到 Camera 组件,无法渲染视觉模块画面。", cameraManager);
return false;
}
viewCamera.allowHDR = false;
viewCamera.allowMSAA = false;
var renderTexture = viewCamera.targetTexture;
if (renderTexture == null)
{
renderTexture = CreateRuntimeEyeRenderTexture();
viewCamera.targetTexture = renderTexture;
}
if (!renderTexture.IsCreated())
{
renderTexture.Create();
}
if (eyeImage.texture != renderTexture)
{
eyeImage.texture = renderTexture;
}
return true;
}
private RenderTexture CreateRuntimeEyeRenderTexture()
{
var width = Mathf.Clamp(Screen.width, 1, 2048);
var height = Mathf.Clamp(Screen.height, 1, 2048);
runtimeEyeRenderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32)
{
name = "Runtime Eye View RenderTexture",
antiAliasing = 1,
useMipMap = false,
autoGenerateMips = false
};
runtimeEyeRenderTexture.Create();
return runtimeEyeRenderTexture;
}
private IEnumerator PrimeEyeViewRender()
{
yield return null;
ForceRenderEyeView();
yield return new WaitForEndOfFrame();
ForceRenderEyeView();
}
private void ForceRenderEyeView()
{
if (cameraManager == null || !cameraManager.gameObject.activeInHierarchy)
{
return;
}
var viewCamera = cameraManager.GetComponent<Camera>();
if (viewCamera != null && viewCamera.enabled && viewCamera.targetTexture != null)
{
viewCamera.Render();
}
}
public void Init()
{
FixSystemCenter.SystemDic.Register(this);
@@ -119,11 +202,15 @@ namespace AibisDream
{
cameraManager.gameObject.SetActive(true);
}
EnsureEyeViewRenderTarget();
mouseFollowAndZoom.SetIsActive(true);
mouseFollowAndZoom.SetIsLock(false);
// 激活 ViewCamera 后再打开 EyeView
OpenEyeView();
ForceRenderEyeView();
StartCoroutine(PrimeEyeViewRender());
// 进入视图时的逻辑
Debug.Log("EyeView entered.");
}
@@ -168,6 +255,16 @@ namespace AibisDream
Debug.Log("EyeView exited.");
}
private void OnDestroy()
{
if (runtimeEyeRenderTexture != null)
{
runtimeEyeRenderTexture.Release();
Destroy(runtimeEyeRenderTexture);
runtimeEyeRenderTexture = null;
}
}
private void Start()
{
SetEyeColorState(_eyeData.currentState);