2019-05-05

Interleaved gradient noise Interleaved gradient noise - Nao_uの日記 を含むブックマーク はてなブックマーク - Interleaved gradient noise - Nao_uの日記 Interleaved gradient noise - Nao_uの日記 のブックマークコメント

レイマーチのアーティファクトを減らすのに使えそう

https://blog.demofox.org/2017/10/31/animating-noise-for-integration-over-time/

Interleaved gradient noise, which gives middle results, is actually very similar in generation costs as white noise believe it or not, and so can also be done in real time on either the CPU or GPU.

If you have X and Y pixel coordinates (not uv coordinates), you can generate the noise value for the pixel by using this formula:

float noise = std::fmodf(52.9829189f * std::fmodf(0.06711056f*float(x) + 0.00583715f*float


マテリアルシェーダーの実験ソースメモ マテリアルシェーダーの実験ソースメモ - Nao_uの日記 を含むブックマーク はてなブックマーク - マテリアルシェーダーの実験ソースメモ - Nao_uの日記 マテリアルシェーダーの実験ソースメモ - Nao_uの日記 のブックマークコメント

f:id:Nao_u:20190506121430j:image

動画:https://twitter.com/Nao_u_/status/1125247333183057920

元ネタ:https://twitter.com/MrZulubo/status/1122611573510377472

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/TestShader2"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
		_MainTex("Albedo (RGB)", 2D) = "white" {}
		_Volume("Volume", 3D) = "" {}
		_SparkMap("SparkMap", 2D) = "white" {}
	//		_ParallaxMap("_ParallaxMap", 2D) = "white" {}
	
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
		_Distotion("Distotion", Float) = 0.5
		_Iteration("Iteration", int) = 5
	}
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
		#pragma vertex vert
//		#pragma fragment frag

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.5

		sampler2D _MainTex;
		sampler2D _SparkMap;
		sampler3D _Volume;
		//		sampler2D _ParallaxMap;

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

		struct appdata
		{
			float4 vertex : POSITION;
			float2 uv : TEXCOORD0;
			float3 normal : NORMAL;
			float4 tangent : TANGENT;
		};


		float _Distotion;
		int _Iteration;
		int _Type;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)


		struct Input {
			float2 uv_MainTex;
			float3 viewDirTangent;
			float4 screenPosition;
			float4 objPos;
			//UNITY_VPOS_TYPE vpos : VPOS;
		};

		void vert(inout appdata_full v, out Input o) {
			UNITY_INITIALIZE_OUTPUT(Input, o);

			float4 objCam = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
			float3 viewDir = v.vertex.xyz - objCam.xyz;
			float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
			float3 bitangent = cross(v.normal.xyz, v.tangent.xyz) * tangentSign;
			o.viewDirTangent = float3(
				dot(viewDir, v.tangent.xyz),
				dot(viewDir, bitangent.xyz),
				dot(viewDir, v.normal.xyz)
				);

			o.screenPosition = ComputeScreenPos(v.vertex);
			o.objPos = UnityObjectToClipPos(v.vertex);
		}

		void surf(Input IN, inout SurfaceOutputStandard o)
		{
			// Interleaved gradient noiseでアーティファクトを消す実験
			float2 screenPos = IN.objPos.xy / IN.objPos.z;
			screenPos.xy *= 1;
			float x = screenPos.x;
			float y = screenPos.y*(16.0f / 9.0f);
			float ig_noise = frac(52.9829189f * frac(0.06711056f*float(x) + 0.00583715f*float(y)));
			float mm = 0.0001; // 100サンプルあるならいらないのでほとんど無効に
			float addNoize = -mm + (2 * mm *ig_noise);

			// テクスチャ歪み
			float2 warp = tex2D(_MainTex, -IN.uv_MainTex).rg;

			// パララックス
			float2 uv = IN.uv_MainTex;
			uv.x += _Time.x*-0.5;
			uv.y += _Time.x*-1.0;
			uv += warp*0.075;
			float parallax = 0;
			for (int j = 0; j < _Iteration; j++) {
				float ratio = (float)j / _Iteration;
				//float col = tex2D(_MainTex, uv + lerp(0, _Distotion, ratio+ addNoize) * normalize(IN.viewDirTangent)) * lerp(1, 0, ratio);
				float2 uv2 = uv + lerp(0, _Distotion, ratio + addNoize) * normalize(IN.viewDirTangent);
				float3 uv3 = float3(uv2.x, uv2.y, 0.5+_Time.x*2);
				float col = tex3D(_Volume, uv3) * lerp(1, 0, ratio)*1.0;

				if (col > ratio) {
					parallax +=  col;
				}
			}
			parallax /= _Iteration;

			// 適当に色を弄る
			fixed4 c = ((tex2D(_MainTex, IN.uv_MainTex+float2(_Time.x*-0.5,_Time.x*-1.1))-float4(0.2,0.5,0.5,0)) * 0.5) * float4(1, 0.5, 0.5, 1);
			o.Albedo = c.rgb + pow(parallax,1.7) * _Color.rgb*100;
			o.Albedo.gb = pow(o.Albedo.gb + float2(0.2, 0.1), 2.5);
			o.Albedo.r += c.r * 1.25;

			// 光の粒(3レイヤー)
			float4 spk_col0 = float4(1.0, 1.0, 1.0, 1);
			float4 spk_col1 = float4(2.0, 1.0, 2.0, 1);
			float4 spk_col2 = float4(2.0, 1.5, 2.0, 1);
			{
				float depth = 2.0;
				float2 uv = IN.uv_MainTex + float2(_Time.x * -3.1, _Time.x * -1.05);
				float4 spk = tex2D(_SparkMap, uv + depth * normalize(IN.viewDirTangent)) * spk_col0;
				o.Albedo += spk.rgb * 2;
			}
			{
				float depth = 0.5;
				float2 uv = IN.uv_MainTex + float2(_Time.x * 1.25, _Time.x * 0.25);
				float4 spk = tex2D(_SparkMap, uv + depth * normalize(IN.viewDirTangent)) * spk_col1;
				o.Albedo += spk.rgb * 3;
			}
			{
				float depth = 0.25;
				float2 uv = IN.uv_MainTex + float2(_Time.x * -0.20, _Time.x * -0.3);
				float4 spk = tex2D(_SparkMap, uv + depth * normalize(IN.viewDirTangent)) * spk_col2;
				o.Albedo += spk.rgb * 2;
			}

			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}


        ENDCG
    }
    FallBack "Diffuse"
}