真の詐称者の技術
基本的な導入
詐欺師、意図「プリテンダーズ」は、実際のメッシュモデルをシミュレートするための最適化技術を使用して、非常に単純なメッシュである、我々は効率的に多数のポリゴンを描画する必要がなく、シーン内の類似した多数のモデルを描くことができます。詐称者の技術は、同時に保存モデルの頂点の完全な角度の表示内容を達成するために、ビルボードとメッシュとの間に介在されているモデルです。偽物矩形メッシュ上に二次元テクスチャマッピングは、アーティファクト精度シミュレーションモデルは、この方法は、リアルタイムで実施することができる、データは、予め計算され、良好なメモリに格納されてもよいです。詐称者モデルは、実際には、いくつかの完全に正確な角度(サンプル角)で、遷移の精度でカメラアングルの変化の動きは、完全に正確な角度にスイッチするまで減少させなければなりません。詐欺師モデルは、サンプリング十分に基本的な現実のもので、オリジナルの自発光、反射、屈折およびその他の特性をサポートしています。
ビルボード、マルチビルボード
伝統的なビルボードビルボード技術原理は、テクスチャマップを表示するメッシュとメッシュが常にこのアプローチの効果を達成するために、迷彩モデルをカメラに直面しているように、貧しい製品の操作により方向ベクトルを与えるために、カメラの位置を監視する四角形を使用するはるかに簡単です距離及びY軸対称モデルの中心である場合には、このようないくつかの単木や草として、良好に機能します。
そのようなアナログの特定の草のような看板方法、後の星のように導出看板表示単一のサーフェスモデルは、積層看板スターの複数が一緒に差し込まれ、より複雑なモデルの詳細を示しています。数看板が重畳されたと同時に、それはまた、メッシュ、頂点の数を増加するメモリ消費を増加させる、より複雑になります。
ビルボードは、大幅に性能要件を減らすことができ、厳しい少ない距離の詳細をモデル化するためにのみ適用されます。ビルボードはまた、多くの場合(たとえば、草原、森林など)の大規模なモデルユニバーサルアプリケーションのレンダリング方法、性能要件を削減する必要がある、アイデアをrenderringベースのイメージがあります。また、この単純では、このような影のようにリアルな照明効果をサポートすることは困難看板。
詐欺師のテクスチャ空間
テクスチャマッピングは、基礎詐称者宇宙技術です。メイン3へのマッピング:球面(球状のスペース)、八面体(八面体スペース)、ヘミ八面体(八面体の半分のスペース)。
変換は、空間マッピング二次元データと3次元データ、すなわち、圧縮データ伸張処理を達成します。詐欺師は、それが詐称者が最終的に二次元のテクスチャデータを異なる表示角度に対応するモデルのマップを実装する必要が伸長描画するときに、圧縮により2次元テクスチャマップに保存される、実際に収集された3次元データをサンプリングしました。
球状空間が同じで同じ緯度上の頂点の数に対応する、二次元のテクスチャマップであることを示し、以下に球状では、近い頂点極に対してより強いにつながる、垂直2次元テクスチャ頂点分布の頂点に対応する二つの辺の極はありません均一な、ダウンあまりに密な繰返し精度の廃棄物の多くをもたらすテクスチャデータの両方の端部に生じました。
そのため、精度を節約するために、我々は、マッピング方法、他の2八面体とヘミ八面体を選択します。
以下のアニメーションGIFは2つのスペース直感的なプロセスのマッピングを示しています。両方の頂点マッピング空間上で可視に均一生じる球面空間マッピング精度の浪費を回避する、分配されます。必要としないディスプレイモデルの一番下の場合は、さらに最適化するための推奨選択肢ヘミ八面体空間マップに:分割するこれら2例の選択に関しては、他に。そして、あなたはオールラウンドディスプレイモデルが必要な場合にのみ、八面体を選択することができます。
八面体たとえば、次のコードは、空間テクスチャマッピング変換関数です。
float2 VectortoOctahedron( float3 N )
{
N /= dot( 1.0, abs( N ) ); // 等同于:N/= abs(N.x)+abs(N.y)+abs(N.z)
if( N.z <= 0 )
{
N.xy = ( 1 - abs( N.yx ) ) * ( N.xy >= 0 ? 1.0 : -1.0 );
}
return N.xy;
}
float3 OctahedronToVector( float2 Oct )
{
float3 N = float3( Oct, 1.0 - dot( 1.0, abs( Oct ) ) );
if(N.z< 0 )
{
N.xy = ( 1 - abs( N.yx) ) * (N.xy >= 0 ? 1.0 : -1.0 );
}
return normalize( N);
}
使用例:VectortoOctahedron(objectCameraDirection.xzy)*0.5 + 0.5
、前記モデルは、モデルに対するシステムobjectCameraDirectionのcamear方向ベクトル座標、すなわち、計算結果がテクスチャ座標に対応する二次元のテクスチャです。
詐欺師ベーキング空間サンプリング
偽物メインサンプリングサンプリング精度提供は、テクスチャ空間マッピングアルゴリズム均一マッピングマスクによれば、異なる角度からモデルのスナップショット、(オブジェクトの色や透明度)出力拡散テクスチャ、法線マップ(影を計算するための点灯後等)を取りますチャネルデータ等(一般的なセットの場合)(背景クリップのクリップされました)。
Amplify Impostor插件烘焙Impostor的方法很简单,在模型上加上AmplifyImpostor.cs脚本,创建Impostor对象并设置到Impostor Assets上,然后设置纹理分辨率(Texture Size)、理采样帧数(Axis Frames),编辑Imspostor的mesh形状(Billboard mesh),以及选择烘焙设置(Bake Preset)等。最后点击Bake Impostor就可以实现一键烘焙。
例如选择基本的Custom Preset输出的结果为三张贴图:AlbedoAlpha、NormalDepth、Mask。
插件提供的另一种用于标准延迟渲染通道的StandardDefferd设置输出则为四张贴图:AlbedoAlpha、NormalDepth、SpecularSmoothness、EmissionOcclusion。
视差映射POM
纹理空间是通过多角度采样得到的不同角度的纹理贴图,然后根据相机的位置来更换不同的贴图,但是在贴图直接更换的瞬间会有不连续的突变,为了实现平滑的过渡达到True Impostor的效果,需要加入视差映射POM(Parallax mapping)技术。
视差映射方法的基本原理是,根据当前相机位置确定当前对应的采样贴图片段,然后将当前贴图临近的贴图进行加权融合采样,实现平滑过渡,达到接近真实模型的效果。以Octahedron空间为例,每个贴图片段邻近的有三个片段,对三个邻近片段进行加权融合得到最终的采样颜色。
对整个纹理空间进行POM是一个比较耗费的过程,一般至少需要9x9的采样空间才能实现平滑过渡。
Billborad Impostor简化版实现
マルチアングル空間変換格差プラスなめらかなテクスチャマッピングPOM詐欺師によって技術をサンプリング詐欺師テクスチャは、モデルの異なるビューを示しています。しかし、POMは、あなたが(実際のモデルに近い直接メッシュモデルを置き換える)に近いモデルの詳細を表示するために詐欺師を使用しない場合はカメラのアングルを変更するとき、あなたは、直接交換をPOMプロセスを削除することができ、ゲームで、よりコストのプロセスであり、テクスチャマッピングをすることができます。
デモウィジェットデータとしてAmplifyImpostor 3つのマップ(ベークプリセット選択カスタム)詐欺師で焼成使用、デモBillboardImpostor.shaderは詐欺師簡易版、拡散反射の効果の単純な加算を達成しました。
完全なコードは次のとおりです。
// 用来展示BillboardImpostor模型
Shader "ImpostorDemo/BillboardImpostor"
{
Properties
{
[NoScaleOffset]_Albedo("Impostor Albedo & Alpha", 2D) = "white" {}
[NoScaleOffset]_Normals("Impostor Normal & Depth", 2D) = "white" {}
[NoScaleOffset]_Mask("Mask", 2D) = "white" {}
[HideInInspector]_AI_Frames("Impostor Frames", Float) = 0
[HideInInspector]_AI_ImpostorSize("Impostor Size", Float) = 0
_AI_Clip("Impostor Clip", Range( 0 , 1)) = 0.5
_DiffuseColor ("DiffuseColor", Color) = (1,1,1,1)
_Diffuse ("Diffuse", Range(0,1)) = 1.0
}
SubShader
{
CGINCLUDE
#pragma target 3.0
#define UNITY_SAMPLE_FULL_SH_PER_PIXEL 1
ENDCG
Tags { "RenderType"="Opaque" "Queue"="Geometry" "DisableBatching"="True" "ImpostorType"="Octahedron" }
Cull Back
Pass
{
ZWrite On
Name "ForwardBase"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform sampler2D _Albedo; // 颜色
uniform sampler2D _Normals; // 法线
uniform sampler2D _Mask;// mask
uniform float _AI_Frames; // 切片规模
uniform float _AI_ImpostorSize; // impostor resolution
uniform float _AI_Clip; // 透明背景裁剪程度
// 漫反射强度
uniform float4 _DiffuseColor;
uniform float _Diffuse;
// Octahedron空间纹理映射变换
float2 VectortoOctahedron( float3 N )
{
N /= dot( 1.0, abs( N ) ); // 等同于:N/= abs(N.x)+abs(N.y)+abs(N.z)
if( N.z <= 0 )
{
N.xy = ( 1 - abs( N.yx ) ) * ( N.xy >= 0 ? 1.0 : -1.0 );
}
return N.xy;
}
float3 OctahedronToVector( float2 Oct )
{
float3 N = float3( Oct, 1.0 - dot( 1.0, abs( Oct ) ) );
if(N.z< 0 )
{
N.xy = ( 1 - abs( N.yx) ) * (N.xy >= 0 ? 1.0 : -1.0 );
}
return normalize( N);
}
inline void OctaImpostorVertex( inout appdata_full v, inout float4 uvsFrame1)
{
float framesXY = _AI_Frames;
float prevFrame = framesXY - 1;
float2 fractions = 1.0 / float2( framesXY, prevFrame );
float fractionsFrame = fractions.x;
float fractionsPrevFrame = fractions.y;
float UVscale = _AI_ImpostorSize;
float3 worldOrigin = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
float3 worldCameraPos = _WorldSpaceCameraPos;
// 模型空间:origin到相机的方向
float3 objectCameraDirection = normalize( mul( worldCameraPos - worldOrigin, (float3x3)unity_WorldToObject ) );
// 模型空间:相机的位置
float3 objectCameraPosition = mul( unity_WorldToObject, float4( worldCameraPos, 1 ) ).xyz;
float3 upVector = float3( 0,1,0 );
//float3 objectCameraDirection = UNITY_MATRIX_V[2].xyz;
// 模型水平竖直向量
float3 objectHorizontalVector = normalize( cross( objectCameraDirection, upVector ) );
float3 objectVerticalVector = cross( objectHorizontalVector, objectCameraDirection );
float2 uvExpansion = ( v.texcoord.xy - 0.5f ) * UVscale;
float3 billboard = objectHorizontalVector * uvExpansion.x + objectVerticalVector * uvExpansion.y;
float2 cameraPos = VectortoOctahedron(objectCameraDirection.xzy)*0.5 + 0.5;
float colFrame = round(abs(cameraPos.x) * (framesXY-1));
float rowFrame = round(abs(cameraPos.y) * (framesXY-1));
// 纹理坐标
uvsFrame1 = 0;
uvsFrame1.xy = (v.texcoord.xy + float2(colFrame, rowFrame)) * fractionsFrame;
// 顶点
v.vertex.xyz = billboard;
v.normal.xyz = objectCameraDirection;
}
struct v2f_surf {
UNITY_POSITION(pos);
float4 UVsFrame117 : TEXCOORD5;
float4 viewPos17 : TEXCOORD6;
};
// 顶点
v2f_surf vert (appdata_full v ) {
UNITY_SETUP_INSTANCE_ID(v);
v2f_surf o;
UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
UNITY_TRANSFER_INSTANCE_ID(v,o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
OctaImpostorVertex( v, o.UVsFrame117 ); ///
o.pos = UnityObjectToClipPos(v.vertex); // 顶点投影坐标
// 漫反射
float3 worldlight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldnormal = normalize(mul((float3x3)unity_ObjectToWorld,v.normal));
float3 diffuse = _LightColor0.rgb * _DiffuseColor * _Diffuse * saturate(dot(worldnormal,worldlight));
o.viewPos17 = float4(diffuse,0);
return o;
}
// 片段着色
fixed4 frag (v2f_surf IN) : SV_Target {
float4 blendedAlbedo = tex2D( _Albedo, float3( IN.UVsFrame117.xy, 0) );
float alpha = blendedAlbedo.a - _AI_Clip;
clip(alpha);
return (blendedAlbedo + IN.viewPos17);
}
ENDCG
}
}
}
シンプルな森のシーンを達成するためにBillborad詐称者技術のデモシーンTreeForest.scene使用は、はるかに詐称者モデルを示すから、実際のショーケースのモデルに近い、詐称者樹木、岩や草を作りました。
概要
詐称者がBILLBORAD詐称者が実装の簡略化バージョンと一緒に、モデルの頂点の詳細と矛盾の数を減少させるためのトレードオフを増加させ、看板及び技術的製品との間の直接メッシュモデルであり、それらの間の関係は、として以下の(3Dモデルの詳細を以下)複数の:
Billborad - マルチBillborad - ビルボード詐欺師 - 真の詐欺師 - メッシュ(モデル)