using System; using System.Collections; using System.Collections.Generic; using System.Text; using BITKit; using UnityEngine; namespace BITFALL.Props { public class Prop_ScopeShaderService : MonoBehaviour { private static readonly int ScopePosition = Shader.PropertyToID("_ScopePosition"); private static readonly int ScopeRadius = Shader.PropertyToID("_ScopeRadius"); private static readonly int ScopeDepth = Shader.PropertyToID("_ScopeDepth"); private static readonly int ScopeSizeOffset = Shader.PropertyToID("_ScopeSizeOffset"); [SerializeField] private Shader shader; [SerializeField] private new Camera camera; [SerializeField, ReadOnly(HideLabel = true)] private string buildReport; private readonly StringBuilder reportBuilder = new StringBuilder(); private void LateUpdate() { reportBuilder.Clear(); foreach (var i in Prop_ScopeMeshComponent.List) { if (i.IsInitialized is true) continue; // foreach (var ii in i.GetComponentsInChildren()) // { // ii.material.shader = i.overrideShader ? i.overrideShader : shader; // } if (i.TryGetComponent(out var nextRenderer)) { nextRenderer.material.shader = i.overrideShader ? i.overrideShader : shader; } i.IsInitialized = true; } foreach (var x in Prop_ScopeDataComponent.List) { reportBuilder.AppendLine($"{x.name}\tRadius:{x.Radius}\tScreenPoint:{x.Position}"); Shader.SetGlobalVector(ScopePosition,x.Position); Shader.SetGlobalFloat(ScopeRadius,x.Radius); var position = x.Position + x.Rotation * new Vector3(x.Radius,x.Radius); var screenPoint = CustomWorldToScreenPoint(position,27); reportBuilder.AppendLine($"ScreenPoint:{screenPoint}"); screenPoint.x = Mathf.Abs(screenPoint.x - camera.pixelWidth/2f) / camera.pixelWidth * 2; screenPoint.y =Mathf.Abs(screenPoint.y - camera.pixelHeight/2f) /camera.pixelHeight * 2; Shader.SetGlobalVector(ScopeSizeOffset,screenPoint); reportBuilder.AppendLine($"ScreenOffset:{screenPoint}"); } buildReport = reportBuilder.ToString(); } public static Vector3 CustomWorldToScreenPoint(Vector3 worldPosition,float customFOV) { Camera customCamera = Camera.main!; // 获取相机属性 float customAspect = customCamera.aspect; float customNearClipPlane = customCamera.nearClipPlane; // 将FOV转换为弧度 float customFieldOfViewRad = Mathf.Deg2Rad * customFOV; // 计算投影矩阵的参数 float tanHalfFOV = Mathf.Tan(customFieldOfViewRad * 0.5f); float screenHeight = 2.0f * customNearClipPlane * tanHalfFOV; float screenWidth = screenHeight * customAspect; // 计算世界坐标相对于相机的位置 Vector3 cameraRelativePosition = worldPosition - customCamera.transform.position; // 计算归一化设备坐标(NDC) Vector3 ndc = new Vector3( cameraRelativePosition.x / (screenWidth * 0.5f), cameraRelativePosition.y / (screenHeight * 0.5f), cameraRelativePosition.z / customNearClipPlane ); // 将归一化设备坐标映射到屏幕坐标 Vector3 screenPoint = new Vector3( (ndc.x + 1.0f) * 0.5f * customCamera.pixelWidth, (ndc.y + 1.0f) * 0.5f * customCamera.pixelHeight, ndc.z ); return screenPoint; } } }