Skip to content

Instantly share code, notes, and snippets.

@sugi-cho
Last active April 8, 2022 00:28
Show Gist options
  • Save sugi-cho/2094612a6ba566f09e9e to your computer and use it in GitHub Desktop.
Save sugi-cho/2094612a6ba566f09e9e to your computer and use it in GitHub Desktop.
クリップ座標系から、ワールド座標へ変換するやつ。理解を深めた http://www.songho.ca/opengl/gl_projectionmatrix.html
Shader "Unlit/ViewPortToPos"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_VP ("viewport position", Vector) = (0.5,0.5,1,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos: TEXCOORD1;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _VP; // viewPosition
float3 clipToLocal(float4 clipPos){
float4 viewPos = mul(unity_CameraInvProjection, clipPos);
viewPos.w = 1;
return mul(viewPos, UNITY_MATRIX_IT_MV).xyz;
}
v2f vert (appdata v)
{
float n = _ProjectionParams.y;
float f = _ProjectionParams.z;
float w = _VP.z;
float z = w * (2*(w-n)/(f-n)-1);
float2 xy = w * (2*_VP.xy-1);
float4 clipPos = float4(xy,z,w);
float3 localPos = clipToLocal(clipPos);
v.vertex.xyz += localPos;
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.pos = o.vertex;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = half4(i.pos.xyz/i.pos.w*0.5+0.5,0);
return col;
}
ENDCG
}
}
}
using UnityEngine;
using System.Collections;
public class ViewToWorldTransformation : MonoBehaviour {
public Vector3 viewPos;
public Transform target;
[SerializeField]
Vector4 clipPos;
[SerializeField]
Vector3 ndcPos;
[SerializeField]
Vector3 worldPos;
void Start(){
if(target == null)
target = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
}
// Update is called once per frame
void Update () {
var cam = Camera.main;
var n = cam.nearClipPlane;
var f = cam.farClipPlane;
var d = f - n;
var w = viewPos.z;
var z = w * (2 * (w - n) / d - 1);
var y = w * (2 * viewPos.y - 1);
var x = w * (2 * viewPos.x - 1);
clipPos = new Vector4(x, y, z, w);
ndcPos = new Vector3(clipPos.x, clipPos.y, clipPos.z) / clipPos.w;
var camToWorld = cam.cameraToWorldMatrix;
var projection = GL.GetGPUProjectionMatrix (cam.projectionMatrix, false);
var inverseP = projection.inverse;
var camPos = inverseP * clipPos;
camPos.w = 1f;
worldPos = camToWorld * camPos;
target.transform.position = worldPos;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment