{
	"connections": [
		{
			"from": "buffer_7",
			"from_port": 0,
			"to": "gen_outputs",
			"to_port": 0
		},
		{
			"from": "gen_inputs",
			"from_port": 0,
			"to": "buffer_2",
			"to_port": 0
		},
		{
			"from": "buffer_2",
			"from_port": 0,
			"to": "voronoi_3",
			"to_port": 0
		},
		{
			"from": "buffer_5",
			"from_port": 0,
			"to": "voronoi_2",
			"to_port": 0
		},
		{
			"from": "voronoi_3",
			"from_port": 0,
			"to": "buffer_5",
			"to_port": 0
		},
		{
			"from": "voronoi_2",
			"from_port": 0,
			"to": "buffer_7",
			"to_port": 0
		}
	],
	"label": "HBAO",
	"longdesc": "Generates a horizon based ambient occlusion texture from a height map",
	"name": "hbao",
	"node_position": {
		"x": 0,
		"y": 0
	},
	"nodes": [
		{
			"name": "voronoi_3",
			"node_position": {
				"x": -600.800720214844,
				"y": -894.601806640625
			},
			"parameters": {
				"angleBiasDeg": 15,
				"depth_scale": 0.08,
				"intensity": 1,
				"quality": 4,
				"radius": 0.1
			},
			"seed": 49449,
			"shader_model": {
				"code": "",
				"global": "",
				"inputs": [
					{
						"default": "0.0",
						"function": true,
						"label": "",
						"name": "in",
						"type": "f"
					}
				],
				"instance": [
					"//inspired by:",
					"//http://developer.download.nvidia.com/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf",
					"//https://gist.github.com/dotModded/981206ae1f4e760b7348",
					"//https://github.com/scanberg/hbao/blob/master/resources/shaders/hbao_full_frag.glsl",
					"//radius - radius of influence in screen space",
					"//angleBiasDeg - ~minimum angle for AO",
					"//intensity - increase strength of caclulated AO",
					"//noiseScale - for randomization values",
					"float $(name)_hbao(vec2 uv, float radius, float angleBiasDeg, float intensity, vec2 noiseScale) {",
					"  int samplig_directions = 8;",
					"  int steps = int($quality);",
					"",
					"  float angleBias = 0.0174532925 * angleBiasDeg;",
					"  vec2 epsilon = vec2(0.001, 0.0);",
					"",
					"  vec3 c_point = vec3(uv*2.0 - 1.0, $in(uv)*$depth_scale);",
					"  vec2 uvpdx = uv+epsilon;",
					"  vec2 uvpdy = uv+epsilon.yx;",
					"  vec3 c_point_pdx = vec3(uvpdx*2.0 - 1.0, $in(uvpdx)*$depth_scale);",
					"  vec3 c_point_pdy = vec3(uvpdy*2.0 - 1.0, $in(uvpdy)*$depth_scale);",
					"  //fun with dfdx & dfdy - https://community.khronos.org/t/getting-the-normal-with-dfdx-and-dfdy/70177",
					"  vec3 c_normal = normalize(cross(c_point_pdx-c_point, c_point_pdy-c_point));",
					"",
					"",
					"  float cosMaxRot = cos(6.28318530718 / float(samplig_directions));",
					"  float sinMaxROt = sin(6.28318530718 / float(samplig_directions));",
					"  ",
					"  // it should be faster than standard rotation in each iteartion",
					"  mat2 deltaRotationMatrix = mat2(",
					"\tvec2(cosMaxRot, -sinMaxROt),",
					"\tvec2(sinMaxROt, cosMaxRot)",
					"  );",
					"  ",
					"  // calculate starting offset, as the smallest step",
					"  vec2 offset_uv = vec2(1.0, 0.0) * (radius /float(steps));",
					"",
					"  //randomize angle",
					"  vec3 sampleNoise\t= rand3(uv * noiseScale);",
					"  sampleNoise.xy\t  = sampleNoise.xy * 2.0 - vec2(1.0);",
					"  mat2 rotationMatrix = mat2(vec2(sampleNoise.x, -sampleNoise.y), ",
					"\t\t\t\t\t\t\t vec2(sampleNoise.y,  sampleNoise.x));",
					"  ",
					"  // apply a random rotation to the base step vector",
					"  offset_uv = rotationMatrix * offset_uv;",
					"  ",
					"  float jitter = sampleNoise.z;",
					"  float occlusion = 0.0;",
					"  ",
					"  for (int i = 0; i < samplig_directions; ++i) {",
					"\t// incrementally rotate sample direction",
					"\toffset_uv = deltaRotationMatrix * offset_uv;",
					"\tfloat oldAngle   = angleBias;",
					"\tfor (int j = 0; j < steps; ++j) {",
					"\t  //add jitter & distance to offset UV",
					"\t  vec2 sample_uv\t = uv + (jitter + float(j)) * offset_uv;",
					"\t  vec3 s_point\t = vec3(sample_uv*2.0 - 1.0, $in(sample_uv)*$depth_scale);",
					"\t  vec3 sample_tan  = (s_point - c_point); //not sure if correct, but looks ok",
					"\t  // 90 deg - (angle between normal from current point &  sampled tangent)",
					"\t  //https://math.stackexchange.com/questions/654315/how-to-convert-a-dot-product-of-two-vectors-to-the-angle-between-the-vectors",
					"\t  float gamma = 1.57079632679 - acos(dot(c_normal, normalize(sample_tan)));",
					"\t  ",
					"\t  if (gamma > oldAngle) {",
					"\t\tfloat value = sin(gamma) - sin(oldAngle);",
					"\t\tfloat attenuation = clamp(1.0 - pow(length(sample_tan.xy)/radius, 2.0), 0.0, 1.0);",
					"\t\tocclusion += attenuation * value;",
					"\t\t//occlusion += value;",
					"\t\toldAngle = gamma;",
					"\t  }",
					"\t}",
					"  }",
					"  ",
					"  occlusion = 1.0 - occlusion / float(samplig_directions);",
					"  return clamp(pow(occlusion, 1.0 + intensity), 0.0, 1.0);",
					"}"
				],
				"longdesc": "A node that generates several images from a tileable voronoi noise",
				"name": "HBAO",
				"outputs": [
					{
						"f": "$(name)_hbao($uv,$radius, $angleBiasDeg, $intensity, vec2(16.0,16.0))",
						"longdesc": "A color pattern that assigns a random color to each cell",
						"shortdesc": "Random color",
						"type": "f"
					}
				],
				"parameters": [
					{
						"control": "None",
						"default": 0.01,
						"label": "Radius",
						"longdesc": "The scale along the X axis",
						"max": 1,
						"min": 0,
						"name": "radius",
						"shortdesc": "Scale.x",
						"step": 0.01,
						"type": "float"
					},
					{
						"control": "None",
						"default": 30,
						"label": "Angle Bias",
						"longdesc": "Angle bias for AO",
						"max": 90,
						"min": 0,
						"name": "angleBiasDeg",
						"shortdesc": "Angle Bias",
						"step": 1,
						"type": "float"
					},
					{
						"control": "None",
						"default": 0.2,
						"label": "Intensity",
						"longdesc": "Change intensity of AO",
						"max": 5,
						"min": 0,
						"name": "intensity",
						"shortdesc": "Intensity",
						"step": 0.01,
						"type": "float"
					},
					{
						"control": "None",
						"default": 1,
						"label": "Depth Scale",
						"longdesc": "Lineary scales depth values affecting cacluated normals & tangents",
						"max": 1,
						"min": 0,
						"name": "depth_scale",
						"shortdesc": "Depth Scale",
						"step": 0.01,
						"type": "float"
					},
					{
						"control": "None",
						"default": 4,
						"label": "Steps",
						"longdesc": "Steps in given direction per ray",
						"max": 12,
						"min": 1,
						"name": "quality",
						"shortdesc": "Quality",
						"step": 1,
						"type": "float"
					}
				],
				"shortdesc": "Voronoi Noise"
			},
			"type": "shader"
		},
		{
			"name": "gen_inputs",
			"node_position": {
				"x": -1338.03076171875,
				"y": -788.080871582031
			},
			"parameters": {

			},
			"ports": [
				{
					"group_size": 0,
					"longdesc": "Grayscale heightmap",
					"name": "input",
					"shortdesc": "Input",
					"type": "f"
				}
			],
			"seed": 43798,
			"type": "ios"
		},
		{
			"name": "gen_outputs",
			"node_position": {
				"x": -902.684204101563,
				"y": -327.282287597656
			},
			"parameters": {

			},
			"ports": [
				{
					"group_size": 0,
					"longdesc": "",
					"name": "port0",
					"shortdesc": "AO",
					"type": "f"
				}
			],
			"seed": 42623,
			"type": "ios"
		},
		{
			"name": "gen_parameters",
			"node_position": {
				"x": -1488.97900390625,
				"y": -561.711669921875
			},
			"parameters": {
				"param0": 10,
				"param1": 0.1,
				"param2": 15,
				"param3": 0.08,
				"param4": 4,
				"param5": 1
			},
			"seed": 58911,
			"type": "remote",
			"widgets": [
				{
					"label": "Size",
					"linked_widgets": [
						{
							"node": "voronoi_2",
							"widget": "size"
						},
						{
							"node": "buffer_2",
							"widget": "size"
						},
						{
							"node": "buffer_5",
							"widget": "size"
						},
						{
							"node": "buffer_7",
							"widget": "size"
						}
					],
					"name": "param0",
					"shortdesc": "Size",
					"type": "linked_control"
				},
				{
					"label": "Radius",
					"linked_widgets": [
						{
							"node": "voronoi_3",
							"widget": "radius"
						}
					],
					"longdesc": "Affected radius of point in UV size",
					"name": "param1",
					"shortdesc": "Radius",
					"type": "linked_control"
				},
				{
					"label": "Angle Bias",
					"linked_widgets": [
						{
							"node": "voronoi_3",
							"widget": "angleBiasDeg"
						}
					],
					"longdesc": "Minimum angle on heightmap for AO to occur. Angle is calculated in UV space, where depth (grayscale input) is scaled by \"Depth Scale\" parameter",
					"name": "param2",
					"shortdesc": "Angle bias",
					"type": "linked_control"
				},
				{
					"label": "Depth Scale",
					"linked_widgets": [
						{
							"node": "voronoi_3",
							"widget": "depth_scale"
						}
					],
					"longdesc": "Lineary scales depth values affecting cacluated normals & tangents",
					"name": "param3",
					"shortdesc": "Depth Scale",
					"type": "linked_control"
				},
				{
					"label": "Quality",
					"linked_widgets": [
						{
							"node": "voronoi_3",
							"widget": "quality"
						}
					],
					"longdesc": "Number of steps per direction sampling",
					"name": "param4",
					"shortdesc": "Quality",
					"type": "linked_control"
				},
				{
					"label": "Intensity",
					"linked_widgets": [
						{
							"node": "voronoi_3",
							"widget": "intensity"
						}
					],
					"longdesc": "Change intensity of calculated AO",
					"name": "param5",
					"shortdesc": "Intensity",
					"type": "linked_control"
				}
			]
		},
		{
			"name": "voronoi_2",
			"node_position": {
				"x": -718.111145019531,
				"y": -642.459533691406
			},
			"parameters": {
				"ksigma": 4,
				"sigma": 3,
				"size": 10,
				"threshold": 0.7
			},
			"seed": 38722,
			"shader_model": {
				"code": "",
				"global": "",
				"inputs": [
					{
						"default": "0.0",
						"function": true,
						"label": "",
						"name": "in",
						"type": "rgba"
					}
				],
				"instance": [
					"//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
					"//  Copyright (c) 2018-2019 Michele Morrone",
					"//  All rights reserved.",
					"//",
					"//  https://michelemorrone.eu - https://BrutPitt.com",
					"//",
					"//  me@michelemorrone.eu - brutpitt@gmail.com",
					"//  twitter: @BrutPitt - github: BrutPitt",
					"//  ",
					"//  https://github.com/BrutPitt/glslSmartDeNoise/",
					"//",
					"//  This software is distributed under the terms of the BSD 2-Clause license",
					"//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
					"//  smartDeNoise - parameters",
					"//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
					"//",
					"//  sampler2D tex\t - sampler image / texture",
					"//  vec2 uv\t\t   - actual fragment coord",
					"//  float sigma  >  0 - sigma Standard Deviation",
					"//  float kSigma >= 0 - sigma coefficient ",
					"//\t  kSigma * sigma  -->  radius of the circular kernel",
					"//  float threshold   - edge sharpening threshold ",
					"vec4 $(name)_smartDeNoise(vec2 uv, float sigma, float kSigma, float threshold)",
					"{",
					"\tfloat INV_SQRT_OF_2PI = 0.39894228040143267793994605993439; // 1.0/SQRT_OF_2PI",
					"\tfloat INV_PI = 0.31830988618379067153776752674503;",
					"\tfloat radius = round(kSigma*sigma);",
					"\tfloat radQ = radius * radius;",
					"",
					"\tfloat invSigmaQx2 = .5 / (sigma * sigma);\t  // 1.0 / (sigma^2 * 2.0)",
					"\tfloat invSigmaQx2PI = INV_PI * invSigmaQx2;\t// 1/(2 * PI * sigma^2)",
					"",
					"\tfloat invThresholdSqx2 = .5 / (threshold * threshold);\t // 1.0 / (sigma^2 * 2.0)",
					"\tfloat invThresholdSqrt2PI = INV_SQRT_OF_2PI / threshold;   // 1.0 / (sqrt(2*PI) * sigma^2)",
					"",
					"\tvec4 centrPx = $in(uv); ",
					"",
					"\tfloat zBuff = 0.0;",
					"\tvec4 aBuff = vec4(0.0);",
					"\tvec2 size = vec2($size, $size);",
					"",
					"\tvec2 d;",
					"\tfor (d.x=-radius; d.x <= radius; d.x++) {",
					"\t\tfloat pt = sqrt(radQ-d.x*d.x);\t   // pt = yRadius: have circular trend",
					"\t\tfor (d.y=-pt; d.y <= pt; d.y++) {",
					"\t\t\tfloat blurFactor = exp( -dot(d , d) * invSigmaQx2 ) * invSigmaQx2PI;",
					"",
					"\t\t\tvec4 walkPx =  $in(uv+d/size);",
					"\t\t\tvec4 dC = walkPx-centrPx;",
					"\t\t\tfloat deltaFactor = exp( -dot(dC, dC) * invThresholdSqx2) * invThresholdSqrt2PI * blurFactor;",
					"",
					"\t\t\tzBuff += deltaFactor;",
					"\t\t\taBuff += deltaFactor*walkPx;",
					"\t\t}",
					"\t}",
					"\treturn aBuff/zBuff;",
					"}"
				],
				"longdesc": "A node that generates several images from a tileable voronoi noise",
				"name": "Denoiser",
				"outputs": [
					{
						"longdesc": "A color pattern that assigns a random color to each cell",
						"rgba": "$(name)_smartDeNoise($uv, $sigma, $ksigma, $threshold)",
						"shortdesc": "Random color",
						"type": "rgba"
					}
				],
				"parameters": [
					{
						"default": 10,
						"first": 0,
						"label": "size",
						"last": 12,
						"longdesc": "The scale along the X axis",
						"name": "size",
						"shortdesc": "Scale.x",
						"type": "size"
					},
					{
						"control": "None",
						"default": 0.5,
						"label": "Sigma",
						"max": 1,
						"min": 0.005,
						"name": "sigma",
						"step": 0.1,
						"type": "float"
					},
					{
						"control": "None",
						"default": 0.5,
						"label": "kSigma",
						"max": 1,
						"min": 0,
						"name": "ksigma",
						"step": 0.1,
						"type": "float"
					},
					{
						"control": "None",
						"default": 0.5,
						"label": "threshold",
						"max": 1,
						"min": 0,
						"name": "threshold",
						"step": 0.1,
						"type": "float"
					}
				],
				"shortdesc": "Voronoi Noise"
			},
			"type": "shader"
		},
		{
			"name": "buffer_5",
			"node_position": {
				"x": -931.449645996094,
				"y": -724.330017089844
			},
			"parameters": {
				"size": 10
			},
			"seed": 6771,
			"type": "buffer",
			"version": 1
		},
		{
			"name": "buffer_7",
			"node_position": {
				"x": -948.36376953125,
				"y": -449.796295166016
			},
			"parameters": {
				"size": 10
			},
			"seed": 16139,
			"type": "buffer",
			"version": 1
		},
		{
			"name": "buffer_2",
			"node_position": {
				"x": -976.009643554688,
				"y": -975.5
			},
			"parameters": {
				"size": 10
			},
			"seed": 42465,
			"type": "buffer",
			"version": 1
		}
	],
	"parameters": {
		"param0": 10,
		"param1": 0.1,
		"param2": 15,
		"param3": 0.08,
		"param4": 4,
		"param5": 1
	},
	"seed": 6741,
	"shortdesc": "Horizon Based Ambient Occulusion",
	"type": "graph"
}
