ミップマップのLODレベルによって処理を振り分ける
環境
Unity2021.2.18f1
概要
処理の重いシェーダを作成するときにミップマップのLODレベルで処理を切り替えたい事があります。 そんな場合は、CalculateLevelOfDetailを使用します。
このシェーダはLODレベルに応じてカラーを変えているだけのものです。
Shader "Custom/MipmapLodVisualize" { Properties { _MainTex ("Texture", 2D) = "white" {} } CGINCLUDE #pragma target 4.5 #include "UnityCG.cginc" #define UNITY_LOD_TEX2D(tex,coord) tex.CalculateLevelOfDetail(sampler##tex,coord) #define UNITY_SAMPLE_TEX2D_GRAD(tex,coord,dx,dy) tex.SampleGrad(sampler##tex,coord,dx,dy) ENDCG SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; Texture2D _MainTex; SamplerState sampler_MainTex; float4 _MainTex_ST; float4 _MainTex_TexelSize; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float mipLevel; float mipLevelInt; float mipLevelFrac; float2 dx, dy; #if 0 //ポイントサンプルなら合う。こちらを使いたい場合もあるかも float2 texCoordsPerSize = i.uv * _MainTex_TexelSize.zw; float2 dxSize, dySize; float4(dxSize, dx) = ddx(float4(texCoordsPerSize, i.uv)); float4(dySize, dy) = ddy(float4(texCoordsPerSize, i.uv)); float minTexCoordDelta; float2 texCoords; texCoords = dxSize * dxSize + dySize * dySize; minTexCoordDelta = max(texCoords.x, texCoords.y); mipLevel = max(0.5 * log2(minTexCoordDelta), 0); #else mipLevel = UNITY_LOD_TEX2D(_MainTex, i.uv); dx = ddx(i.uv); dy = ddy(i.uv); #endif mipLevelFrac = modf(mipLevel, mipLevelInt); fixed4 col; fixed4 cols[] = {fixed4(1,0,0,1), fixed4(0,1,1,1), fixed4(1,0,1,1), fixed4(0,1,0,1), fixed4(0,0,1,1), fixed4(1,1,0,1), fixed4(1,1,1,1)}; if(mipLevel > 5) col = fixed4(1,1,1,1); else { fixed4 col0 = cols[mipLevelInt]; fixed4 col1 = cols[mipLevelInt + 1]; col = lerp(col0, col1, mipLevelFrac); } return col; //return UNITY_SAMPLE_TEX2D_GRAD(_MainTex, i.uv, dx, dy); } ENDCG } } }
参考
textureQueryLod/CalculateLevelOfDetail in Fragment Shader - Unity Answers
コースティクス
環境
Unity2021.2.18f1
概要
テクスチャを使用したコースティクスです。
参考リンクのものを実装しました。ルミナンスマスクは実装していません。
以下のサイトのテクスチャを使用させていただいています。
Water Caustics Effect (Small) | OpenGameArt.org
Shader "Custom/Caustics" { Properties { _CausticsTexture("Caustics Texture", 2D) = "white" {} _CausticsSpeed("CausticsSpeed", float) = 0.05 _CausticsScale("CausticsScale", float) = 3 _CausticsStrength("CausticsStrength", float) = 1 _CausticsSplit("CausticsSplit", float) = 0.002 _CausticsFadeRadius("CausticsFadeRadius", float) = 0.3 _CausticsFadeStrength("CausticsFadeStrength", float) = 0.6 } SubShader { Tags { "RenderType" = "Transparent" "Queue" = "Transparent" //"LightMode" = "ForwardBase" } Pass { ZWrite Off ZTest Always Cull Front Lighting Off Cull Back Blend SrcAlpha One//OneMinusSrcAlpha CGPROGRAM //#pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //#include "AutoLight.cginc" //#include "Lighting.cginc" half4 _Color; sampler2D _CameraDepthTexture; float _CausticsSpeed; float _CausticsScale; float _CausticsStrength; float _CausticsSplit; float _CausticsFadeRadius; float _CausticsFadeStrength; struct VSInput { float4 vertex : POSITION; float3 texcoord : TEXCOORD0; }; struct VSOut { float4 positionCS :SV_POSITION; float4 positionSS : TEXCOORD0; float3 rayVS : TEXCOORD1; float radius : TEXCOORD3; }; half4x4 _MainLightDirection; sampler2D _CausticsTexture; VSOut vert(VSInput v) { VSOut o; o.positionCS = UnityObjectToClipPos(v.vertex); o.positionSS = ComputeScreenPos(o.positionCS); o.rayVS = UnityObjectToViewPos(v.vertex).xyz; o.rayVS.z *= -1; o.radius = length(UNITY_MATRIX_M._m01_m11_m21) * 0.5; return o; } half2 Panner(half2 uv, half speed, half tiling) { return (half2(1, 0) * _Time.y * speed) + (uv * tiling); } half3 SampleCaustics(half2 uv, half split) { half2 uv1 = uv + half2(split, split); half2 uv2 = uv + half2(split, -split); half2 uv3 = uv + half2(-split, -split); half r = tex2D(_CausticsTexture, uv1).r; half g = tex2D(_CausticsTexture, uv2).r; half b = tex2D(_CausticsTexture, uv3).r; return half3(r, g, b); } fixed4 frag(VSOut i) : Color { const float far = _ProjectionParams.z; i.rayVS = i.rayVS * (far / i.rayVS.z); float depth; float3 normalVS; float2 positionSS = i.positionSS.xy / i.positionSS.w; depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, positionSS); depth = Linear01Depth(depth); float4 positionVS = float4(i.rayVS * depth, 1); float3 positionWS = mul(unity_CameraToWorld, positionVS).xyz; /* half4 color = half4(frac(positionWS.xyz), 1.0); #if UNITY_REVERSED_Z if (depth < 0.0001) return half4(0,0,0,1); #else if (depth > 0.9999) return half4(0,0,0,1); #endif */ // calculate position in object-space coordinates float3 positionOS = mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz; /* // create bounding box mask float boundingBoxMask = all(step(positionOS, 0.5) * (1 - step(positionOS, -0.5))); color.rgb = boundingBoxMask; */ half2 uv = mul(positionWS, _MainLightDirection).xy; half2 uv1 = Panner(uv, 0.75 * _CausticsSpeed, 1 / _CausticsScale); half2 uv2 = Panner(uv, 1 * _CausticsSpeed, -1 / _CausticsScale); half3 tex1 = SampleCaustics(uv1, _CausticsSplit); half3 tex2 = SampleCaustics(uv2, _CausticsSplit); half edgeFadeMask = 1 - saturate((distance(positionOS, 0) - _CausticsFadeRadius) / (1 - _CausticsFadeStrength)); half3 caustics = min(tex1, tex2) * _CausticsStrength * edgeFadeMask; return fixed4(caustics, 1); } ENDCG } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] public class Caustics : MonoBehaviour { private Material _causticsMaterial = null; private void OnEnable() { var renderer = GetComponent<Renderer>(); _causticsMaterial = renderer.sharedMaterial; } private void Update() { var sunMatrix = RenderSettings.sun.transform.localToWorldMatrix; _causticsMaterial.SetMatrix("_MainLightDirection", sunMatrix); } }
感想
色収差の部分のテクスチャフェッチは重いので、パラメータの値が決まったら、あらかじめテクスチャのUVにチャンネルごとにオフセットを入れておくと良いと思いました。
参考
2DLookupLighting(FakeBRDF)
環境
Unity2021.2.18f1
概要
Lookupテクスチャを使用したライティングです。
以下のページの画像に対応するようにしています。 BRDF - Wakapon
Shader "Unlit/2DLookupLighting" { Properties { _NormalTex("Normal Texture", 2D) = "white" {} _Lookup("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD0; }; struct v2f { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; fixed3 TSToWS0 : TEXCOORD1; fixed3 TSToWS1 : TEXCOORD2; fixed3 TSToWS2 : TEXCOORD3; half3 viewDirWS: TEXCOORD4; half3 lightDirWS: TEXCOORD5; }; sampler2D _NormalTex; float4 _NormalTex_ST; sampler2D _Lookup; v2f vert(appdata v) { v2f o; o.positionCS = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _NormalTex); fixed3 normalWS = UnityObjectToWorldNormal(v.normal); fixed3 tangentWS = UnityObjectToWorldDir(v.tangent.xyz); fixed3 binormalWS = cross(normalWS, tangentWS) * v.tangent.w; o.TSToWS0 = fixed3(tangentWS.x, binormalWS.x, normalWS.x); o.TSToWS1 = fixed3(tangentWS.y, binormalWS.y, normalWS.y); o.TSToWS2 = fixed3(tangentWS.z, binormalWS.z, normalWS.z); o.viewDirWS = WorldSpaceViewDir(v.vertex); o.lightDirWS = WorldSpaceLightDir(v.vertex); return o; } fixed3 LightingLookup(half3 lightDir, half3 viewDir, half3 normal) { #define HALF_VEC 1 #if HALF_VEC half3 HalfDir = normalize(lightDir + viewDir); float NdotL = dot(normal, HalfDir); #else float NdotL = dot(normal, viewDir); #endif float NdotV = dot(normal, viewDir); float2 lookupUV = float2(1.0 - (NdotL * 0.5 + 0.5), 1.0 - saturate(NdotV)); fixed3 exitRadiance = tex2D(_Lookup, lookupUV).rgb; float atten = 1; return _LightColor0.rgb * (exitRadiance * atten * 2); } fixed4 frag(v2f i) : SV_Target { half3 normalTS = UnpackNormal(tex2D(_NormalTex, i.uv)); half3 normalWS; normalWS.x = dot(i.TSToWS0.xyz, normalTS); normalWS.y = dot(i.TSToWS1.xyz, normalTS); normalWS.z = dot(i.TSToWS2.xyz, normalTS); normalWS = normalize(normalWS); half3 lightDirWS = normalize(i.lightDirWS); half3 viewDirWS = normalize(i.viewDirWS); fixed3 diffuse = LightingLookup(lightDirWS, viewDirWS, normalWS); return fixed4(diffuse, 1); } ENDCG } } }
参考
Problem with BRDF Shader - Unity Forum
Writing Surface Shaders in Unity3D: BRDF Fake - YouTube
Index of /datahoarder/Walt Disney Animation Studios/BRDF Explorer
環境マッピング
環境
Unity2021.2.18f1
概要
環境マッピングです。 Cube、FakeSpherical(Matcap)、Equirectangular、FishEyeで行ってみました。 BumpMap付です。
Shader "Custom/Cube-BumpedEnv" { Properties { _Color("Main Color", Color) = (1,1,1,1) _MainTex("Diffuse (RGB) Alpha (A)", 2D) = "gray" {} _NormalTex("Normal Texture", 2D) = "white" {} _EnvTex("Env Texture", CUBE) = "white" {} } SubShader { Pass { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD; }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; half3 lightDirWS : TEXCOORD1; fixed3 TSToWS0 : TEXCOORD2; fixed3 TSToWS1 : TEXCOORD3; fixed3 TSToWS2 : TEXCOORD4; half3 viewDirWS : TEXCOORD5; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _NormalTex; UNITY_DECLARE_TEXCUBE(_EnvTex); v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.lightDirWS = WorldSpaceLightDir(v.vertex); fixed3 normalWS = UnityObjectToWorldNormal(v.normal); fixed3 tangentWS = UnityObjectToWorldDir(v.tangent.xyz); fixed3 binormalWS = cross(normalWS, tangentWS) * v.tangent.w; o.TSToWS0 = fixed3(tangentWS.x, binormalWS.x, normalWS.x); o.TSToWS1 = fixed3(tangentWS.y, binormalWS.y, normalWS.y); o.TSToWS2 = fixed3(tangentWS.z, binormalWS.z, normalWS.z); o.viewDirWS = WorldSpaceViewDir(v.vertex); return o; } fixed4 frag(v2f i) : COLOR { half3 normalTS = UnpackNormal(tex2D(_NormalTex, i.uv)); half3 normalWS; normalWS.x = dot(i.TSToWS0.xyz, normalTS); normalWS.y = dot(i.TSToWS1.xyz, normalTS); normalWS.z = dot(i.TSToWS2.xyz, normalTS); normalWS = normalize(normalWS); half3 lightDirWS = normalize(i.lightDirWS); fixed4 diffuse = (dot(normalWS, lightDirWS) * 0.5 + 0.5) * _LightColor0; fixed4 col = diffuse * tex2D(_MainTex, i.uv); half3 viewDirWS = normalize(i.viewDirWS); half3 reflDirWS = reflect(-viewDirWS, normalWS); fixed4 envCol = UNITY_SAMPLE_TEXCUBE(_EnvTex, reflDirWS); return col + envCol; } ENDCG } } FallBack "VertexLit" }
Shader "Custom/FakeSpherical-BumpedEnv" { Properties { _Color("Main Color", Color) = (1,1,1,1) _MainTex("Diffuse (RGB) Alpha (A)", 2D) = "gray" {} _NormalTex("Normal Texture", 2D) = "white" {} _EnvTex("Env Texture", 2D) = "white" {} } SubShader { Pass { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD; }; #define MAPPING_TYPE0 1 struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; half3 lightDirWS : TEXCOORD1; fixed3 TSToWS0 : TEXCOORD2; fixed3 TSToWS1 : TEXCOORD3; fixed3 TSToWS2 : TEXCOORD4; #if MAPPING_TYPE0 half3 viewDirWS : TEXCOORD5; #endif }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _NormalTex; sampler2D _EnvTex; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.lightDirWS = WorldSpaceLightDir(v.vertex); fixed3 normalWS = UnityObjectToWorldNormal(v.normal); fixed3 tangentWS = UnityObjectToWorldDir(v.tangent.xyz); fixed3 binormalWS = cross(normalWS, tangentWS) * v.tangent.w; o.TSToWS0 = fixed3(tangentWS.x, binormalWS.x, normalWS.x); o.TSToWS1 = fixed3(tangentWS.y, binormalWS.y, normalWS.y); o.TSToWS2 = fixed3(tangentWS.z, binormalWS.z, normalWS.z); #if MAPPING_TYPE0 o.viewDirWS = WorldSpaceViewDir(v.vertex); #endif return o; } inline float2 Mapping(float3 normal) { #if MAPPING_TYPE0 half3 normalVS = mul((float3x3)UNITY_MATRIX_V, normal); normalVS.z += 1; return normalVS.xy / length(normalVS) * 0.5 + 0.5; #else return normal.xy * 0.5 + 0.5; #endif } fixed4 frag(v2f i) : COLOR { half3 normalTS = UnpackNormal(tex2D(_NormalTex, i.uv)); half3 normalWS; normalWS.x = dot(i.TSToWS0.xyz, normalTS); normalWS.y = dot(i.TSToWS1.xyz, normalTS); normalWS.z = dot(i.TSToWS2.xyz, normalTS); normalWS = normalize(normalWS); half3 lightDirWS = normalize(i.lightDirWS); fixed4 diffuse = (dot(normalWS, lightDirWS) * 0.5 + 0.5) * _LightColor0; fixed4 col = diffuse * tex2D(_MainTex, i.uv); #if MAPPING_TYPE0 half3 viewDirWS = normalize(i.viewDirWS); half3 reflDirWS = reflect(-viewDirWS, normalWS); fixed4 envCol = tex2D(_EnvTex, Mapping(reflDirWS)); #else half3 normalVS = mul((float3x3)UNITY_MATRIX_V, normalWS); fixed4 envCol = tex2D(_EnvTex, Mapping(normalVS)); #endif return col + envCol; } ENDCG } } FallBack "VertexLit" }
Shader "Custom/Equirectangular-BumpedEnv" { Properties { _Color("Main Color", Color) = (1,1,1,1) _MainTex("Diffuse (RGB) Alpha (A)", 2D) = "gray" {} _NormalTex("Normal Texture", 2D) = "white" {} _EnvTex("Env Texture", 2D) = "white" {} } SubShader { Pass { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD; }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; half3 lightDirWS : TEXCOORD1; fixed3 TSToWS0 : TEXCOORD2; fixed3 TSToWS1 : TEXCOORD3; fixed3 TSToWS2 : TEXCOORD4; half3 viewDirWS : TEXCOORD5; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _NormalTex; sampler2D _EnvTex; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.lightDirWS = WorldSpaceLightDir(v.vertex); fixed3 normalWS = UnityObjectToWorldNormal(v.normal); fixed3 tangentWS = UnityObjectToWorldDir(v.tangent.xyz); fixed3 binormalWS = cross(normalWS, tangentWS) * v.tangent.w; o.TSToWS0 = fixed3(tangentWS.x, binormalWS.x, normalWS.x); o.TSToWS1 = fixed3(tangentWS.y, binormalWS.y, normalWS.y); o.TSToWS2 = fixed3(tangentWS.z, binormalWS.z, normalWS.z); o.viewDirWS = WorldSpaceViewDir(v.vertex); return o; } inline float2 Mapping(half3 normal) { float2 longlat = float2(atan2(normal.x, normal.z) + UNITY_PI, acos(-normal.y)); float2 uv = longlat / float2(2.0 * UNITY_PI, UNITY_PI); return uv; } fixed4 frag(v2f i) : COLOR { half3 normalTS = UnpackNormal(tex2D(_NormalTex, i.uv)); half3 normalWS; normalWS.x = dot(i.TSToWS0.xyz, normalTS); normalWS.y = dot(i.TSToWS1.xyz, normalTS); normalWS.z = dot(i.TSToWS2.xyz, normalTS); normalWS = normalize(normalWS); half3 lightDirWS = normalize(i.lightDirWS); fixed4 diffuse = (dot(normalWS, lightDirWS) * 0.5 + 0.5) * _LightColor0; fixed4 col = diffuse * tex2D(_MainTex, i.uv); half3 viewDirWS = normalize(i.viewDirWS); half3 reflDirWS = reflect(-viewDirWS, normalWS); fixed4 envCol = tex2Dlod(_EnvTex, float4(Mapping(reflDirWS), 0, 0)); return col + envCol; } ENDCG } } FallBack "VertexLit" }
Shader "Custom/FishEye-BumpedEnv" { Properties { _Color("Main Color", Color) = (1,1,1,1) _MainTex("Diffuse (RGB) Alpha (A)", 2D) = "gray" {} _NormalTex("Normal Texture", 2D) = "white" {} _EnvTex("Env Texture", 2D) = "white" {} } SubShader { Pass { Tags { "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma multi_compile_fwdbase #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 uv : TEXCOORD; }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; half3 lightDirWS : TEXCOORD1; fixed3 TSToWS0 : TEXCOORD2; fixed3 TSToWS1 : TEXCOORD3; fixed3 TSToWS2 : TEXCOORD4; half3 viewDirWS : TEXCOORD5; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _NormalTex; sampler2D _EnvTex; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.lightDirWS = WorldSpaceLightDir(v.vertex); fixed3 normalWS = UnityObjectToWorldNormal(v.normal); fixed3 tangentWS = UnityObjectToWorldDir(v.tangent.xyz); fixed3 binormalWS = cross(normalWS, tangentWS) * v.tangent.w; o.TSToWS0 = fixed3(tangentWS.x, binormalWS.x, normalWS.x); o.TSToWS1 = fixed3(tangentWS.y, binormalWS.y, normalWS.y); o.TSToWS2 = fixed3(tangentWS.z, binormalWS.z, normalWS.z); o.viewDirWS = WorldSpaceViewDir(v.vertex); return o; } inline float2 Mapping(float3 normal) { normal.z *= -1; float m = 2.0 * sqrt( pow(normal.x, 2.0) + pow(normal.y, 2.0) + pow(normal.z + 1.0, 2.0) ); return normal.xy / m + 0.5; } fixed4 frag(v2f i) : COLOR { half3 normalTS = UnpackNormal(tex2D(_NormalTex, i.uv)); half3 normalWS; normalWS.x = dot(i.TSToWS0.xyz, normalTS); normalWS.y = dot(i.TSToWS1.xyz, normalTS); normalWS.z = dot(i.TSToWS2.xyz, normalTS); normalWS = normalize(normalWS); half3 lightDirWS = normalize(i.lightDirWS); fixed4 diffuse = (dot(normalWS, lightDirWS) * 0.5 + 0.5) * _LightColor0; fixed4 col = diffuse * tex2D(_MainTex, i.uv); half3 viewDirWS = normalize(i.viewDirWS); half3 reflDirWS = reflect(-viewDirWS, normalWS); fixed4 envCol = tex2Dlod(_EnvTex, float4(Mapping(reflDirWS), 0, 0)); return col + envCol; } ENDCG } } FallBack "VertexLit" }
感想
Equirectangular、FishEyeはtex2Dlodでミップマップを使わないようにしないと線が出てしまいます。全天で行いたい場合は素直にCubeマップを使用した方が良いと思いました。
参考
Distinctive Derivative Differences | by Ben Golus | Medium
c# - Map points on a sphere to pixel locations on fish eye image - Stack Overflow
フェイクポイントライト
環境
Unity2021.2.18f1
概要
フェイクポイントライトの実装テストです。 法線を考慮してないシンプルなものです。
Hierarchy>3d Object >Sphareで球体モデルを生成して、マテリアルに設定します。
コード
Shader "Custom/FakePointLight" { Properties{ [HDR]_Color("Color", Color) = (1, 1, 1, 1) } SubShader { Tags { "RenderType" = "Transparent" "Queue" = "Transparent" } Pass { ZWrite Off Lighting Off Cull Front ZTest Always Blend SrcAlpha One CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" half4 _Color; sampler2D _CameraDepthTexture; struct VSInput { float4 vertex : POSITION; float3 texcoord : TEXCOORD0; }; #define SSTOWS_TYPE0 1 struct VSOut { float4 positionCS :SV_POSITION; float4 positionSS : TEXCOORD0; #if SSTOWS_TYPE0 float3 rayVS : TEXCOORD1; #else float3 positionWS : TEXCOORD2; #endif float radius : TEXCOORD3; }; VSOut vert(VSInput v) { VSOut o; o.positionCS = UnityObjectToClipPos(v.vertex); o.positionSS = ComputeScreenPos(o.positionCS); #if SSTOWS_TYPE0 o.rayVS = UnityObjectToViewPos(v.vertex).xyz; o.rayVS.z *= -1; #else o.positionWS = mul(unity_ObjectToWorld, v.vertex).xyz; #endif o.radius = length(UNITY_MATRIX_M._m01_m11_m21) * 0.5; return o; } fixed4 frag(VSOut i) : Color { #if SSTOWS_TYPE0 const float far = _ProjectionParams.z; i.rayVS = i.rayVS * (far / i.rayVS.z); float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.positionSS.xy / i.positionSS.w)); float4 positionVS = float4(i.rayVS * depth, 1); float3 positionWS = mul(unity_CameraToWorld, positionVS).xyz; #else float4 positionSS = i.positionSS / i.positionSS.w; float eyeDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, positionSS.xy)); float3 cameraForwardDir = -UNITY_MATRIX_V._m20_m21_m22; float3 viewDirWS = normalize(UnityWorldSpaceViewDir(i.positionWS)); float3 positionWS = ((eyeDepth * viewDirWS * (1.0 / dot(cameraForwardDir, viewDirWS))) + _WorldSpaceCameraPos); #endif float len = length(positionWS - UNITY_MATRIX_M._m03_m13_m23); float power = 1.0 - smoothstep(0, 1, pow(saturate(len / i.radius), 0.5)); //float power = 1.0 - smoothstep(0, 1, len / i.radius); return fixed4(_Color.rgb, _Color.a * power); } ENDCG } } }
参考
UnityでC#7.2を使用できるようにしてVisualStudioに対応させる
この記事は2018年09月05日にqiitaに投稿した内容です。
環境
Unity2018.2.2f1 Incrementalcompiler 0.0.42-preview.19
概要
Incrementalcompilerをインストールしたら、VisualStudioにc#のバージョンが違うと怒られました。 その対処方法です。
Incrementalcompilerのインストール
・Unityを開く ・「window」>「PackageManager」を開く ・「All」タブでIncrementalcompilerを選択し、「install」を押す
VisualStudioがエラーを出さないようにする
・https://github.com/zoon/C-Sharp-Latest-for-Unity/releases から「csharplatest-0.1.0.18.unitypackage」をインストールする
参照
https://forum.unity.com/threads/unity-incremental-c-compiler.523993/page-7
OpticalFlowによるテクスチャアニメ補間のテスト
この記事は2018年07月02日にqiitaに投稿した内容です。
環境
Unity2017.3.0p4 Windows10 Home
概要
OpenCv3のOpticalFlowでFlowMapを作成して補間するテストです
OpenCV
OpenCvSharp3を使用しました
テクスチャ
使用した画像です https://blogs.unity3d.com/jp/2016/11/28/free-vfx-image-sequences-flipbooks/
動作
左側がflowmapで右側が線形補間です。flowmapのほうは補間は綺麗ですが、全体的に揺れている。 テクスチャを均等分割したけど、中心がずれてるスプライトがあるのかも。
flowmapです。
コード
多いのでgithubにアップ Tools/OpticalFlowで生成 https://github.com/fukaken5050/OpticalFlow
ツール
市販のVFXツールでも作成できます
Slate Editor https://www.facedownfx.com/
Houdini https://www.sidefx.com/ja/
参考
http://www.klemenlozar.com/frame-blending-with-motion-vectors/