avatar/Assets/Unlit_WF_ShaderSuite/Shaders/WF_Common.cginc
2022-09-27 20:47:45 -07:00

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