group = "Output"
display_name = "Unlit Base"
output_node = true
render_configs = ["core/stingray_renderer/renderer"]

inputs = {
	"aee6e47b-be7b-4d67-a123-2ab5d660b94e" = {
		name = "vertex_offset"
		display_name = "Position offset"
		is_required = false
		type = { vector3: ["HAS_VERTEX_OFFSET"] }
		domain = "vertex"
	}

	"aca690cb-6305-4a2f-bf3d-69183a493db3" = {
		name = "base_color"
		is_required = false
		display_name = "Base Color"
		type = { vector3: ["HAS_BASE_COLOR"] }
		domain = "pixel"
	}

	"34259752-b962-4b65-92c3-903a57338519" = {
		name = "opacity"
		is_required = false
		display_name = "Opacity"
		type = { scalar: ["HAS_OPACITY"] }
		domain = "pixel"
	}

	"c9a30d71-a8ad-4b9e-aedf-d785ae7e301f" = {
		name = "additive"
		is_required = false
		display_name = "Additive"
		type = { scalar: ["HAS_ADDITIVE"] }
		domain = "pixel"
	}
}

options = {
	"d1a42a54-0794-4d57-9aa0-eb35acb6b35c" = "INSTANCED"
	"8df1b8f7-17c2-4ae4-8c4e-25517ec1df46" = "DOUBLE_SIDED"
	"34994d84-9d51-48ac-af85-bc053b2c65c3" = "SKIN"
	"e1bfa889-2503-4ac3-9134-c08a7fa04568" = "PROJECT_TO_FAR_PLANE"
	"6a6241cc-7d21-4e2e-87c8-8d9c7bdcd322" = "CAMERA_TRANSLATION_LOCK"
	"435e14e4-556d-4ac1-af14-8dafe63aff8f" = "BLEND_TRANSPARENT"
	"52c7ce01-ee57-4770-914e-727fc1966962" = "LAYER_EMISSIVE"
	"182fabd6-9a4d-4cfc-8c8f-0c45ef09a138" = "LAYER_SKYDOME"
	"4c3163d4-c086-4645-ba1c-0d68a98022a1" = "LAYER_HDR_TRANSPARENT"
	"c8d8b754-c567-4c7b-9cbd-8acab22beff5" = "LAYER_TRANSPARENT"
	"afe47c59-33c4-43b2-af4a-817085b1113c" = "DEPTH_TEST_INVERTED"
	"774556cd-2d1e-4df8-8ae2-5e84800f0c04" = "DEPTH_TEST_DISABLED"
	"7b8bc0bf-c453-49d2-9415-0e80fec1039f" = "DISABLE_DEPTH_WRITE"
	"b2556764-e8e9-47cf-9ecc-f53b5d5d73c7" = "HAS_CUSTOM_FOV"
}

ui = [
	{
		type = "drop_down"
		display_name = "Layer"
		options = {
			"Emissive"	= "52c7ce01-ee57-4770-914e-727fc1966962"
			"Skydome"	= "182fabd6-9a4d-4cfc-8c8f-0c45ef09a138"
			"HDR Transparent" = "4c3163d4-c086-4645-ba1c-0d68a98022a1"
			"LDR Transparent" = "c8d8b754-c567-4c7b-9cbd-8acab22beff5"
		}
		default = "4c3163d4-c086-4645-ba1c-0d68a98022a1"
	}

	{
		type = "drop_down"
		display_name = "Depth Testing"
		options = {
			"Normal"	= "00000000-0000-0000-0000-000000000000"
			"Inverted"	= "afe47c59-33c4-43b2-af4a-817085b1113c"
			"Disabled"	= "774556cd-2d1e-4df8-8ae2-5e84800f0c04"
		}
		default = "00000000-0000-0000-0000-000000000000"
	}

	{
		type = "drop_down"
		display_name = "Blend Mode"
		options = {
			"Opaque"	= "00000000-0000-0000-0000-000000000000"
			"Transparent"	= "435e14e4-556d-4ac1-af14-8dafe63aff8f"
		}
		default = "00000000-0000-0000-0000-000000000000"
	}

	{ type = "checkbox" display_name = "Disable Depth Writes" option = "7b8bc0bf-c453-49d2-9415-0e80fec1039f" }
	{ type = "checkbox" display_name = "Double Sided" option = "8df1b8f7-17c2-4ae4-8c4e-25517ec1df46" }
	{ type = "checkbox" display_name = "Instancing" option = "d1a42a54-0794-4d57-9aa0-eb35acb6b35c" }
	{ type = "checkbox" display_name = "Project to Far Plane" option = "e1bfa889-2503-4ac3-9134-c08a7fa04568" }
	{ type = "checkbox" display_name = "Camera Translation Lock" option = "6a6241cc-7d21-4e2e-87c8-8d9c7bdcd322" }
	{ type = "checkbox" display_name = "Custom FOV" option = "b2556764-e8e9-47cf-9ecc-f53b5d5d73c7" }
]

render_state = {
	unlit = {
		inherit: ["core/stingray_renderer/shader_libraries/common#default"]
		state: {
			"defined(BLEND_TRANSPARENT)" = {
				blend_enable = "true"
				blend_op = "blend_op_add"
				dest_blend = "blend_inv_src_alpha"
				src_blend = "blend_one"
			}

			"defined(DEPTH_TEST_DISABLED)" = {
				z_enable = "false"
			}
			
			"defined(DISABLE_DEPTH_WRITE)" = {
				z_write_enable = "false"
			}

			"defined(DEPTH_TEST_INVERTED)" = {
				z_func = "greater_equal"
			}
		}
	}

	material_transfer = {
		inherit: ["core/stingray_renderer/shader_libraries/common#default"]
		state: {
			cull_mode = "cull_none"
			z_write_enable = "false"
			z_enable = "false"
		}
	}	

	wireframe = {
		inherit: ["core/stingray_renderer/shader_libraries/common#opacity"]
		state: {
			fill_mode = "fill_wireframe"
			"on_renderer(D3D11, D3D12)" = {
				depth_bias = "-1"
				depth_bias_clamp = "-0.00015"
				slope_scale_depth_bias = "-2.0"
			}
		}
	}	
}

sampler_state = { }

channels = 	{
	"defined(NEEDS_EYE_VECTOR)": {
		eye_vector = { type = "float3" domain = "vertex" }
	}

	"defined(NEEDS_WORLD_SPACE_NORMAL)": {
		world_space_normal = { type = "float3" domains = ["vertex", "pixel"] }
	}

	"defined(MOTION_BLUR)": {
		last_clip_position = { type = "float3" domains = ["vertex", "pixel"] }
	}

	"defined(MATERIAL_TRANSFER)": {
		lightmap_uv = { type = "float2" semantic="TEXCOORD1" domains = ["vertex"] }
	}

	"defined(NEEDS_SCREEN_POS)": {
		screen_pos = { type = "float2" domain = "pixel" }
	}

	"defined(NEEDS_PIXEL_DEPTH)": {
		pixel_depth = { type = "float" domain = "pixel" }
	}

	vertex_position = { type = "float4" domain = "vertex" }
	vertex_normal = { type = "float3" semantic = "NORMAL" domain = "vertex" }
}

//log_permutations = true
permutation_sets = {
	vertex_modifiers = [
		{ if: "num_skin_weights() == 4" define: { "macros": ["SKINNED_4WEIGHTS"] stages: ["vertex"] } }
		{ if: "num_skin_weights() == 3" define: { "macros": ["SKINNED_3WEIGHTS"] stages: ["vertex"] } }
		{ if: "num_skin_weights() == 2" define: { "macros": ["SKINNED_2WEIGHTS"] stages: ["vertex"] } }
		{ if: "num_skin_weights() == 1" define: { "macros": ["SKINNED_1WEIGHT"]  stages: ["vertex"] } }
		{ default = true }
	]

	instanced_modifiers = [
		{ default = true }
	]
	
	non_instanced_modifiers = [
		{ permute_with: "vertex_modifiers" }
	]

	default = [
		{ if: "defined(INSTANCED)" permute_with: "instanced_modifiers" }
		{ if: "!defined(INSTANCED)" permute_with: "non_instanced_modifiers" }
	]
}

shader_contexts = {
	default = {
		passes_sort_mode = "deferred"
		compile_with = [
			{ if: "on_renderer(D3D11, D3D12, GNM, GL) && defined(LAYER_HDR_TRANSPARENT) && render_setting(low_res_transparency)" defines=["LOW_RES_ENABLED"] permute_with: "default" }
			{ if: "on_renderer(D3D11, D3D12, GNM, GL)" permute_with: "default" }
		]

		passes = [
			{ if: "defined(LAYER_EMISSIVE)" then: [
				{ layer="emissive" code_block="unlit" defines="MOTION_BLUR" render_state="unlit" }
			]}	
			{ if: "defined(LAYER_SKYDOME)" then: [
				{ layer="skydome" code_block="unlit" render_state="unlit" }
			]}
			{ if: "defined(LAYER_HDR_TRANSPARENT)" then: [
				{ layer="hdr_transparent" code_block="unlit" render_state="unlit" }
			]}

			{ if: "defined(LAYER_TRANSPARENT)" then: [
				{ layer="transparent" code_block="unlit" render_state="unlit" }
			] else: [
				{ if: "!on_renderer(GL)" then: [
					{ layer="wireframe" code_block="unlit" define="DRAW_WIREFRAME" render_state="wireframe" branch_key="dev_wireframe" }
				]}
			]}
		]
	}
}

code_blocks = {
	macros = {
		code = {
			shared = """
				#define TAA_GUI_DEPTH_BIAS_RANGE 50.0 // The [0, TAA_GUI_DEPTH_BIAS_RANGE] depth range for which we lerp the min-max depth biases for line drawing
				#define TAA_GUI_MIN_DEPTH_BIAS 0.001 // The depth offset to add for lines drawn at z = 0
				#define TAA_GUI_MAX_DEPTH_BIAS 0.05 // The depth offset to add for lines drawn at z >= GUI_DEPTH_BIAS_RANGE

				// We need to disable instancing for the material transfer context as it doesn't use the world transform.
				#if defined(INSTANCED) && defined(MATERIAL_TRANSFER)
					#undef INSTANCED
				#endif

				#if defined(PS_NEEDS_WP) || defined(NEEDS_EYE_VECTOR) || defined(HAS_VERTEX_OFFSET) || ((defined(RENDERER_D3D11) || defined(RENDERER_D3D12)) && defined(INSTANCED)) || defined(CAMERA_TRANSLATION_LOCK) || defined(BILLBOARD)
					#define NEEDS_WORLD_SPACE_POSITION
				#endif
			"""
		}
	}
	
	unlit = {
		include:[
			"core/stingray_renderer/shader_libraries/common#common",
			"core/stingray_renderer/shader_libraries/common#gbuffer_access",
			"core/stingray_renderer/shader_libraries/common#skinning",
			"core/stingray_renderer/shader_libraries/common#taa_offsets",
			"macros",
			"core/stingray_renderer/shader_libraries/common#billboard_transformation"]

		instance_data = {
			"on_renderer(D3D11, D3D12) && !defined(MATERIAL_TRANSFER) && defined(INSTANCED)": {
				world = { type = "matrix4x4" }
				"defined(MOTION_BLUR)": {
					last_world = { type = "matrix4x4" }
				}
				"defined(DRAW_WIREFRAME)": {
					dev_wireframe_color = { type = "vector4" }
				}
			}
		}

		samplers = {
			"defined(NEEDS_LINEAR_DEPTH)": {
				linear_depth = {
					sampler_state = "core/stingray_renderer/shader_libraries/common#clamp_point"
					source = "resource_set"
					slot_name = "linear_depth"
					type = "2d"
				}
			}
			"!defined(LOW_RES)": {
				"defined(LOW_RES_ENABLED)": {
					hdr_transparent_div4 = {
						sampler_state = "core/stingray_renderer/shader_libraries/common#clamp_linear"
						source = "resource_set"
						slot_name = "hdr_transparent_div4"
						type = "2d"
					}

					hdr_linear_depth_div4 = {
						sampler_state = "core/stingray_renderer/shader_libraries/common#clamp_linear"
						source = "resource_set"
						slot_name = "hdr_linear_depth_div4"
						type = "2d"
					}
				}
			}
		}

		code = {
			glsl = """				
				#if defined(STAGE_VERTEX)
					layout(location = POSITION0) in highp vec4 in_pos;
					
					CBUFFER_START(c_per_object)
						#if defined(NEEDS_WORLD_SPACE_POSITION)
							#if defined(CAMERA_TRANSLATION_LOCK)
								UNIFORM mat4 view;
								UNIFORM mat4 proj;
							#else
								UNIFORM mat4 view_proj;
							#endif
						#else
							UNIFORM mat4 world_view_proj;
						#endif
						UNIFORM mat4 world;
					CBUFFER_END
					
					void main()
					{
						GraphManualChannels params;
						GraphResults graph;
						
						// Write output channels
						#if defined(SKINNED)
							vec4 position = vec4(skin_point(in_pos, blendindices, blendweights), 1);
							mediump vec3 normal = skin_vector(GRAPH_DATA(vertex_normal), blendindices, blendweights);
							#if defined(NEEDS_TANGENT_SPACE)
								mediump vec3 tangent = skin_vector(GRAPH_DATA(vertex_tangent), blendindices, blendweights);
								mediump vec3 binormal = skin_vector(GRAPH_DATA(vertex_binormal), blendindices, blendweights);
							#endif
						#else
							vec4 position = in_pos;
							mediump vec3 normal = GRAPH_DATA(vertex_normal);
							#if defined(NEEDS_TANGENT_SPACE)
								mediump vec3 tangent = GRAPH_DATA(vertex_tangent);
								mediump vec3 binormal = GRAPH_DATA(vertex_binormal);
							#endif
						#endif

						#if defined(NEEDS_WORLD_SPACE_POSITION)
							vec4 wp = position * world;
				#endif

						GRAPH_PARAM(params, vertex_position) = position;

						#if defined(NEEDS_WORLD_SPACE_NORMAL)
							GRAPH_PARAM(params, world_space_normal) = normal * mat3(world);
						#endif

						#if defined(NEEDS_EYE_VECTOR)
							GRAPH_PARAM(params, eye_vector) = camera_pos - wp.rgb;
						#endif

						#if defined(NEEDS_TANGENT_SPACE)
							tspace_transform_transpose(
								GRAPH_PARAM(params, tsm0),
								GRAPH_PARAM(params, tsm1),
								GRAPH_PARAM(params, tsm2),
								tangent, binormal, normal,
								mat3(world));
						#endif

						// Evaluate all pieces of the graph that should run per-vertex.
						graph_evaluate(graph, params);

						vec4 p;
						#if defined(NEEDS_WORLD_SPACE_POSITION)
							#if defined(HAS_VERTEX_OFFSET)
								wp += vec4(graph.vertex_offset, 0);
							#endif

							#if defined(CAMERA_TRANSLATION_LOCK)
								view[0][3] = 0.0;
								view[1][3] = 0.0;
								view[2][3] = 0.0;
								p = (wp * view) * proj;
							#else
								p = wp * view_proj;
							#endif
						#else
							p = position * world_view_proj;
						#endif
						
						#if defined(PROJECT_TO_FAR_PLANE)
							p.z = p.w;
						#endif

						gl_Position = p;
					}				
				#elif defined(STAGE_FRAGMENT)
					layout(location = 0) out mediump vec4 out_color;
					
					void main()
					{
						#if defined(HAS_BASE_COLOR) || defined(HAS_OPACITY)
							GraphManualChannels params;
							GraphResults graph;
							graph_evaluate(graph, params);
						#endif

						vec3 color = vec3(0.5, 0.5, 0.5);
						#if defined(HAS_BASE_COLOR)
							color = graph.base_color;
						#endif

						float op = 1.0;
						#if defined(HAS_OPACITY)
							op = graph.opacity;
						#endif

						out_color = vec4(color.r, color.g, color.b, op);
					}
				#endif
			"""
			
			hlsl = """
				#if defined(NEEDS_LINEAR_DEPTH)
					DECLARE_SAMPLER_2D(linear_depth);
					#define HAS_LINEAR_DEPTH
				#endif

				#if !defined(LOW_RES) && defined(LOW_RES_ENABLED)
					DECLARE_SAMPLER_2D(hdr_transparent_div4);
					DECLARE_SAMPLER_2D(hdr_linear_depth_div4);
				#endif

				#if defined(NEEDS_PIXEL_DEPTH) || (!defined(LOW_RES) && defined(LOW_RES_ENABLED))
					#define PS_NEEDS_WP
				#endif

				#if defined(PS_NEEDS_WP)
					#define NEEDS_WORLD_SPACE_POSITION
				#endif

				struct VS_INPUT {
					float4 position : POSITION;
					SKIN_INPUT
					GRAPH_VERTEX_INPUT
				};

				struct PS_INPUT {
					#if (defined(RENDERER_D3D11) || defined(RENDERER_D3D12)) && defined(INSTANCED) && defined(DRAW_WIREFRAME)
						float4 instance_wireframe_color : COLOR0;
					#endif
					float4 position : SV_POSITION;
					#if defined(PS_NEEDS_WP)
						float3 world_pos : TEXCOORD15;
					#endif
					GRAPH_PIXEL_INPUT
				};

				CBUFFER_START(c_per_object)
					#if defined(NEEDS_WORLD_SPACE_POSITION)
						#if defined(CAMERA_TRANSLATION_LOCK)
							float4x4 view;
							float4x4 proj;
						#else
							float4x4 view_proj;
						#endif
					#else
						float4x4 world_view_proj;
					#endif
					#if defined(BILLBOARD) && defined(LAYER_SKYDOME_BILLBOARD)
						#if defined(SECONDARY_SUN_DIRECTION)
							float3 secondary_sun_direction;
							#define billboard_direction secondary_sun_direction
						#else
							float3 sun_direction;
							#define billboard_direction sun_direction
						#endif
					#endif
					float4x4 world;
					float4x4 last_world;
					float4 dev_wireframe_color;
					GRAPH_MATERIAL_EXPORTS
				CBUFFER_END

				#if defined(INSTANCED) && (defined(RENDERER_D3D11) || defined(RENDERER_D3D12))
					Buffer<float4> idata;
					float ioffset;
				#endif

				DEFAULT_ROOT_SIGNATURE_ATTRIBUTE
				PS_INPUT vs_main(VS_INPUT input
					#if defined(INSTANCED) && (defined(RENDERER_D3D11) || defined(RENDERER_D3D12))
						, uint instance_id : SV_InstanceId
					#endif
					)
				{
					PS_INPUT o;
					float4 p;

					GraphVertexParams params;
					GraphVertexResults results;

					#if defined(INSTANCED) && (defined(RENDERER_D3D11) || defined(RENDERER_D3D12))
						uint offset = (uint)ioffset + instance_id*IDATA_STRIDE;
						world[0] = idata.Load(offset + IDATA_world + 0);
						world[1] = idata.Load(offset + IDATA_world + 1);
						world[2] = idata.Load(offset + IDATA_world + 2);
						world[3] = idata.Load(offset + IDATA_world + 3);

						#if defined(MOTION_BLUR)
							last_world[0] = idata.Load(offset + IDATA_last_world + 0);
							last_world[1] = idata.Load(offset + IDATA_last_world + 1);
							last_world[2] = idata.Load(offset + IDATA_last_world + 2);
							last_world[3] = idata.Load(offset + IDATA_last_world + 3);
						#endif

						#if defined(DRAW_WIREFRAME)
							o.instance_wireframe_color = idata.Load(offset + (instance_id*IDATA_STRIDE + IDATA_dev_wireframe_color));
						#endif
					#endif

					// Write automatic params
					GRAPH_VERTEX_WRITE_PARAMS(params, input);

					// Write output channels
					#if defined(SKINNED)
						float4 position = float4(skin_point(input.position, input.blendindices, input.blendweights), 1);
						#if defined(MOTION_BLUR)
							float4 last_position = float4(skin_point_last_frame(input.position, input.blendindices, input.blendweights), 1);
						#endif
						#if !defined(BILLBOARD)
							#if (defined(NEEDS_WORLD_SPACE_NORMAL) || defined(NEEDS_TANGENT_SPACE))
								float3 normal = skin_vector(GRAPH_VERTEX_DATA(input, vertex_normal).xyz, input.blendindices, input.blendweights);
							#endif
							#if defined(NEEDS_TANGENT_SPACE)
								float3 tangent = skin_vector(GRAPH_VERTEX_DATA(input, vertex_tangent).xyz, input.blendindices, input.blendweights);
								float3 binormal = skin_vector(GRAPH_VERTEX_DATA(input, vertex_binormal).xyz, input.blendindices, input.blendweights);
							#endif
						#endif
					#else
						float4 position = input.position;
						#if defined(MOTION_BLUR)
							float4 last_position = position;
						#endif
						#if !defined(BILLBOARD)
							#if (defined(NEEDS_WORLD_SPACE_NORMAL) || defined(NEEDS_TANGENT_SPACE))
								float3 normal = GRAPH_VERTEX_DATA(input, vertex_normal).xyz;
							#endif
							#if defined(NEEDS_TANGENT_SPACE)
								float3 tangent = GRAPH_VERTEX_DATA(input, vertex_tangent).xyz;
								float3 binormal = GRAPH_VERTEX_DATA(input, vertex_binormal).xyz;
							#endif
						#endif
					#endif

					#if defined(BILLBOARD)
						float4 wp;
						float3 normal, tangent, binormal;
						#if !defined(LAYER_SKYDOME_BILLBOARD)
							get_billboard_data_from_position(world._m30_m31_m32, camera_world._m30_m31_m32, camera_view, position, wp, normal, tangent, binormal);
						#else
							get_billboard_data_from_direction(billboard_direction, position, wp, normal, tangent, binormal);
						#endif
					#elif defined(NEEDS_WORLD_SPACE_POSITION)
						float4 wp = mul(position, world);
					#endif

					GRAPH_VERTEX_PARAM(params, vertex_position) = position;

					#if defined(NEEDS_WORLD_SPACE_NORMAL)
						GRAPH_VERTEX_PARAM(params, world_space_normal).rgb = mul(normal, (float3x3)world);
					#endif

					#if defined(NEEDS_EYE_VECTOR)
						#if defined(BILLBOARD) && defined(LAYER_SKYDOME_BILLBOARD)
							// TODO: not correct length, we can't use length(eye_vector) to determine the distance
							GRAPH_VERTEX_PARAM(params, eye_vector).rgb = billboard_direction;
						#else
							GRAPH_VERTEX_PARAM(params, eye_vector).rgb = camera_pos - wp.rgb;
						#endif
					#endif

					#if defined(NEEDS_TANGENT_SPACE)
						tspace_transform_transpose(
							GRAPH_VERTEX_PARAM(params, tsm0),
							GRAPH_VERTEX_PARAM(params, tsm1),
							GRAPH_VERTEX_PARAM(params, tsm2),
							tangent, binormal, normal,
							(float3x3)world);
					#endif

					#if defined(MOTION_BLUR)
						GRAPH_VERTEX_PARAM(params, last_clip_position) = float3(0.0, 0.0, 0.0);

						#if defined(BILLBOARD)
							float4 cur_wp = wp;
							float4 last_wp;
							#if !defined(LAYER_SKYDOME_BILLBOARD)
								get_billboard_positions_from_position(last_world._m30_m31_m32, camera_last_world._m30_m31_m32, camera_last_view, last_position, last_wp);
							#else
								get_billboard_positions_from_direction(billboard_direction, last_position, last_wp);
							#endif
						#else
							float4 cur_wp = mul(position, world);
							float4 last_wp = mul(last_position, last_world);
						#endif
						if(length(cur_wp - last_wp) > 0.0) {
							float4 last_clip_pos = mul(last_wp, camera_last_view_projection);
							GRAPH_VERTEX_PARAM(params, last_clip_position) = last_clip_pos.xyw;
						}
					#endif

					// Evaluate all pieces of the graph that should run per-vertex.
					GRAPH_EVALUATE_VERTEX(results, params);

					#if defined(NEEDS_WORLD_SPACE_POSITION)
						#if defined(HAS_VERTEX_OFFSET)
							wp += float4(results.vertex_offset, 0);
						#endif

						#if defined(CAMERA_TRANSLATION_LOCK)
							view._m30_m31_m32 = float3(0,0,0);
							p = mul(mul(wp, view), proj);
						#else
							#if defined(HAS_CUSTOM_FOV)
								p = mul(wp, camera_custom_fov_view_projection);
							#else
								p = mul(wp, view_proj);
							#endif
						#endif
					#else
						#if defined(HAS_CUSTOM_FOV)
							// TODO: create camera_custom_fov_world_view_projection?
							p = mul(mul(position, world), camera_custom_fov_view_projection); 
						#else
							p = mul(position, world_view_proj);
						#endif
					#endif

					#if defined(MATERIAL_TRANSFER)
						float2 unwrapped_uv = GRAPH_VERTEX_DATA(input, lightmap_uv);
						float2 ndc = float2(unwrapped_uv.x, unwrapped_uv.y) * 2 - 1;
						ndc.y *= -1;
						p = float4(ndc, 0, 1);
					#endif
					
					#if defined(PROJECT_TO_FAR_PLANE)
						p.z = p.w;
					#endif

					#if defined(LAYER_TRANSPARENT) && !defined(DEPTH_TEST_DISABLED)
						p.z -= lerp(TAA_GUI_MIN_DEPTH_BIAS, TAA_GUI_MAX_DEPTH_BIAS, saturate((o.position.z / o.position.w) / TAA_GUI_DEPTH_BIAS_RANGE)) * taa_enabled;
					#endif

					#if defined(PS_NEEDS_WP)
						o.world_pos = wp.xyz;
					#endif

					#if defined(DRAW_WIREFRAME) || defined(MATERIAL_TRANSFER) || defined(LAYER_TRANSPARENT)
						o.position = p;
					#else
						float4 view_space = p / p.w;
						view_space.xy += get_vs_halton_offset(frame_number);
						o.position = view_space * p.w;
					#endif					

					// Write results
					GRAPH_VERTEX_WRITE(o, results, params);

					return o;
				}

				#if defined(DRAW_WIREFRAME)
					DEFAULT_ROOT_SIGNATURE_ATTRIBUTE
					float4 ps_main(PS_INPUT input) : SV_TARGET0
					{
						#if (defined(RENDERER_D3D11) || defined(RENDERER_D3D12)) && defined(INSTANCED)
							return input.instance_wireframe_color;
						#else
							return dev_wireframe_color;
						#endif
					}
				#else
					DEFAULT_ROOT_SIGNATURE_ATTRIBUTE
					float4 ps_main(PS_INPUT input) : SV_TARGET0
					{
						#if defined(NEEDS_PIXEL_DEPTH) || (!defined(LOW_RES) && defined(LOW_RES_ENABLED))
							const float3 world_pos = input.world_pos;
							const float3 view_dir = camera_world._m30_m31_m32 - world_pos;
							const float3 camera_dir = camera_world._m10_m11_m12;
							const float depth = dot(-view_dir, camera_dir);
						#endif

						#if defined(HAS_BASE_COLOR) || defined(HAS_OPACITY) || defined(HAS_ADDITIVE)
							GraphPixelParams params;
							GraphPixelResults graph;

							GRAPH_PIXEL_WRITE_PARAMS(params, input);

							#if defined(NEEDS_PIXEL_DEPTH)
								GRAPH_PIXEL_PARAM(params, pixel_depth) = depth;
							#endif

							#if defined(NEEDS_SCREEN_POS)
								float2 screen_pos = (input.position.xy / back_buffer_size);
								GRAPH_PIXEL_PARAM(params, screen_pos) = screen_pos;
							#endif

							GRAPH_EVALUATE_PIXEL(graph, params);
						#endif

						float3 color = float3(0.5, 0.5, 0.5);
						#if defined(HAS_BASE_COLOR)
							color = graph.base_color;
						#endif

						float op = 1.f;
						#if defined(HAS_OPACITY)
							op = graph.opacity;
						#endif

						#if !defined(LOW_RES) && defined(LOW_RES_ENABLED)
							float2 screen_uv = input.position.xy / back_buffer_size;

							// Fade out high resolution particle if the low resolution particles is infront of the high resolution particle
							float2 particle_depth_values = TEX2D(hdr_linear_depth_div4, screen_uv).rg;
							float depth_mean = particle_depth_values.x;
							float depth_variance = particle_depth_values.y - depth_mean*depth_mean;
							float background_depth = depth;
							
							float diff = max(background_depth - depth_mean, 0.0);
							float C = 1.38629436112; // 2 * ln(2)
							float T = exp2(-diff*diff / (C * max(depth_variance, 0.001)));
							float alpha_modifier = TEX2D(hdr_transparent_div4, screen_uv).a * (1.0 - T);
							op *= 1.0 - alpha_modifier;
						#endif

						#ifdef LAYER_SKYDOME
							return float4(color, 1.0);
						#else
							#if defined(HAS_ADDITIVE)
								return float4(color * op, op * (1.0 - saturate(graph.additive)));
							#else
								return float4(color * op, op);
							#endif
						#endif
					}
				#endif
			"""
		}
	}
}
