105 lines
3.2 KiB
C#
105 lines
3.2 KiB
C#
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<Renderer>())
|
|
// {
|
|
// ii.material.shader = i.overrideShader ? i.overrideShader : shader;
|
|
// }
|
|
if (i.TryGetComponent<Renderer>(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;
|
|
}
|
|
}
|
|
}
|