最近とても忙しく、プロジェクトの要件が大幅に変更され、夜には成人向け英語のテストを復習しなければなりません。
「VRのワンクリック生成」の要件が追加されました。既存のフレームワーク上で、通常のキーボードとマウスとVRハンドルの操作をプリコンパイルして同期し、PCとVRのさまざまなインターフェイスの使用を同期します。ビジネス開発者は、処理機能を実行するための新しい基本クラスとAPIを派生および呼び出し、エディタ機能を使用してワンクリックでVRとPCのデュアルエンドシーンを生成し、完全に実行できます。
リーダーとしては、新たな要求に応じて変化していくしかない、つまり、無駄な仕事に費やした時間は取り戻せません。
今、VRの需要として映像の歪みが問題になっていますが、このVRヘッドセットも同様で、同じヘッドセットを違う人が使っても、違和感、特に空間感覚の違いが生じてしまうので、この問題を解決する方法が必要です。画像の後処理を使用して歪みを解決します。
伝統的な画像の歪みの方法を見てください: 樽歪み
Baidu 樽歪み
wiki 歪み
テクスチャ uv グリッドは、ワインを保存するための木製の樽のように見えます。これに似ています。
画像から、uv が中心 (0.5,0.5) から四隅に向かって「膨張」していることがわかります。uv をこれに変換できる計算方法があるかどうかを推測できます。私はインターネット上でアルゴリズムを見つけ、次のように独自の変更をいくつか組み合わせました。
まず、インターネット上のアルゴリズムです。
Shader "VRDistort/VRDistortImageEffectShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {
}
_Distort("Distort",Range(-4,4)) = 0
_Adjust("Adjust",Range(0,4)) = 1
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
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 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float _Distort; //畸变系数
float _Adjust; //矫正系数
//桶形畸变
float2 barreldistort(float2 uv)
{
//得到pixeluv相对center坐标d
float2 d = uv.xy-float2(0.5,0.5);
//d的长度方(0<d<0.5)
float2 d2 = d.x*d.x+d.y*d.y;
//畸变权重(-1<f<3)
float f = 1.0+d2*_Distort;
//畸变uv
//(f*_Adjust)用于修正权重
//再*d后“还原”相对坐标d
//再+center还原pixeluv
float2 buv = f*_Adjust*d+float2(0.5,0.5);
return buv;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, barreldistort(i.uv));
return col;
}
ENDCG
}
}
}
このアルゴリズムは非常に巧妙に設計されており、pixeluv と centeruv の相対座標 d を使用して変換し、pixeluv に復元し、次にディストーション パラメータと補正パラメータを調整すると、次のようにバレル ディストーションの効果を得ることができます: ここでは、OnRenderImage を使用して画像を後処理しており、ディストーション効果は良好であることがわかります
。
同時に、問題も見つかります。UV 間隔 [0,1] の変更により、歪みが生じた後、テクスチャの「四隅」に再度一致するように補正パラメータを手動で調整する必要があります。
したがって、アルゴリズムを変更して _Adjust パラメータを削除する必要があります。アルゴリズムは次のことを保証する必要があります:
1. _Adjust パラメータを自動的に計算する
2. 4 つの UV エンドポイントが変換された後も UV が同じであること 上記の計算は、
P0(0,0) と P1(1,1) を元の BarrelDistort アルゴリズムに取り込むことであり、_Adjust = 1/(1+0.5*_Distort) を取得できます。
コードを変更します。
float2 barrel(float2 uv)
{
float j = 1/(1+0.5*_Distort);
float2 d = uv.xy-float2(0.5,0.5);
float d2 = d.x*d.x+d.y*d.y;
float f = 1.0+d2*_Distort;
float2 buv = f*j*d+float2(0.5,0.5);
return buv;
}
結果は次のとおりです:
_Distort>0 の区間ではアルゴリズムに問題がないことがわかりますが、_Distort<0 の区間では問題があります。問題は次のとおりです: 1. 画面が「凹」になった後、画面の 4 辺の「凹」の UV を「完了」できません
。
2. _Distort=-2、分母=0の場合、計算は間違っています。
次に、_Distort<0 の場合の正しい UV マッピング関係を次のように考えなければなりません。4
つの辺の中心点のピクセル UV は、変換後も元のピクセル UV のままであり、計算は次のとおりです。計算方法は逆
演繹、単純な 1 次元線形方程式です。
コードを変更します。
float2 barrel(float2 uv)
{
float j = _Distort >= 0 ? (1/(1+0.5*_Distort)) : (1/(1+0.25*_Distort));
float2 d = uv.xy-float2(0.5,0.5);
float d2 = d.x*d.x+d.y*d.y;
float f = 1.0+d2*_Distort;
float2 buv = f*j*d+float2(0.5,0.5);
return buv;
}
効果は次のとおりです。
このようにして効果が達成され、ユーザーはユーザー設定インターフェイスの「バンプ」パラメーターについて画面を微調整するだけで済みます。
もちろん、シェーダーの計算時間を節約するために、次のように _Distort と _Adjust を計算して C# で渡すことをお勧めします。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class VRDistortSetting : MonoBehaviour
{
public Slider slider;
public Material mat;
void Start()
{
slider.onValueChanged.AddListener(SliderValueChange);
}
private void SliderValueChange(float val)
{
float distort = val;
float adjust = distort >= 0 ? (1 / (1 + 0.5f * distort)) : (1 / (1 + 0.25f * distort));
mat.SetFloat("_Distort", distort);
mat.SetFloat("_Adjust", adjust );
}
}
さて、今日はここで、しばらくはメーデーだけが無料になると思います。