368 lines
14 KiB
HLSL
368 lines
14 KiB
HLSL
/*
|
|
* The MIT License
|
|
*
|
|
* Copyright 2018-2021 whiteflare.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef INC_UNLIT_WF_COMMON
|
|
#define INC_UNLIT_WF_COMMON
|
|
|
|
////////////////////////////
|
|
// Platform Glue
|
|
////////////////////////////
|
|
|
|
#ifdef _WF_PLATFORM_LWRP
|
|
// Lightweight RP 向け定義
|
|
#include "WF_Common_LightweightRP.cginc"
|
|
#else
|
|
// Builtin RP 向け定義
|
|
#include "WF_Common_BuiltinRP.cginc"
|
|
#endif
|
|
|
|
#ifdef _WF_FORCE_USE_SAMPLER
|
|
// サンプラーを強制的に使用する場合は、_SUB_ 側を undef して MAIN 側を使うように置き換える
|
|
#undef DECL_SUB_TEX2D
|
|
#define DECL_SUB_TEX2D(name) DECL_MAIN_TEX2D(name)
|
|
#undef PICK_SUB_TEX2D
|
|
#define PICK_SUB_TEX2D(tex, name, uv) PICK_MAIN_TEX2D(tex, uv)
|
|
#endif
|
|
|
|
////////////////////////////
|
|
// Common Utility
|
|
////////////////////////////
|
|
|
|
#define TGL_ON(value) (0.5 <= value)
|
|
#define TGL_OFF(value) (value < 0.5)
|
|
#define TGL_01(value) step(0.5, value)
|
|
|
|
static const float3 MEDIAN_GRAY = IsGammaSpace() ? float3(0.5, 0.5, 0.5) : GammaToLinearSpace( float3(0.5, 0.5, 0.5) );
|
|
|
|
#define MAX3(r, g, b) max(r, max(g, b) )
|
|
#define AVE3(r, g, b) ((r + g + b) / 3)
|
|
#define MAX_RGB(v) max(v.r, max(v.g, v.b))
|
|
#define AVE_RGB(v) ((v.r + v.g + v.b) / 3)
|
|
|
|
#define INVERT_MASK_VALUE(rgba, inv) saturate( TGL_OFF(inv) ? rgba : float4(1 - rgba.rgb, rgba.a) )
|
|
#define SAMPLE_MASK_VALUE(tex, uv, inv) INVERT_MASK_VALUE( PICK_SUB_TEX2D(tex, _MainTex, uv), inv )
|
|
#define SAMPLE_MASK_VALUE_LOD(tex, uv, inv) INVERT_MASK_VALUE( PICK_VERT_TEX2D_LOD(tex, uv, 0), inv )
|
|
|
|
#define NZF 0.0001
|
|
#define NON_ZERO_FLOAT(v) max(v, NZF)
|
|
#define NON_ZERO_VEC3(v) max(v, float3(NZF, NZF, NZF))
|
|
#define ZERO_VEC3 float3(0, 0, 0)
|
|
#define ZERO_VEC4 float4(0, 0, 0, 0)
|
|
#define ONE_VEC3 float3(1, 1, 1)
|
|
#define ONE_VEC4 float4(1, 1, 1, 1)
|
|
|
|
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
|
|
#define _LMAP_ENABLE
|
|
#endif
|
|
|
|
float2 SafeNormalizeVec2(float2 in_vec) {
|
|
float lenSq = dot(in_vec, in_vec);
|
|
if (lenSq < NZF) {
|
|
return float2(0, 0);
|
|
}
|
|
return in_vec * rsqrt(lenSq);
|
|
}
|
|
|
|
float3 SafeNormalizeVec3(float3 in_vec) {
|
|
float lenSq = dot(in_vec, in_vec);
|
|
if (lenSq < NZF) {
|
|
return float3(0, 0, 0);
|
|
}
|
|
return in_vec * rsqrt(lenSq);
|
|
}
|
|
|
|
float3 SafeNormalizeVec3Normal(float3 in_vec) {
|
|
float lenSq = dot(in_vec, in_vec);
|
|
if (lenSq < NZF) {
|
|
return float3(0, 0, 1);
|
|
}
|
|
return in_vec * rsqrt(lenSq);
|
|
}
|
|
|
|
////////////////////////////
|
|
// Normal
|
|
////////////////////////////
|
|
|
|
void localNormalToWorldTangentSpace(float3 normal, out float3 out_normal) {
|
|
out_normal = UnityObjectToWorldNormal(normal);
|
|
}
|
|
|
|
void localNormalToWorldTangentSpace(float3 normal, float4 tangent, out float3 out_normal, out float3 out_tangent, out float3 out_bitangent, float flipMirrorX, float flipMirrorY) {
|
|
// Normalは普通に計算
|
|
localNormalToWorldTangentSpace(normal, out_normal);
|
|
|
|
float tan_sign = step(0, tangent.w) * 2 - 1;
|
|
tan_sign *= unity_WorldTransformParams.w;
|
|
|
|
out_tangent = UnityObjectToWorldDir(tangent.xyz);
|
|
out_bitangent = cross(out_normal, out_tangent) * tan_sign;
|
|
|
|
if (0 < tan_sign) {
|
|
if (TGL_ON(flipMirrorX)) {
|
|
out_tangent = -out_tangent;
|
|
}
|
|
if (TGL_ON(flipMirrorY)) {
|
|
out_bitangent = -out_bitangent;
|
|
}
|
|
}
|
|
}
|
|
|
|
void localNormalToWorldTangentSpace(float3 normal, float4 tangent, out float3 out_normal, out float3 out_tangent, out float3 out_bitangent, float flipTangent) {
|
|
localNormalToWorldTangentSpace(normal, tangent, out_normal, out_tangent, out_bitangent, flipTangent, flipTangent);
|
|
}
|
|
|
|
////////////////////////////
|
|
// Lighting
|
|
////////////////////////////
|
|
|
|
static const float3 BT601 = { 0.299, 0.587, 0.114 };
|
|
static const float3 BT709 = { 0.21, 0.72, 0.07 };
|
|
|
|
float calcBrightness(float3 color) {
|
|
return dot(color, BT601);
|
|
}
|
|
|
|
float3 calcPointLight1WorldDir(float3 ws_vertex) {
|
|
ws_vertex = getPoint1LightPos() - ws_vertex;
|
|
if (dot(ws_vertex, ws_vertex) < 0.1) {
|
|
ws_vertex = float3(0, 1, 0);
|
|
}
|
|
return SafeNormalizeVec3( ws_vertex );
|
|
}
|
|
|
|
float3 calcPointLight1Dir(float3 ws_vertex) {
|
|
ws_vertex = getPoint1LightPos() - ws_vertex;
|
|
if (dot(ws_vertex, ws_vertex) < 0.1) {
|
|
ws_vertex = float3(0, 1, 0);
|
|
}
|
|
return UnityWorldToObjectDir( ws_vertex );
|
|
}
|
|
|
|
float3 calcHorizontalCoordSystem(float azimuth, float alt) {
|
|
azimuth = radians(azimuth + 90);
|
|
alt = radians(alt);
|
|
return normalize( float3(cos(azimuth) * cos(alt), sin(alt), -sin(azimuth) * cos(alt)) );
|
|
}
|
|
|
|
////////////////////////////
|
|
// Camera management
|
|
////////////////////////////
|
|
|
|
float3 worldSpaceCameraVector(float3 ws_vertex) {
|
|
// カメラへの正規化されていないベクトル
|
|
return _WorldSpaceCameraPos - ws_vertex;
|
|
}
|
|
|
|
float3 worldSpaceCameraDistance(float3 ws_vertex) {
|
|
// カメラへの距離
|
|
return length(worldSpaceCameraVector(ws_vertex));
|
|
}
|
|
|
|
float3 worldSpaceCameraDir(float3 ws_vertex) {
|
|
// カメラ方向(正規化されたベクトル)
|
|
return normalize(worldSpaceCameraVector(ws_vertex));
|
|
}
|
|
|
|
float3 worldSpaceViewPointPos() {
|
|
// ビューポイントの座標。これは SinglePass Stereo のときは左目と右目の中点になる。
|
|
#ifdef USING_STEREO_MATRICES
|
|
return (unity_StereoWorldSpaceCameraPos[0] + unity_StereoWorldSpaceCameraPos[1]) * 0.5;
|
|
#else
|
|
return _WorldSpaceCameraPos;
|
|
#endif
|
|
}
|
|
|
|
float3 worldSpaceViewPointVector(float3 ws_vertex) {
|
|
// ビューポイントへの正規化されていないベクトル
|
|
return worldSpaceViewPointPos() - ws_vertex;
|
|
}
|
|
|
|
float3 worldSpaceViewPointDistance(float3 ws_vertex) {
|
|
// ビューポイントへの距離
|
|
return length(worldSpaceViewPointVector(ws_vertex));
|
|
}
|
|
|
|
float3 worldSpaceViewPointDir(float3 ws_vertex) {
|
|
// ビューポイント方向(正規化されたベクトル)
|
|
return SafeNormalizeVec3(worldSpaceViewPointVector(ws_vertex));
|
|
}
|
|
|
|
float3 worldSpaceViewDirStereoLerp(float3 ws_vertex, float x) {
|
|
return SafeNormalizeVec3(lerp(worldSpaceViewPointPos(), _WorldSpaceCameraPos, x) - ws_vertex);
|
|
}
|
|
|
|
bool isInMirror() {
|
|
return unity_CameraProjection[2][0] != 0.0f || unity_CameraProjection[2][1] != 0.0f;
|
|
}
|
|
|
|
////////////////////////////
|
|
// Color Utility
|
|
////////////////////////////
|
|
|
|
inline float3 blendColor_Alpha(float3 base, float3 over, float power) {
|
|
// アルファブレンド
|
|
float3 c = over;
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_Add(float3 base, float3 over, float power) {
|
|
// 加算
|
|
float3 c = base + over;
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_Mul(float3 base, float3 over, float power) {
|
|
// 乗算
|
|
float3 c = base * over;
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_AddAndSub(float3 base, float3 over, float power) {
|
|
// 半加算
|
|
float3 c = base + over - MEDIAN_GRAY;
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_Screen(float3 base, float3 over, float power) {
|
|
// スクリーン
|
|
float3 c = 1 - (1 - base) * (1 - over);
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_Overlay(float3 base, float3 over, float power) {
|
|
// オーバーレイ
|
|
float3 c = lerp(
|
|
2 * base * over,
|
|
1 - 2 * (1 - base) * (1 - over.rgb),
|
|
step(AVE_RGB(base), 0.5)
|
|
);
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
inline float3 blendColor_HardLight(float3 base, float3 over, float power) {
|
|
// ハードライト
|
|
float3 c = lerp(
|
|
2 * base * over,
|
|
1 - 2 * (1 - base) * (1 - over.rgb),
|
|
step(AVE_RGB(over), 0.5)
|
|
);
|
|
return lerp(base, c, power);
|
|
}
|
|
|
|
////////////////////////////
|
|
// Matcap
|
|
////////////////////////////
|
|
|
|
float3 matcapViewCorrect(float3 vs_normal, float3 ws_view_dir) {
|
|
float3 base = mul( (float3x3)UNITY_MATRIX_V, ws_view_dir ) * float3(-1, -1, 1) + float3(0, 0, 1);
|
|
float3 detail = vs_normal.xyz * float3(-1, -1, 1);
|
|
return base * dot(base, detail) / base.z - detail;
|
|
}
|
|
|
|
float2x2 matcapRotateCorrectMatrix() {
|
|
float2 vs_topdir = mul( (float3x3)UNITY_MATRIX_V, float3(0, 1, 0) ).xy;
|
|
float top_angle = 0;
|
|
if (any(vs_topdir)) {
|
|
vs_topdir = normalize(vs_topdir);
|
|
top_angle = sign(vs_topdir.x) * acos( clamp(vs_topdir.y, -1, 1) );
|
|
}
|
|
float2x2 matrixRotate = { cos(top_angle), sin(top_angle), -sin(top_angle), cos(top_angle) };
|
|
return matrixRotate;
|
|
}
|
|
|
|
float3 calcMatcapVector(in float3 ws_view_dir, in float3 ws_normal) {
|
|
// ワールド法線をビュー法線に変換
|
|
float3 vs_normal = mul(float4(ws_normal, 1), UNITY_MATRIX_I_V).xyz;
|
|
|
|
// カメラ位置にて補正する
|
|
vs_normal = matcapViewCorrect(vs_normal, ws_view_dir);
|
|
// 真上を揃える
|
|
vs_normal.xy = mul( vs_normal.xy, matcapRotateCorrectMatrix() );
|
|
|
|
return normalize( vs_normal );
|
|
}
|
|
|
|
float4x4 calcMatcapVectorArray(in float3 ws_view_dir, in float3 ws_camera_dir, in float3 ws_normal, in float3 ws_bump_normal) {
|
|
// ワールド法線をビュー法線に変換
|
|
float3 vs_normal = mul(float4(ws_normal, 1), UNITY_MATRIX_I_V).xyz;
|
|
float3 vs_bump_normal = mul(float4(ws_bump_normal, 1), UNITY_MATRIX_I_V).xyz;
|
|
|
|
// カメラ位置にて補正する
|
|
float3 vs_normal_center = matcapViewCorrect(vs_normal, ws_view_dir);
|
|
float3 vs_normal_side = matcapViewCorrect(vs_normal, ws_camera_dir);
|
|
float3 vs_bump_normal_center = matcapViewCorrect(vs_bump_normal, ws_view_dir);
|
|
float3 vs_bump_normal_side = matcapViewCorrect(vs_bump_normal, ws_camera_dir);
|
|
|
|
// 真上を揃える
|
|
float2x2 rotate = matcapRotateCorrectMatrix();
|
|
vs_normal_center.xy = mul( vs_normal_center.xy, rotate );
|
|
vs_normal_side.xy = mul( vs_normal_side.xy, rotate );
|
|
vs_bump_normal_center.xy = mul( vs_bump_normal_center.xy, rotate );
|
|
vs_bump_normal_side.xy = mul( vs_bump_normal_side.xy, rotate );
|
|
|
|
float4x4 matcapVector;
|
|
matcapVector[0] = float4( normalize(vs_normal_center), 0 );
|
|
matcapVector[1] = float4( normalize(vs_bump_normal_center), 0 );
|
|
matcapVector[2] = float4( normalize(vs_normal_side), 0 );
|
|
matcapVector[3] = float4( normalize(vs_bump_normal_side), 0 );
|
|
return matcapVector;
|
|
}
|
|
|
|
float3 calcMatcapVector(float4x4 matcapVector, float normal, float parallax) {
|
|
return lerp( lerp(matcapVector[0].xyz, matcapVector[1].xyz, normal), lerp(matcapVector[2].xyz, matcapVector[3].xyz, normal), parallax);
|
|
}
|
|
|
|
////////////////////////////
|
|
// RGB-HSV convert
|
|
////////////////////////////
|
|
|
|
float3 rgb2hsv(float3 c) {
|
|
// i see "https://qiita.com/_nabe/items/c8ba019f26d644db34a8"
|
|
static float4 k = float4( 0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0 );
|
|
static float e = 1.0e-10;
|
|
float4 p = lerp( float4(c.bg, k.wz), float4(c.gb, k.xy), step(c.b, c.g) );
|
|
float4 q = lerp( float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r) );
|
|
float d = q.x - min(q.w, q.y);
|
|
return float3( abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x );
|
|
}
|
|
|
|
float3 hsv2rgb(float3 c) {
|
|
// i see "https://qiita.com/_nabe/items/c8ba019f26d644db34a8"
|
|
static float4 k = float4( 1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0 );
|
|
float3 p = abs( frac(c.xxx + k.xyz) * 6.0 - k.www );
|
|
return c.z * lerp( k.xxx, saturate(p - k.xxx), c.y );
|
|
}
|
|
|
|
////////////////////////////
|
|
// ReflectionProbe Sampler
|
|
////////////////////////////
|
|
|
|
#define pickReflectionCubemap(cubemap, hdrInst, ws_vertex, ws_normal, lod) \
|
|
( DecodeHDR( PICK_MAIN_TEXCUBE_LOD(cubemap, reflect(-worldSpaceCameraDir(ws_vertex), ws_normal), lod ), hdrInst) )
|
|
|
|
/*
|
|
float3 pickReflectionCubemap(samplerCUBE cubemap, half4 cubemap_HDR, float3 ws_vertex, float3 ws_normal, float lod) {
|
|
float3 ws_camera_dir = worldSpaceCameraDir(ws_vertex);
|
|
float3 reflect_dir = reflect(-ws_camera_dir, ws_normal);
|
|
|
|
float4 color = texCUBElod(cubemap, float4(reflect_dir, lod) );
|
|
return DecodeHDR(color, cubemap_HDR);
|
|
}
|
|
*/
|
|
|
|
#endif
|