using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Rendering.Universal.Internal; using UnityEngine.UI; public class BlendShaderController : MonoBehaviour { private static string savePath = Application.streamingAssetsPath + '\\'; private const string filename = "dsitMap"; private const string ext = ".txt"; public Shader DepthShader; public ComputeShader BlendShader; public Camera camera1; public Camera camera2; public int QuadResolution = 256; public float Multiplier; public RawImage Reciever; [Range(0, 1000)] public float OffsetMultiplier = 1000; public RenderTexture test; private RenderTexture depth1; private RenderTexture depth2; private RenderTexture cameraTexture1; private RenderTexture cameraTexture2; private RenderTexture Result; private int currentRes; private bool flag = false; private ComputeBuffer computeBuffer; private float[] resultArray; Thread savingThread; Task task1; Task task2; // Start is called before the first frame update void Start() { InitializeTextures(); InitializeComputeBuffer(); } void InitializeComputeBuffer() { computeBuffer = new ComputeBuffer(currentRes * currentRes, 1 * sizeof(float));//2 dimensional array of 1 value type of double } void InitializeTextures() { currentRes = QuadResolution; RenderTexture[] defaultTextures = CreateTextures(2, currentRes, currentRes); cameraTexture1 = defaultTextures[0]; cameraTexture2 = defaultTextures[1]; RenderTexture[] depthTextures = CreateTextures(2, currentRes, currentRes, true); depth1 = depthTextures[0]; depth2 = depthTextures[1]; Result = CreateTextures(1, currentRes, currentRes)[0]; Reciever.texture = Result; camera1.targetTexture = cameraTexture1; camera2.targetTexture = cameraTexture2; } public static RenderTexture[] CreateTextures(int count, int resX, int resY, bool depth = false) { RenderTexture[] result = new RenderTexture[count]; for (int i = 0; i < count; i++) { result[i] = new RenderTexture(resX, resY, 32, depth ? RenderTextureFormat.Depth : RenderTextureFormat.ARGBFloat); result[i].enableRandomWrite = !depth; result[i].Create(); } return result; } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.F)) { SetFlag(); } if (flag) { GenerateDepth(); } UpdateShader(cameraTexture1, cameraTexture2); if(Input.GetKeyDown(KeyCode.S)) { SaveTexture(); } if (Input.GetKeyDown(KeyCode.J)) { Debug.Log(GetDistanceByDepth()); } if (Input.GetKeyDown(KeyCode.K)) { Debug.Log(GetDistanceByRayCast()); } if (Input.GetKeyDown(KeyCode.T)) { camera1.targetTexture = test; camera1.RenderWithShader(DepthShader, "fragment"); camera1.targetTexture = cameraTexture1; } } void UpdateShader(RenderTexture tex1, RenderTexture tex2) { BlendShader.SetTexture(0, "Camera1", tex1); BlendShader.SetTexture(0, "Camera2", tex2); BlendShader.SetTexture(0, "Result", Result); BlendShader.SetFloat(Shader.PropertyToID("Offset"), (int)(camera2.transform.localPosition.x * OffsetMultiplier)); BlendShader.SetFloat(Shader.PropertyToID("ResX"), Result.width); BlendShader.SetBuffer(0, "MonoChannelResult", computeBuffer); //BlendShader.SetTexture(0, "Test", test); BlendShader.Dispatch(0, Result.width / 8, Result.height / 8, 1); } void GenerateDepth() { //camera1.RenderWithShader(DepthShader, "RenderType"); //camera2.RenderWithShader(DepthShader, "RenderType"); Graphics.Blit(depth1, cameraTexture1); //Depth generated due to format of render texture Graphics.Blit(depth2, cameraTexture2); } void SwapRenderTargets() { if (flag) { camera1.targetTexture = depth1; camera2.targetTexture = depth2; } else { camera1.targetTexture = cameraTexture1; camera2.targetTexture = cameraTexture2; } } public void SetFlag() { flag = !flag; SwapRenderTargets(); } private async void SaveTexture() { Debug.Log("Start Saving"); resultArray = new float[currentRes * currentRes]; computeBuffer.GetData(resultArray); Debug.Log("Data copied"); task1 = Task.Run(() => SerializeArray()); await task1; string result = task1.Result; task2 = SavingProcessAsync(result); await task2; } private async Task SavingProcessAsync(string data) { int filesCount = Directory.EnumerateFiles(savePath, filename + '*' + ext).Count(); await File.WriteAllTextAsync(savePath + filename + filesCount.ToString() + ext, data); Debug.Log("File saved"); } private string SerializeArray() { string result = string.Empty; for (int i = 0; i < resultArray.Length; i += currentRes) { result += string.Join(", ", resultArray[i..(i + currentRes)]) + '\n'; } return result; } private float GetDistanceByDepth() { resultArray = new float[currentRes * currentRes]; computeBuffer.GetData(resultArray); int idx = (int)(currentRes * (0.5f + currentRes * 0.5f)); Matrix4x4 porjMat = camera1.projectionMatrix; float zDepth = resultArray[idx]; float far = camera1.farClipPlane; float near = camera1.nearClipPlane; return zDepth * (far - near) + near; } private float GetDistanceByRayCast() { Vector3 position = camera1.transform.position + camera1.transform.right * camera2.transform.localPosition.x * 0.5f; if (Physics.Raycast(position, camera1.transform.forward, out var hit, 100)) { return hit.distance; } return -1; } private void OnDisable() { computeBuffer.Release(); computeBuffer = null; } }