From 4251f7a374841582a51df59cf0f38a89b65407c8 Mon Sep 17 00:00:00 2001 From: andyoneal Date: Thu, 9 Mar 2023 19:46:52 -0600 Subject: [PATCH] reduce size of shell array properties --- CustomShaderDesc.cs | 10 +- CustomShaderManager.cs | 28 +- Patch_DysonShell.cs | 17 + README.md | 9 +- SphereOpt.cs | 23 +- SphereOpt.csproj | 5 +- shaders/Dyson Shell Unlit REPLACE-Huge.shader | 751 ++++++++++++++++++ .../Dyson Shell Unlit REPLACE-Large.shader | 751 ++++++++++++++++++ .../Dyson Shell Unlit REPLACE-Small.shader | 751 ++++++++++++++++++ thunderstore/dysonopt.png | Bin 0 -> 142860 bytes thunderstore/manifest.json | 9 + 11 files changed, 2327 insertions(+), 27 deletions(-) create mode 100644 Patch_DysonShell.cs create mode 100644 shaders/Dyson Shell Unlit REPLACE-Huge.shader create mode 100644 shaders/Dyson Shell Unlit REPLACE-Large.shader create mode 100644 shaders/Dyson Shell Unlit REPLACE-Small.shader create mode 100644 thunderstore/dysonopt.png create mode 100644 thunderstore/manifest.json diff --git a/CustomShaderDesc.cs b/CustomShaderDesc.cs index 98784a8..49c9c19 100644 --- a/CustomShaderDesc.cs +++ b/CustomShaderDesc.cs @@ -7,14 +7,12 @@ public class CustomShaderDesc public readonly string shortName; public readonly Shader shader; public readonly string shaderName; - public readonly string replacementForShader; - public CustomShaderDesc (string shortName, string shaderToReplace, string replacementShader) + public CustomShaderDesc (string shortName, string customShaderName) { - shader = CustomShaderManager.GetShader(replacementShader); - if (shader == null) SphereOpt.logger.LogError($"Could not find shader for name: {replacementShader}"); - shaderName = replacementShader; - replacementForShader = shaderToReplace; + shader = CustomShaderManager.GetShader(customShaderName); + if (shader == null) SphereOpt.logger.LogError($"Could not find shader for name: {customShaderName}"); + shaderName = customShaderName; this.shortName = shortName; } } \ No newline at end of file diff --git a/CustomShaderManager.cs b/CustomShaderManager.cs index 443b087..e1dcfe6 100644 --- a/CustomShaderManager.cs +++ b/CustomShaderManager.cs @@ -12,7 +12,7 @@ public static class CustomShaderManager private static readonly List bundleShaders = new(); private static readonly List customShaderDescs = new(); private static readonly Dictionary shortNameMap = new(); - private static readonly Dictionary replacementForShaderMap = new(); + private static readonly Dictionary autoReplaceShaderMap = new(); private static readonly Dictionary> shaderReplacedOnMaterialsMap = new(); public static void InitWithBundle(string bundleFileName) @@ -66,23 +66,17 @@ private static bool LoadShadersFromBundle() return true; } - public static void AddCustomShaderDesc(string shortName, string shaderToReplace, string replacementShader) + public static void AddCustomShaderDesc(string shortName, string shaderName, string alwaysReplaceShaderName = null) { - CustomShaderDesc shaderDesc = new(shortName, shaderToReplace, replacementShader); + CustomShaderDesc shaderDesc = new(shortName, shaderName); customShaderDescs.Add(shaderDesc); - replacementForShaderMap.Add(shaderDesc.replacementForShader, shaderDesc); + if(alwaysReplaceShaderName != null) autoReplaceShaderMap.Add(alwaysReplaceShaderName, shaderDesc); shortNameMap.Add(shaderDesc.shortName, shaderDesc); - - } - - public static CustomShaderDesc LookupReplacementShaderFor(string originalShaderName) - { - return replacementForShaderMap.TryGetValue(originalShaderName, out var customShader) ? customShader : null; } public static bool ReplaceShaderIfAvailable(Material mat) { - if (replacementForShaderMap.TryGetValue(mat.shader.name, out var customShaderDesc)) + if (autoReplaceShaderMap.TryGetValue(mat.shader.name, out var customShaderDesc)) { SphereOpt.logger.LogInfo($"replacing shader on: {mat.name}"); ApplyCustomShaderToMaterial(mat, customShaderDesc); @@ -102,7 +96,17 @@ public static Shader GetShader (string customShaderName) return null; } - public static void ApplyCustomShaderToMaterial(Material mat, CustomShaderDesc replacementShader) + public static void ApplyCustomShaderToMaterial(Material mat, string shortName) + { + if (!shortNameMap.TryGetValue(shortName, out var customShaderDesc)) + { + SphereOpt.logger.LogWarning($"Couldn't find a CustomShaderDesc with shortname: {shortName}"); + return; + } + ApplyCustomShaderToMaterial(mat, customShaderDesc); + } + + private static void ApplyCustomShaderToMaterial(Material mat, CustomShaderDesc replacementShader) { mat.shader = replacementShader.shader; diff --git a/Patch_DysonShell.cs b/Patch_DysonShell.cs new file mode 100644 index 0000000..c9ebc8b --- /dev/null +++ b/Patch_DysonShell.cs @@ -0,0 +1,17 @@ +using HarmonyLib; + +namespace SphereOpt; + +internal class Patch_DysonShell +{ + [HarmonyPatch(typeof(DysonShell), "SetProtoId")] + [HarmonyPostfix] + static void DysonShell_SetProtoId(DysonShell __instance) + { + var arraySizeNeeded = __instance.polygon.Count * 3; + if (arraySizeNeeded > 256) CustomShaderManager.ApplyCustomShaderToMaterial(__instance.material, "dysonshell-max"); + else if (arraySizeNeeded > 128) CustomShaderManager.ApplyCustomShaderToMaterial(__instance.material, "dysonshell-huge"); + else if (arraySizeNeeded > 16) CustomShaderManager.ApplyCustomShaderToMaterial(__instance.material, "dysonshell-large"); + else CustomShaderManager.ApplyCustomShaderToMaterial(__instance.material, "dysonshell-small"); + } +} \ No newline at end of file diff --git a/README.md b/README.md index cd71dc1..120b678 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # SphereOpt -Replaces the shader used by Dyson Shells. -Currently has no effect to performance or visuals in-game, and might even make both worse. \ No newline at end of file +**SphereOpt v0.5.0 should be considered a "beta" release. The worst you should is experience is errors or graphical glitches, in which case you can uninstall the mod. Please report any issues you encounter.** + +Improves rendering of Dyson Shells by drastically reducing the amount of data sent to the gpu per shell. Impact is larger depending on the number of shells in your Dyson Sphere(s). + +In a new game with a large and densely packed sphere containing 5,240 shells, framerate increased from 18fps with [DSPOptimizations](https://dsp.thunderstore.io/package/Selsion/DSPOptimizations/) alone to 40fps with SphereOpt. + +[DSPOptimizations](https://dsp.thunderstore.io/package/Selsion/DSPOptimizations/) is not required, but I don't know why you wouldn't use it if you're interested in this mod. \ No newline at end of file diff --git a/SphereOpt.cs b/SphereOpt.cs index 995d045..7d98c02 100644 --- a/SphereOpt.cs +++ b/SphereOpt.cs @@ -36,18 +36,31 @@ private static AssetBundle Bundle } private void Awake() { - // Plugin startup logic logger = Logger; - logger.LogInfo($"Plugin {PluginInfo.PLUGIN_GUID} is loaded!"); CustomShaderManager.InitWithBundle(Bundle); CustomShaderManager.AddCustomShaderDesc( - "dysonshell", - "VF Shaders/Dyson Sphere/Dyson Shell Unlit", + "dysonshell-max", "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE" ); - Harmony.CreateAndPatchAll(typeof(Patch_VFPreload)); + CustomShaderManager.AddCustomShaderDesc( + "dysonshell-small", + "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Small" + ); + + CustomShaderManager.AddCustomShaderDesc( + "dysonshell-large", + "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Large" + ); + + CustomShaderManager.AddCustomShaderDesc( + "dysonshell-huge", + "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Huge" + ); + + //Harmony.CreateAndPatchAll(typeof(Patch_VFPreload)); + Harmony.CreateAndPatchAll(typeof(Patch_DysonShell)); } } \ No newline at end of file diff --git a/SphereOpt.csproj b/SphereOpt.csproj index 8ec7a5c..f01263e 100644 --- a/SphereOpt.csproj +++ b/SphereOpt.csproj @@ -1,12 +1,13 @@ - + net472 SphereOpt Optimize Dyson Sphere rendering - 1.0.0 + 0.5.0 true latest + x64 diff --git a/shaders/Dyson Shell Unlit REPLACE-Huge.shader b/shaders/Dyson Shell Unlit REPLACE-Huge.shader new file mode 100644 index 0000000..9370b6a --- /dev/null +++ b/shaders/Dyson Shell Unlit REPLACE-Huge.shader @@ -0,0 +1,751 @@ +Shader "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Huge" { + Properties { + _Color ("Color", Vector) = (1,1,1,1) + _MainTex ("Albedo (RGB)", 2D) = "white" {} + _NormalTex ("Normal Map", 2D) = "bump" {} + _MSTex ("Metallic Smoothness (RA)", 2D) = "white" {} + _EmissionTex ("Emission (RGB)", 2D) = "black" {} + _EmissionTex2 ("Emission Large (RGB)", 2D) = "black" {} + _NoiseTex ("Noise Texture (R)", 2D) = "gray" {} + _ColorControlTex ("Color Control", 2D) = "black" {} + _ColorControlTex2 ("Color Control Large", 2D) = "black" {} + _AlbedoMultiplier ("漫反射倍率", Float) = 1 + _NormalMultiplier ("法线倍率", Float) = 1 + _EmissionMultiplier ("自发光倍率", Float) = 5.5 + _CellSize ("细胞大小(是否有间隙)", Float) = 1 + } + SubShader { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Pass { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Cull Off + Stencil { + CompFront Always + PassFront Replace + FailFront Keep + ZFailFront Keep + } + GpuProgramID 41389 + CGPROGRAM + #pragma vertex vert + #pragma geometry geom + #pragma fragment frag + #include "UnityCG.cginc" + #pragma target 5.0 + //#pragma enable_d3d11_debug_symbols + + struct v2g + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + //x [0,3] node index + //y [0,1] vert# / total#verts + float2 uv2 : TEXCOORD1; //u1.x is unused? + //x [0 or 1] (!s_outvmap.ContainsKey(item.Key)) ? 1 : 0) + //y [0,2] polygon index - which edge it is closest to? + float2 uv3 : TEXCOORD2; //axial coordinates on a grid of hexagons + }; + + struct g2f + { + float4 vertex : SV_POSITION; + float4 vertPos_axialCoords : TEXCOORD0; + float3 objectPos : TEXCOORD1; + float3 worldPos : TEXCOORD2; + float3 tangent : TEXCOORD3; + float3 binormal : TEXCOORD4; + float3 normal : TEXCOORD5; + float4 screenPos : TEXCOORD6; + float2 polyGroup_pctComplete : TEXCOORD7; + float4 color : TEXCOORD8; + }; + + struct fout + { + float4 sv_target : SV_Target0; + }; + + float4 _SunColor; + float4 _DysonEmission; + float3 _Global_DS_SunPosition; + float3 _Global_DS_SunPosition_Map; + int _Global_IsMenuDemo; + int _Global_DS_RenderPlace; // -1=Demo, 0=In-Game (Universe), 1=StarMap, or 2=DysonMap + int _Global_DS_HideFarSide; + int _Global_DS_PaintingLayerId; + int _Global_DS_PaintingGridMode; + float _Global_VMapEnabled; //(always 1f if gameData != null) + float _CellSize; ////always 1 except dyson-shell-unlit-0 which is 0.94 + int _Color32Int; + float _AlbedoMultiplier; + float _NormalMultiplier; + float _EmissionMultiplier; + float _State; // bitfield for selection/tool state + int _LayerId; + float _Radius; //Radius of dyson sphere + float _Scale; //(int)(Math.Pow(radius / 4000.0, 0.75) + 0.5); //4000 radius = 1. + float _GridSize; //_Scale * 80 + float4 _Center; //Center of the shell that this point is a member of. + // xaxis = normalize(cross(normalize(_Center), vector3.up)) + // yaxis = normalize(cross(xaxis, normalize(_Center))) + // t0axis = yaxis * _GridSize * rsqrt(3); + // t1axis = yaxis * _GridSize * rsqrt(3) * 0.5 - xaxis * _GridSize * 0.5; + // t2axis = yaxis * _GridSize * rsqrt(3) * 0.5 + xaxis * _GridSize * 0.5; + float3 _t0Axis; //in an axial coordinate system, the "q" axis. relative to center of shell. + float3 _t1Axis; //in an axial coordinate system, the "r" axis. relative to center of shell. + float3 _t2Axis; //in an axial coordinate system, the "s" axis. relative to center of shell. + float _PolyCount; //number of nodes that make of the shape of this shell + float _Clockwise; + float _NodeProgressArr[256]; + float4 _PolygonArr[256]; // points that make up the shape of the polygon. repeated PolyCount times. + float4 _PolygonNArr[256]; // normals + sampler2D _NoiseTex; + sampler2D _MainTex; + sampler2D _NormalTex; + sampler2D _MSTex; + sampler2D _EmissionTex; + sampler2D _EmissionTex2; + sampler2D _ColorControlTex; + sampler2D _ColorControlTex2; + + v2g vert(appdata_full v) + { + v2g o; + + o.vertex.xyzw = v.vertex.xyzw; + o.uv.xy = v.texcoord.xy; + o.uv2.xy = v.texcoord1.xy; + o.uv3.xy = v.texcoord2.xy; + + return o; + } + + [maxvertexcount(12)] + void geom(point v2g input[1], inout TriangleStream triStream) + { + g2f o; + + uint nodeIndex = (uint)input[0].uv.x; + float vertFillOrder = input[0].uv.y; //sorted by which vert should appear first, if this is vert 3 of 8, vertFillOrder = (3/8) = 0.375. + float pctNodeComplete = _NodeProgressArr[nodeIndex]; + float weighted_vertFillOrder = pow(vertFillOrder, 1.25); //fill early verts a little faster than later verts + uint renderPlace = asuint(_Global_DS_RenderPlace); + bool isDysonMap = renderPlace > 1.5; + + float hexPctComplete = saturate(pctNodeComplete + (_Scale/.28) * (pctNodeComplete - weighted_vertFillOrder)); + bool shouldRenderHex = hexPctComplete > 0.0001; + + if (isDysonMap || shouldRenderHex) { // Always render in DysonMap + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + + float triangleVertPos = (1.0 / 3.0) * _Scale; + float3 normal = normalize(mul((float3x3)unity_ObjectToWorld, input[0].vertex.xyz)); + + float3 worldMidPtPos = mul(unity_ObjectToWorld, input[0].vertex.xyz); + float scaleGridFactor = min(1.0, (min(1.0, 30.0 * saturate((length(worldMidPtPos) / (_GridSize * 18.0)) - 0.5)) * 0.07 + 1) - min(0.1, 0.2 / _Scale)) * saturate(length(worldMidPtPos) / (_GridSize * 1.5)); + + float distFromCam = length(_WorldSpaceCameraPos.xyz - input[0].vertex.xyz); + float cellSizeFalloff = 1.0 - saturate(distFromCam / 40000.0 - 0.075); + + float AngleCenterToPoint = dot(normalize(_Center.xyz), normalize(input[0].vertex.xyz)); + + AngleCenterToPoint = isDysonMap ? AngleCenterToPoint : AngleCenterToPoint * scaleGridFactor; + + float centerToEdgeLength = AngleCenterToPoint * lerp(1.0, _CellSize, cellSizeFalloff); + + float3 t0_up_pos = normalize(input[0].vertex.xyz + _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_up_pos = normalize(input[0].vertex.xyz + _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_up_pos = normalize(input[0].vertex.xyz + _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 t0_down_pos = normalize(input[0].vertex.xyz - _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_down_pos = normalize(input[0].vertex.xyz - _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_down_pos = normalize(input[0].vertex.xyz - _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 midPtPos = input[0].vertex.xyz; + + if (isDysonOrStarMap) { // not demoscene and not ingame, so starmap and dysonmap + t0_up_pos.xyz = t0_up_pos.xyz / 4000.0; + t1_up_pos.xyz = t1_up_pos.xyz / 4000.0; + t2_up_pos.xyz = t2_up_pos.xyz / 4000.0; + t0_down_pos.xyz = t0_down_pos.xyz / 4000.0; + t1_down_pos.xyz = t1_down_pos.xyz / 4000.0; + t2_down_pos.xyz = t2_down_pos.xyz / 4000.0; + midPtPos.xyz = midPtPos.xyz / 4000.0; + } + + float3 worldTangent = normalize(mul(unity_ObjectToWorld, t1_down_pos.xyz - t1_up_pos.xyz)); + float3 worldBinormal = normalize(mul(unity_ObjectToWorld, t0_up_pos.xyz - t0_down_pos.xyz)); + + //unpack and convert gamma to linear color + float4 gamma_color = float4(asuint(_Color32Int) & 255, (asuint(_Color32Int) >> 8) & 255, (asuint(_Color32Int) >> 16) & 255, (asuint(_Color32Int) >> 24) & 255) * (1.0f / 255); //asuint(_Color32Int)? + float4 linear_color = pow((gamma_color.xyzw + 0.055F)/1.055F, 2.4F); //GammaToLinearSpaceExact + + float4 worldPos = mul(unity_ObjectToWorld, float4(t0_up_pos.xyz, 1.0)); + float3 ray = worldPos.xyz - _WorldSpaceCameraPos.xyz; + float3 adjustedRay = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + float3 objPos = mul(unity_WorldToObject, worldPos.xyzw); + float3 t0up_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + float3 final_objpos = isInGame ? objPos.xyz : t0_up_pos.xyz; + + float4 t0up_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 t0up_screenPos = ComputeScreenPos(t0up_clipPos); + + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + //midPtPos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(midPtPos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 center_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : midPtPos.xyz; + + float4 center_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 center_screenPos = ComputeScreenPos(center_clipPos); + + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + + //t1_up_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_up_pos.xyz; + + float4 clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + + triStream.Append(o); + + // t2_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t2_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t0_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t0_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t1_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t1_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_up_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + //t2_up_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_up_pos + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + } + return; + } + + fout frag(g2f i) + { + + fout o; + const float4 icb[16] = { + float4(16.0, 0.0, 0.0, 0.0), + float4(8.0, 0.0, 0.0, 0.0), + float4(14.0, 0.0, 0.0, 0.0), + float4(6.0, 0.0, 0.0, 0.0), + float4(4.0, 0.0, 0.0, 0.0), + float4(12.0, 0.0, 0.0, 0.0), + float4(2.0, 0.0, 0.0, 0.0), + float4(10.0, 0.0, 0.0, 0.0), + float4(13.0, 0.0, 0.0, 0.0), + float4(5.0, 0.0, 0.0, 0.0), + float4(15.0, 0.0, 0.0, 0.0), + float4(7.0, 0.0, 0.0, 0.0), + float4(1.0, 0.0, 0.0, 0.0), + float4(9.0, 0.0, 0.0, 0.0), + float4(3.0, 0.0, 0.0, 0.0), + float4(11.0, 0.0, 0.0, 0.0) + }; + + float2 triangleVertPos = i.vertPos_axialCoords.xy; + float2 axialCoords = i.vertPos_axialCoords.zw; + int polygonGroup = (int)((uint)(0.5 + i.polyGroup_pctComplete.x)); + float hexPctComplete = i.polyGroup_pctComplete.y; + + uint renderPlace = asuint(_Global_DS_RenderPlace); + + bool isDysonMap = renderPlace > 1.5; + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + bool isMenuDemo = 0.5 < asuint(_Global_IsMenuDemo); + + if ((int)(asint(_Global_DS_PaintingLayerId) != asint(_LayerId)) | (int)(asuint(_Global_DS_PaintingGridMode) > 0.5) ? asuint(_Global_DS_PaintingLayerId) > 0 ? isDysonMap : 0 : 0 != 0) discard; + + float3 rayPosToCamera = _WorldSpaceCameraPos.xyz - i.worldPos.xyz; + + //if a ray from the the vert to the camera and a ray from the vert to the sun are pointing in the same direction, must be far side. + bool isFarSide = dot(rayPosToCamera, _Global_DS_SunPosition_Map.xyz - i.worldPos.xyz) > 0; + bool hideFarSideEnabled = asuint(_Global_DS_HideFarSide) > 0.5; + if (isDysonMap && hideFarSideEnabled && isFarSide) discard; + + /* remove pixels that fall outside the bounds of the frame that surrounds this shell */ + uint polyCount = (uint)(0.5 + _PolyCount) < 1 ? 1 : min(380, (uint)(0.5 + _PolyCount)); + int polygonIndex = (int)polyCount + (int)(0.5 + polygonGroup); + + float3 prevLineNormal = _PolygonNArr[polygonIndex - 1].xyz; + float3 prevLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex - 1].xyz; + + float3 thisLineDir = _PolygonArr[polygonIndex + 1].xyz - _PolygonArr[polygonIndex].xyz; + float3 thisLineNormal = _PolygonNArr[polygonIndex].xyz; + + float3 nextLineDir = _PolygonArr[polygonIndex + 2].xyz - _PolygonArr[polygonIndex + 1].xyz; + float3 nextLineNormal = _PolygonNArr[polygonIndex + 1].xyz; + float3 nextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 1].xyz; + + float3 nextnextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 2].xyz; + + + float prevLineIsConcave = dot(thisLineDir, prevLineNormal); + float nextLineIsConcave = dot(nextLineDir, thisLineNormal); + // <0 means convex + // >0 means concave + // 0 means parallel + int prevLineIsConvex = prevLineIsConcave > 0 ? 1 : prevLineIsConcave < 0 ? -1 : 0; + int nextLineIsConvex = nextLineIsConcave > 0 ? 1 : nextLineIsConcave < 0 ? -1 : 0; + //set to int, flip sign. 1=convex, -1=concave + + float prevLineInside = dot(prevLineToPoint, prevLineNormal); + float thisLineInside = dot(nextLineToPoint, thisLineNormal); + float nextLineInside = dot(nextnextLineToPoint, nextLineNormal); + // inside if >0, outside if <0 + + prevLineIsConvex *= _Clockwise; + nextLineIsConvex *= _Clockwise; + prevLineInside *= _Clockwise; + thisLineInside *= _Clockwise; + nextLineInside *= _Clockwise; + // flip sign if counterclockwise (_Clockwise = -1) + + float insideBounds = -1; + if (nextLineIsConvex > 0 && prevLineIsConvex > 0) { + if (nextLineInside > 0 && thisLineInside > 0 && prevLineInside > 0) { + insideBounds = 1; + } else { + insideBounds = -1; + } + } else { + if (nextLineIsConvex > 0 && prevLineIsConvex <= 0) { + insideBounds = nextLineInside > 0 && (prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } else { + if (nextLineIsConvex <= 0 && prevLineIsConvex > 0) { + insideBounds = prevLineInside > 0 && (thisLineInside > 0 || nextLineInside > 0) ? 1 : -1; + } else { + insideBounds = (nextLineInside > 0 || prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } + } + } + if (insideBounds < 0) discard; + /* end shell/frame bounds check */ + + + float distancePosToCamera = length(rayPosToCamera); + + float4 cubeCoords = _Scale * float4(0.666666687,0.333333343,-0.333333343,0.333333343) * axialCoords.xxyy; + cubeCoords.xy = cubeCoords.yx + cubeCoords.wz; + + float gridFalloff = 0.99 - saturate((distancePosToCamera / _GridSize) / 15.0 - 0.2) * 0.03; + + float2 adjustPoint = triangleVertPos.yx * gridFalloff + cubeCoords.xy; + adjustPoint.xy = adjustPoint.yx * float2(2,2) - adjustPoint.xy; + float adjustPoint_z = -adjustPoint.x - adjustPoint.y; + float2 roundedAdjustPoint = round(adjustPoint.xy); + float roundedAdjustPoint_z = round(adjustPoint_z); + float2 roundedPointDiff = -roundedAdjustPoint.yx - round(adjustPoint_z); + adjustPoint.xy = roundedAdjustPoint.xy < adjustPoint.xy ? adjustPoint.xy - roundedAdjustPoint.xy : roundedAdjustPoint.xy - adjustPoint.xy; + adjustPoint_z = roundedAdjustPoint_z < adjustPoint_z ? adjustPoint_z - roundedAdjustPoint_z : roundedAdjustPoint_z - adjustPoint_z; + adjustPoint.xy = adjustPoint_z < adjustPoint.xy ? adjustPoint.yx < adjustPoint.xy : 0; + + float alternatePointY = adjustPoint.y ? roundedPointDiff.y : roundedAdjustPoint.y; + float2 correctedCoords = roundedAdjustPoint.x + roundedAdjustPoint.y + roundedAdjustPoint_z != 0.000000 ? (adjustPoint.xx ? float2(roundedPointDiff.x, roundedAdjustPoint.y) : float2(roundedAdjustPoint.x, alternatePointY)) : roundedAdjustPoint.xy; + + float2 randomSampleCoords = float2(0.001953125,0.001953125) * correctedCoords.xy; + float random_num = tex2Dlod(_NoiseTex, float4(randomSampleCoords.xy, 0, 0)).x; + + + int bitmask; + float cutOut = 0; + if (hexPctComplete - random_num * 0.999 < 0.00005) { + if (isDysonMap) { + float2 pixelPos = (_ScreenParams.xy * (i.screenPos.xy / i.screenPos.ww)); + pixelPos = (int2)pixelPos; + bitmask = ((~(-1 << 2)) << 2) & 0xffffffff; // 12 + cutOut = (((uint)pixelPos.x << 2) & bitmask) | ((uint)0 & ~bitmask); + bitmask = ((~(-1 << 2)) << 0) & 0xffffffff; // 3 + cutOut = (((uint)pixelPos.y << 0) & bitmask) | ((uint)cutOut & ~bitmask); + if (0.2499 - (icb[cutOut].x * 0.0588) < 0) discard; + cutOut = 1; + } else { + if (-1 != 0) discard; + cutOut = 0; + } + } else { + cutOut = 0; + } + + float2 triPosAdjusted; + triPosAdjusted.x = triangleVertPos.x / _Scale + (2.0 * axialCoords.x - axialCoords.y) / 3.0; + triPosAdjusted.y = triangleVertPos.y / _Scale + (axialCoords.x + axialCoords.y) / 3.0; + + float lodBias = min(4, max(0, log(0.0001 * distancePosToCamera))); + + float4 albedoTex = tex2Dbias(_MainTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + + float4 normalTex = tex2Dbias(_NormalTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + float3 unpackedNormal = UnpackNormal(normalTex); + + float2 msTex = tex2D(_MSTex, triangleVertPos.xy).xw; + + float3 emissionTex_A = tex2Dbias(_EmissionTex, float4(triangleVertPos.xy, 0, lodBias)).xyz; + float3 emissionTex_B = tex2Dbias(_EmissionTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).xyz; + + float3 emissionTex = lerp(emissionTex_A.xyz, emissionTex_B.xyz, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float3 emissionTexTwo = tex2Dbias(_EmissionTex2, float4(triPosAdjusted.xy, 0, lodBias)).xyz; + + float colorControlTex_A = tex2Dbias(_ColorControlTex, float4(triangleVertPos.xy, 0, lodBias)).x; + float colorControlTex_B = tex2Dbias(_ColorControlTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).x; + float colorControlTex = lerp(colorControlTex_A, colorControlTex_B, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float colorControlTexTwo = tex2Dbias(_ColorControlTex2, float4(triPosAdjusted.xy, 0, lodBias)).x; + + unpackedNormal.xy = (-1.5 * _NormalMultiplier) * unpackedNormal.xy; + float3 worldNormal = normalize(i.normal.xyz * unpackedNormal.z + i.tangent.xyz * unpackedNormal.x + i.binormal.xyz * unpackedNormal.y); + + float3 triPosNew; + triPosNew.x = 1.0 - abs(frac(0.5 * (0.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + triPosNew.y = 1.0 - abs(frac(0.5 * (0 + triPosAdjusted.y)) * 2.0 - 1.0); + triPosNew.z = 1.0 - abs(frac(0.5 * (1.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + + float2 newPosOne; + newPosOne.x = ((triPosNew.x + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosOne.y = (triPosNew.y - triPosNew.x) / sqrt(2); + + float2 newPosTwo; + newPosTwo.x = ((triPosNew.z + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosTwo.y = (triPosNew.y - triPosNew.z) / sqrt(2); + + float3 viewDir = normalize(rayPosToCamera); + bool viewingSunFacingSide = dot(i.normal.xyz, viewDir.xyz) < 0; + + float emissionAnim = saturate(30.0 * (0.05 - abs(length(newPosOne.xy) - frac(2.9 * _Time.x)))) * min(1, 5 * (1 - frac(2.9 * _Time.x))) + + saturate(30.0 * (0.05 - abs(length(newPosTwo.xy) - frac(_Time.x * 3.7 + 0.5)))) * min(1, 5 * (1 - frac(_Time.x * 3.7 + 0.5))); + emissionAnim = viewingSunFacingSide ? saturate((emissionTexTwo.y * 2 + emissionTex.y) * emissionAnim) : 0; + + float3 dysonEmission = viewingSunFacingSide ? _DysonEmission.xyz : float3(1,1,1); + float colorControl = saturate(colorControlTex + colorControlTexTwo); + float3 colorOutwardFacing = lerp(colorControl * i.color.xyz, i.color.xyz, 0.01 / _EmissionMultiplier); + float3 emissionOutwardFacing = lerp(emissionTexTwo.xyz * float3(0.3, 0.3, 0.3) + emissionTex.xyz, colorOutwardFacing, i.color.w); + float3 emissionSunFacing = float3(3,3,3) * (emissionTexTwo.x + emissionTex.x) * dysonEmission.xyz; + float3 emission = viewingSunFacingSide ? emissionSunFacing.xyz : emissionOutwardFacing.xyz; + + emission = _EmissionMultiplier * lerp(emission.xyz, dysonEmission.xyz, emissionAnim); + + float3 albedo = _AlbedoMultiplier * albedoTex.xyz * lerp(float3(1,1,1), albedoTex.xyz, saturate(1.25 * (albedoTex.w - 0.1))); + float specularStrength = dot(albedo, float3(0.3, 0.6, 0.1)); + + float scaledDistancePosToCamera = isMenuDemo ? distancePosToCamera : isDysonOrStarMap ? 3999.9998 * distancePosToCamera : distancePosToCamera; + float scaleMetallic = isMenuDemo ? 0.1 : isDysonOrStarMap ? 0.93 : 0.7; + scaleMetallic = saturate(pow(0.25 * log(scaledDistancePosToCamera + 1) - 1.5, 3.0)) * scaleMetallic; + float multiplyEmission = isDysonMap ? 2.2 : isDysonOrStarMap ? 1.8 : 2.5; + + float3 shellColor = i.color.w > 0.5 ? i.color.xyz : (asint(_Global_DS_PaintingLayerId) == asint(_LayerId) ? float3(0, 0.3, 0.65) : float3(0, 0.8, 0.6)); + float3 shellEmissionColor = lerp(emission.xyz * multiplyEmission, shellColor, 0.8 * cutOut); + + specularStrength = _State > 0.5 ? 0 : 0.8 * specularStrength * (1.0 - cutOut); + float fadeOut = _State > 0.5 ? 0 : 0.03 * (1.0 - cutOut); + float metallic = _State > 0.5 ? 0 : msTex.x * (1.0 - scaleMetallic); + float smoothness = _State > 0.5 ? 0.5 : min(0.8, msTex.y); + + float3 defaultColor = isDysonMap ? i.color.xyz * (viewingSunFacingSide ? 2 : 1.5) : float3(0,0,0); + float3 highStateColor = i.color.w > 0.5 ? defaultColor : float3(2.59, 0.0525, 0.0875); + float3 medStateColor = i.color.w > 0.5 ? defaultColor : float3(0.525,0.875, 3.5); + float3 lowStateColor = i.color.w > 0.5 ? defaultColor : float3(0.35, 0.7, 3.5); + float3 zeroStateColor = i.color.w > 0.5 ? defaultColor : float3(1.05, 1.05, 1.05); + float3 finalColor = 3.5 < _State ? highStateColor : + 2.5 < _State ? medStateColor : + 1.5 < _State ? lowStateColor : + 0.5 < _State ? zeroStateColor : + shellEmissionColor; + + float emissionFactor = (int)(_State > 0.5) | (int)(cutOut > 0.5) ? (1.0 / _EmissionMultiplier) : saturate(colorControlTex + colorControlTexTwo.x); + float metallicFactor = saturate(metallic * 0.85 + 0.149); + + float perceptualRoughness = min(1, 1 - smoothness * 0.97); + float roughness = perceptualRoughness * perceptualRoughness; + float roughnessSqr = roughness * roughness; + + float NdotV = viewingSunFacingSide ? -dot(worldNormal.xyz, viewDir.xyz) : dot(worldNormal.xyz, viewDir.xyz); + worldNormal.xyz = viewingSunFacingSide ? -worldNormal.xyz : worldNormal.xyz; + + float3 lightDir = -i.normal.xyz; + float3 halfDir = normalize(normalize(rayPosToCamera) + lightDir.xyz); + + float NdotL = dot(worldNormal.xyz, lightDir.xyz); + float NdotH = dot(worldNormal.xyz, halfDir.xyz); + float VdotH = dot(viewDir, halfDir.xyz); + float clamp_NdotL = max(0, NdotL); + float clamp_NdotH = max(0, NdotH); + float clamp_VdotH = max(0, VdotH); + + float D = 0.25 * pow(rcp(clamp_NdotH * clamp_NdotH * (roughnessSqr - 1) + 1),2) * roughnessSqr; + + float gv = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, NdotV); + float gl = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, clamp_NdotL); + float G = rcp(gv * gl); + + float fk = exp2((clamp_VdotH * -5.55472994 - 6.98316002) * clamp_VdotH); + float F = lerp(0.5 + metallicFactor, 1.0, fk); + + float sunStrength = isInGame ? pow(saturate(1.05 + dot(normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz), i.normal.xyz)), 0.4) : 1.0; + float3 sunColor = float3(1.5625,1.5625,1.5625) * _SunColor.xyz; + float intensity = saturate(pow(NdotL * 0.6 + 1, 3)); + float3 sunColorIntensity = float3(0.07, 0.07, 0.07) * _SunColor * (intensity * 1.5 + 1) * intensity; + float3 sunSpecular = sunColor.xyz * clamp_NdotL * specularStrength; + + float3 finalLight = lerp(1, specularStrength, metallicFactor) * fadeOut * sunColor.xyz * (F * D * G + (0.1 / UNITY_PI)) * clamp_NdotL; + finalLight = finalLight.xyz * lerp(metallicFactor, 1, specularStrength * 0.2); + finalLight = float3(5,5,5) * lerp(float3(1,1,1), _SunColor, float3(0.3,0.3,0.3)) * finalLight.xyz; + finalLight = (sunColorIntensity.xyz * specularStrength * (1 - metallicFactor * 0.6) + sunSpecular.xyz * pow(1 - metallicFactor, 0.6) + finalLight.xyz) * sunStrength; + + float finalStength = dot(finalLight, float3(0.3, 0.6, 0.1)); + float3 normalizedLight = finalLight / finalStength; + float megaLog = log(log(log(log(log(log(log(log(finalStength / 0.32) + 1) + 1) + 1) + 1) + 1) + 1) + 1) + 1; + finalLight = 0.32 < finalStength ? normalizedLight * megaLog * 0.32 : finalLight; + + float finalAlpha = _EmissionMultiplier * emissionFactor; + o.sv_target.xyzw = float4(finalColor, 0.0) + float4(finalLight, finalAlpha); + + return o; + } + ENDCG + } + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/shaders/Dyson Shell Unlit REPLACE-Large.shader b/shaders/Dyson Shell Unlit REPLACE-Large.shader new file mode 100644 index 0000000..ac7a007 --- /dev/null +++ b/shaders/Dyson Shell Unlit REPLACE-Large.shader @@ -0,0 +1,751 @@ +Shader "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Large" { + Properties { + _Color ("Color", Vector) = (1,1,1,1) + _MainTex ("Albedo (RGB)", 2D) = "white" {} + _NormalTex ("Normal Map", 2D) = "bump" {} + _MSTex ("Metallic Smoothness (RA)", 2D) = "white" {} + _EmissionTex ("Emission (RGB)", 2D) = "black" {} + _EmissionTex2 ("Emission Large (RGB)", 2D) = "black" {} + _NoiseTex ("Noise Texture (R)", 2D) = "gray" {} + _ColorControlTex ("Color Control", 2D) = "black" {} + _ColorControlTex2 ("Color Control Large", 2D) = "black" {} + _AlbedoMultiplier ("漫反射倍率", Float) = 1 + _NormalMultiplier ("法线倍率", Float) = 1 + _EmissionMultiplier ("自发光倍率", Float) = 5.5 + _CellSize ("细胞大小(是否有间隙)", Float) = 1 + } + SubShader { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Pass { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Cull Off + Stencil { + CompFront Always + PassFront Replace + FailFront Keep + ZFailFront Keep + } + GpuProgramID 41389 + CGPROGRAM + #pragma vertex vert + #pragma geometry geom + #pragma fragment frag + #include "UnityCG.cginc" + #pragma target 5.0 + //#pragma enable_d3d11_debug_symbols + + struct v2g + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + //x [0,3] node index + //y [0,1] vert# / total#verts + float2 uv2 : TEXCOORD1; //u1.x is unused? + //x [0 or 1] (!s_outvmap.ContainsKey(item.Key)) ? 1 : 0) + //y [0,2] polygon index - which edge it is closest to? + float2 uv3 : TEXCOORD2; //axial coordinates on a grid of hexagons + }; + + struct g2f + { + float4 vertex : SV_POSITION; + float4 vertPos_axialCoords : TEXCOORD0; + float3 objectPos : TEXCOORD1; + float3 worldPos : TEXCOORD2; + float3 tangent : TEXCOORD3; + float3 binormal : TEXCOORD4; + float3 normal : TEXCOORD5; + float4 screenPos : TEXCOORD6; + float2 polyGroup_pctComplete : TEXCOORD7; + float4 color : TEXCOORD8; + }; + + struct fout + { + float4 sv_target : SV_Target0; + }; + + float4 _SunColor; + float4 _DysonEmission; + float3 _Global_DS_SunPosition; + float3 _Global_DS_SunPosition_Map; + int _Global_IsMenuDemo; + int _Global_DS_RenderPlace; // -1=Demo, 0=In-Game (Universe), 1=StarMap, or 2=DysonMap + int _Global_DS_HideFarSide; + int _Global_DS_PaintingLayerId; + int _Global_DS_PaintingGridMode; + float _Global_VMapEnabled; //(always 1f if gameData != null) + float _CellSize; ////always 1 except dyson-shell-unlit-0 which is 0.94 + int _Color32Int; + float _AlbedoMultiplier; + float _NormalMultiplier; + float _EmissionMultiplier; + float _State; // bitfield for selection/tool state + int _LayerId; + float _Radius; //Radius of dyson sphere + float _Scale; //(int)(Math.Pow(radius / 4000.0, 0.75) + 0.5); //4000 radius = 1. + float _GridSize; //_Scale * 80 + float4 _Center; //Center of the shell that this point is a member of. + // xaxis = normalize(cross(normalize(_Center), vector3.up)) + // yaxis = normalize(cross(xaxis, normalize(_Center))) + // t0axis = yaxis * _GridSize * rsqrt(3); + // t1axis = yaxis * _GridSize * rsqrt(3) * 0.5 - xaxis * _GridSize * 0.5; + // t2axis = yaxis * _GridSize * rsqrt(3) * 0.5 + xaxis * _GridSize * 0.5; + float3 _t0Axis; //in an axial coordinate system, the "q" axis. relative to center of shell. + float3 _t1Axis; //in an axial coordinate system, the "r" axis. relative to center of shell. + float3 _t2Axis; //in an axial coordinate system, the "s" axis. relative to center of shell. + float _PolyCount; //number of nodes that make of the shape of this shell + float _Clockwise; + float _NodeProgressArr[128]; + float4 _PolygonArr[128]; // points that make up the shape of the polygon. repeated PolyCount times. + float4 _PolygonNArr[128]; // normals + sampler2D _NoiseTex; + sampler2D _MainTex; + sampler2D _NormalTex; + sampler2D _MSTex; + sampler2D _EmissionTex; + sampler2D _EmissionTex2; + sampler2D _ColorControlTex; + sampler2D _ColorControlTex2; + + v2g vert(appdata_full v) + { + v2g o; + + o.vertex.xyzw = v.vertex.xyzw; + o.uv.xy = v.texcoord.xy; + o.uv2.xy = v.texcoord1.xy; + o.uv3.xy = v.texcoord2.xy; + + return o; + } + + [maxvertexcount(12)] + void geom(point v2g input[1], inout TriangleStream triStream) + { + g2f o; + + uint nodeIndex = (uint)input[0].uv.x; + float vertFillOrder = input[0].uv.y; //sorted by which vert should appear first, if this is vert 3 of 8, vertFillOrder = (3/8) = 0.375. + float pctNodeComplete = _NodeProgressArr[nodeIndex]; + float weighted_vertFillOrder = pow(vertFillOrder, 1.25); //fill early verts a little faster than later verts + uint renderPlace = asuint(_Global_DS_RenderPlace); + bool isDysonMap = renderPlace > 1.5; + + float hexPctComplete = saturate(pctNodeComplete + (_Scale/.28) * (pctNodeComplete - weighted_vertFillOrder)); + bool shouldRenderHex = hexPctComplete > 0.0001; + + if (isDysonMap || shouldRenderHex) { // Always render in DysonMap + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + + float triangleVertPos = (1.0 / 3.0) * _Scale; + float3 normal = normalize(mul((float3x3)unity_ObjectToWorld, input[0].vertex.xyz)); + + float3 worldMidPtPos = mul(unity_ObjectToWorld, input[0].vertex.xyz); + float scaleGridFactor = min(1.0, (min(1.0, 30.0 * saturate((length(worldMidPtPos) / (_GridSize * 18.0)) - 0.5)) * 0.07 + 1) - min(0.1, 0.2 / _Scale)) * saturate(length(worldMidPtPos) / (_GridSize * 1.5)); + + float distFromCam = length(_WorldSpaceCameraPos.xyz - input[0].vertex.xyz); + float cellSizeFalloff = 1.0 - saturate(distFromCam / 40000.0 - 0.075); + + float AngleCenterToPoint = dot(normalize(_Center.xyz), normalize(input[0].vertex.xyz)); + + AngleCenterToPoint = isDysonMap ? AngleCenterToPoint : AngleCenterToPoint * scaleGridFactor; + + float centerToEdgeLength = AngleCenterToPoint * lerp(1.0, _CellSize, cellSizeFalloff); + + float3 t0_up_pos = normalize(input[0].vertex.xyz + _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_up_pos = normalize(input[0].vertex.xyz + _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_up_pos = normalize(input[0].vertex.xyz + _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 t0_down_pos = normalize(input[0].vertex.xyz - _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_down_pos = normalize(input[0].vertex.xyz - _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_down_pos = normalize(input[0].vertex.xyz - _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 midPtPos = input[0].vertex.xyz; + + if (isDysonOrStarMap) { // not demoscene and not ingame, so starmap and dysonmap + t0_up_pos.xyz = t0_up_pos.xyz / 4000.0; + t1_up_pos.xyz = t1_up_pos.xyz / 4000.0; + t2_up_pos.xyz = t2_up_pos.xyz / 4000.0; + t0_down_pos.xyz = t0_down_pos.xyz / 4000.0; + t1_down_pos.xyz = t1_down_pos.xyz / 4000.0; + t2_down_pos.xyz = t2_down_pos.xyz / 4000.0; + midPtPos.xyz = midPtPos.xyz / 4000.0; + } + + float3 worldTangent = normalize(mul(unity_ObjectToWorld, t1_down_pos.xyz - t1_up_pos.xyz)); + float3 worldBinormal = normalize(mul(unity_ObjectToWorld, t0_up_pos.xyz - t0_down_pos.xyz)); + + //unpack and convert gamma to linear color + float4 gamma_color = float4(asuint(_Color32Int) & 255, (asuint(_Color32Int) >> 8) & 255, (asuint(_Color32Int) >> 16) & 255, (asuint(_Color32Int) >> 24) & 255) * (1.0f / 255); //asuint(_Color32Int)? + float4 linear_color = pow((gamma_color.xyzw + 0.055F)/1.055F, 2.4F); //GammaToLinearSpaceExact + + float4 worldPos = mul(unity_ObjectToWorld, float4(t0_up_pos.xyz, 1.0)); + float3 ray = worldPos.xyz - _WorldSpaceCameraPos.xyz; + float3 adjustedRay = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + float3 objPos = mul(unity_WorldToObject, worldPos.xyzw); + float3 t0up_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + float3 final_objpos = isInGame ? objPos.xyz : t0_up_pos.xyz; + + float4 t0up_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 t0up_screenPos = ComputeScreenPos(t0up_clipPos); + + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + //midPtPos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(midPtPos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 center_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : midPtPos.xyz; + + float4 center_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 center_screenPos = ComputeScreenPos(center_clipPos); + + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + + //t1_up_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_up_pos.xyz; + + float4 clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + + triStream.Append(o); + + // t2_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t2_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t0_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t0_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t1_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t1_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_up_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + //t2_up_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_up_pos + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + } + return; + } + + fout frag(g2f i) + { + + fout o; + const float4 icb[16] = { + float4(16.0, 0.0, 0.0, 0.0), + float4(8.0, 0.0, 0.0, 0.0), + float4(14.0, 0.0, 0.0, 0.0), + float4(6.0, 0.0, 0.0, 0.0), + float4(4.0, 0.0, 0.0, 0.0), + float4(12.0, 0.0, 0.0, 0.0), + float4(2.0, 0.0, 0.0, 0.0), + float4(10.0, 0.0, 0.0, 0.0), + float4(13.0, 0.0, 0.0, 0.0), + float4(5.0, 0.0, 0.0, 0.0), + float4(15.0, 0.0, 0.0, 0.0), + float4(7.0, 0.0, 0.0, 0.0), + float4(1.0, 0.0, 0.0, 0.0), + float4(9.0, 0.0, 0.0, 0.0), + float4(3.0, 0.0, 0.0, 0.0), + float4(11.0, 0.0, 0.0, 0.0) + }; + + float2 triangleVertPos = i.vertPos_axialCoords.xy; + float2 axialCoords = i.vertPos_axialCoords.zw; + int polygonGroup = (int)((uint)(0.5 + i.polyGroup_pctComplete.x)); + float hexPctComplete = i.polyGroup_pctComplete.y; + + uint renderPlace = asuint(_Global_DS_RenderPlace); + + bool isDysonMap = renderPlace > 1.5; + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + bool isMenuDemo = 0.5 < asuint(_Global_IsMenuDemo); + + if ((int)(asint(_Global_DS_PaintingLayerId) != asint(_LayerId)) | (int)(asuint(_Global_DS_PaintingGridMode) > 0.5) ? asuint(_Global_DS_PaintingLayerId) > 0 ? isDysonMap : 0 : 0 != 0) discard; + + float3 rayPosToCamera = _WorldSpaceCameraPos.xyz - i.worldPos.xyz; + + //if a ray from the the vert to the camera and a ray from the vert to the sun are pointing in the same direction, must be far side. + bool isFarSide = dot(rayPosToCamera, _Global_DS_SunPosition_Map.xyz - i.worldPos.xyz) > 0; + bool hideFarSideEnabled = asuint(_Global_DS_HideFarSide) > 0.5; + if (isDysonMap && hideFarSideEnabled && isFarSide) discard; + + /* remove pixels that fall outside the bounds of the frame that surrounds this shell */ + uint polyCount = (uint)(0.5 + _PolyCount) < 1 ? 1 : min(380, (uint)(0.5 + _PolyCount)); + int polygonIndex = (int)polyCount + (int)(0.5 + polygonGroup); + + float3 prevLineNormal = _PolygonNArr[polygonIndex - 1].xyz; + float3 prevLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex - 1].xyz; + + float3 thisLineDir = _PolygonArr[polygonIndex + 1].xyz - _PolygonArr[polygonIndex].xyz; + float3 thisLineNormal = _PolygonNArr[polygonIndex].xyz; + + float3 nextLineDir = _PolygonArr[polygonIndex + 2].xyz - _PolygonArr[polygonIndex + 1].xyz; + float3 nextLineNormal = _PolygonNArr[polygonIndex + 1].xyz; + float3 nextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 1].xyz; + + float3 nextnextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 2].xyz; + + + float prevLineIsConcave = dot(thisLineDir, prevLineNormal); + float nextLineIsConcave = dot(nextLineDir, thisLineNormal); + // <0 means convex + // >0 means concave + // 0 means parallel + int prevLineIsConvex = prevLineIsConcave > 0 ? 1 : prevLineIsConcave < 0 ? -1 : 0; + int nextLineIsConvex = nextLineIsConcave > 0 ? 1 : nextLineIsConcave < 0 ? -1 : 0; + //set to int, flip sign. 1=convex, -1=concave + + float prevLineInside = dot(prevLineToPoint, prevLineNormal); + float thisLineInside = dot(nextLineToPoint, thisLineNormal); + float nextLineInside = dot(nextnextLineToPoint, nextLineNormal); + // inside if >0, outside if <0 + + prevLineIsConvex *= _Clockwise; + nextLineIsConvex *= _Clockwise; + prevLineInside *= _Clockwise; + thisLineInside *= _Clockwise; + nextLineInside *= _Clockwise; + // flip sign if counterclockwise (_Clockwise = -1) + + float insideBounds = -1; + if (nextLineIsConvex > 0 && prevLineIsConvex > 0) { + if (nextLineInside > 0 && thisLineInside > 0 && prevLineInside > 0) { + insideBounds = 1; + } else { + insideBounds = -1; + } + } else { + if (nextLineIsConvex > 0 && prevLineIsConvex <= 0) { + insideBounds = nextLineInside > 0 && (prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } else { + if (nextLineIsConvex <= 0 && prevLineIsConvex > 0) { + insideBounds = prevLineInside > 0 && (thisLineInside > 0 || nextLineInside > 0) ? 1 : -1; + } else { + insideBounds = (nextLineInside > 0 || prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } + } + } + if (insideBounds < 0) discard; + /* end shell/frame bounds check */ + + + float distancePosToCamera = length(rayPosToCamera); + + float4 cubeCoords = _Scale * float4(0.666666687,0.333333343,-0.333333343,0.333333343) * axialCoords.xxyy; + cubeCoords.xy = cubeCoords.yx + cubeCoords.wz; + + float gridFalloff = 0.99 - saturate((distancePosToCamera / _GridSize) / 15.0 - 0.2) * 0.03; + + float2 adjustPoint = triangleVertPos.yx * gridFalloff + cubeCoords.xy; + adjustPoint.xy = adjustPoint.yx * float2(2,2) - adjustPoint.xy; + float adjustPoint_z = -adjustPoint.x - adjustPoint.y; + float2 roundedAdjustPoint = round(adjustPoint.xy); + float roundedAdjustPoint_z = round(adjustPoint_z); + float2 roundedPointDiff = -roundedAdjustPoint.yx - round(adjustPoint_z); + adjustPoint.xy = roundedAdjustPoint.xy < adjustPoint.xy ? adjustPoint.xy - roundedAdjustPoint.xy : roundedAdjustPoint.xy - adjustPoint.xy; + adjustPoint_z = roundedAdjustPoint_z < adjustPoint_z ? adjustPoint_z - roundedAdjustPoint_z : roundedAdjustPoint_z - adjustPoint_z; + adjustPoint.xy = adjustPoint_z < adjustPoint.xy ? adjustPoint.yx < adjustPoint.xy : 0; + + float alternatePointY = adjustPoint.y ? roundedPointDiff.y : roundedAdjustPoint.y; + float2 correctedCoords = roundedAdjustPoint.x + roundedAdjustPoint.y + roundedAdjustPoint_z != 0.000000 ? (adjustPoint.xx ? float2(roundedPointDiff.x, roundedAdjustPoint.y) : float2(roundedAdjustPoint.x, alternatePointY)) : roundedAdjustPoint.xy; + + float2 randomSampleCoords = float2(0.001953125,0.001953125) * correctedCoords.xy; + float random_num = tex2Dlod(_NoiseTex, float4(randomSampleCoords.xy, 0, 0)).x; + + + int bitmask; + float cutOut = 0; + if (hexPctComplete - random_num * 0.999 < 0.00005) { + if (isDysonMap) { + float2 pixelPos = (_ScreenParams.xy * (i.screenPos.xy / i.screenPos.ww)); + pixelPos = (int2)pixelPos; + bitmask = ((~(-1 << 2)) << 2) & 0xffffffff; // 12 + cutOut = (((uint)pixelPos.x << 2) & bitmask) | ((uint)0 & ~bitmask); + bitmask = ((~(-1 << 2)) << 0) & 0xffffffff; // 3 + cutOut = (((uint)pixelPos.y << 0) & bitmask) | ((uint)cutOut & ~bitmask); + if (0.2499 - (icb[cutOut].x * 0.0588) < 0) discard; + cutOut = 1; + } else { + if (-1 != 0) discard; + cutOut = 0; + } + } else { + cutOut = 0; + } + + float2 triPosAdjusted; + triPosAdjusted.x = triangleVertPos.x / _Scale + (2.0 * axialCoords.x - axialCoords.y) / 3.0; + triPosAdjusted.y = triangleVertPos.y / _Scale + (axialCoords.x + axialCoords.y) / 3.0; + + float lodBias = min(4, max(0, log(0.0001 * distancePosToCamera))); + + float4 albedoTex = tex2Dbias(_MainTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + + float4 normalTex = tex2Dbias(_NormalTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + float3 unpackedNormal = UnpackNormal(normalTex); + + float2 msTex = tex2D(_MSTex, triangleVertPos.xy).xw; + + float3 emissionTex_A = tex2Dbias(_EmissionTex, float4(triangleVertPos.xy, 0, lodBias)).xyz; + float3 emissionTex_B = tex2Dbias(_EmissionTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).xyz; + + float3 emissionTex = lerp(emissionTex_A.xyz, emissionTex_B.xyz, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float3 emissionTexTwo = tex2Dbias(_EmissionTex2, float4(triPosAdjusted.xy, 0, lodBias)).xyz; + + float colorControlTex_A = tex2Dbias(_ColorControlTex, float4(triangleVertPos.xy, 0, lodBias)).x; + float colorControlTex_B = tex2Dbias(_ColorControlTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).x; + float colorControlTex = lerp(colorControlTex_A, colorControlTex_B, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float colorControlTexTwo = tex2Dbias(_ColorControlTex2, float4(triPosAdjusted.xy, 0, lodBias)).x; + + unpackedNormal.xy = (-1.5 * _NormalMultiplier) * unpackedNormal.xy; + float3 worldNormal = normalize(i.normal.xyz * unpackedNormal.z + i.tangent.xyz * unpackedNormal.x + i.binormal.xyz * unpackedNormal.y); + + float3 triPosNew; + triPosNew.x = 1.0 - abs(frac(0.5 * (0.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + triPosNew.y = 1.0 - abs(frac(0.5 * (0 + triPosAdjusted.y)) * 2.0 - 1.0); + triPosNew.z = 1.0 - abs(frac(0.5 * (1.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + + float2 newPosOne; + newPosOne.x = ((triPosNew.x + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosOne.y = (triPosNew.y - triPosNew.x) / sqrt(2); + + float2 newPosTwo; + newPosTwo.x = ((triPosNew.z + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosTwo.y = (triPosNew.y - triPosNew.z) / sqrt(2); + + float3 viewDir = normalize(rayPosToCamera); + bool viewingSunFacingSide = dot(i.normal.xyz, viewDir.xyz) < 0; + + float emissionAnim = saturate(30.0 * (0.05 - abs(length(newPosOne.xy) - frac(2.9 * _Time.x)))) * min(1, 5 * (1 - frac(2.9 * _Time.x))) + + saturate(30.0 * (0.05 - abs(length(newPosTwo.xy) - frac(_Time.x * 3.7 + 0.5)))) * min(1, 5 * (1 - frac(_Time.x * 3.7 + 0.5))); + emissionAnim = viewingSunFacingSide ? saturate((emissionTexTwo.y * 2 + emissionTex.y) * emissionAnim) : 0; + + float3 dysonEmission = viewingSunFacingSide ? _DysonEmission.xyz : float3(1,1,1); + float colorControl = saturate(colorControlTex + colorControlTexTwo); + float3 colorOutwardFacing = lerp(colorControl * i.color.xyz, i.color.xyz, 0.01 / _EmissionMultiplier); + float3 emissionOutwardFacing = lerp(emissionTexTwo.xyz * float3(0.3, 0.3, 0.3) + emissionTex.xyz, colorOutwardFacing, i.color.w); + float3 emissionSunFacing = float3(3,3,3) * (emissionTexTwo.x + emissionTex.x) * dysonEmission.xyz; + float3 emission = viewingSunFacingSide ? emissionSunFacing.xyz : emissionOutwardFacing.xyz; + + emission = _EmissionMultiplier * lerp(emission.xyz, dysonEmission.xyz, emissionAnim); + + float3 albedo = _AlbedoMultiplier * albedoTex.xyz * lerp(float3(1,1,1), albedoTex.xyz, saturate(1.25 * (albedoTex.w - 0.1))); + float specularStrength = dot(albedo, float3(0.3, 0.6, 0.1)); + + float scaledDistancePosToCamera = isMenuDemo ? distancePosToCamera : isDysonOrStarMap ? 3999.9998 * distancePosToCamera : distancePosToCamera; + float scaleMetallic = isMenuDemo ? 0.1 : isDysonOrStarMap ? 0.93 : 0.7; + scaleMetallic = saturate(pow(0.25 * log(scaledDistancePosToCamera + 1) - 1.5, 3.0)) * scaleMetallic; + float multiplyEmission = isDysonMap ? 2.2 : isDysonOrStarMap ? 1.8 : 2.5; + + float3 shellColor = i.color.w > 0.5 ? i.color.xyz : (asint(_Global_DS_PaintingLayerId) == asint(_LayerId) ? float3(0, 0.3, 0.65) : float3(0, 0.8, 0.6)); + float3 shellEmissionColor = lerp(emission.xyz * multiplyEmission, shellColor, 0.8 * cutOut); + + specularStrength = _State > 0.5 ? 0 : 0.8 * specularStrength * (1.0 - cutOut); + float fadeOut = _State > 0.5 ? 0 : 0.03 * (1.0 - cutOut); + float metallic = _State > 0.5 ? 0 : msTex.x * (1.0 - scaleMetallic); + float smoothness = _State > 0.5 ? 0.5 : min(0.8, msTex.y); + + float3 defaultColor = isDysonMap ? i.color.xyz * (viewingSunFacingSide ? 2 : 1.5) : float3(0,0,0); + float3 highStateColor = i.color.w > 0.5 ? defaultColor : float3(2.59, 0.0525, 0.0875); + float3 medStateColor = i.color.w > 0.5 ? defaultColor : float3(0.525,0.875, 3.5); + float3 lowStateColor = i.color.w > 0.5 ? defaultColor : float3(0.35, 0.7, 3.5); + float3 zeroStateColor = i.color.w > 0.5 ? defaultColor : float3(1.05, 1.05, 1.05); + float3 finalColor = 3.5 < _State ? highStateColor : + 2.5 < _State ? medStateColor : + 1.5 < _State ? lowStateColor : + 0.5 < _State ? zeroStateColor : + shellEmissionColor; + + float emissionFactor = (int)(_State > 0.5) | (int)(cutOut > 0.5) ? (1.0 / _EmissionMultiplier) : saturate(colorControlTex + colorControlTexTwo.x); + float metallicFactor = saturate(metallic * 0.85 + 0.149); + + float perceptualRoughness = min(1, 1 - smoothness * 0.97); + float roughness = perceptualRoughness * perceptualRoughness; + float roughnessSqr = roughness * roughness; + + float NdotV = viewingSunFacingSide ? -dot(worldNormal.xyz, viewDir.xyz) : dot(worldNormal.xyz, viewDir.xyz); + worldNormal.xyz = viewingSunFacingSide ? -worldNormal.xyz : worldNormal.xyz; + + float3 lightDir = -i.normal.xyz; + float3 halfDir = normalize(normalize(rayPosToCamera) + lightDir.xyz); + + float NdotL = dot(worldNormal.xyz, lightDir.xyz); + float NdotH = dot(worldNormal.xyz, halfDir.xyz); + float VdotH = dot(viewDir, halfDir.xyz); + float clamp_NdotL = max(0, NdotL); + float clamp_NdotH = max(0, NdotH); + float clamp_VdotH = max(0, VdotH); + + float D = 0.25 * pow(rcp(clamp_NdotH * clamp_NdotH * (roughnessSqr - 1) + 1),2) * roughnessSqr; + + float gv = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, NdotV); + float gl = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, clamp_NdotL); + float G = rcp(gv * gl); + + float fk = exp2((clamp_VdotH * -5.55472994 - 6.98316002) * clamp_VdotH); + float F = lerp(0.5 + metallicFactor, 1.0, fk); + + float sunStrength = isInGame ? pow(saturate(1.05 + dot(normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz), i.normal.xyz)), 0.4) : 1.0; + float3 sunColor = float3(1.5625,1.5625,1.5625) * _SunColor.xyz; + float intensity = saturate(pow(NdotL * 0.6 + 1, 3)); + float3 sunColorIntensity = float3(0.07, 0.07, 0.07) * _SunColor * (intensity * 1.5 + 1) * intensity; + float3 sunSpecular = sunColor.xyz * clamp_NdotL * specularStrength; + + float3 finalLight = lerp(1, specularStrength, metallicFactor) * fadeOut * sunColor.xyz * (F * D * G + (0.1 / UNITY_PI)) * clamp_NdotL; + finalLight = finalLight.xyz * lerp(metallicFactor, 1, specularStrength * 0.2); + finalLight = float3(5,5,5) * lerp(float3(1,1,1), _SunColor, float3(0.3,0.3,0.3)) * finalLight.xyz; + finalLight = (sunColorIntensity.xyz * specularStrength * (1 - metallicFactor * 0.6) + sunSpecular.xyz * pow(1 - metallicFactor, 0.6) + finalLight.xyz) * sunStrength; + + float finalStength = dot(finalLight, float3(0.3, 0.6, 0.1)); + float3 normalizedLight = finalLight / finalStength; + float megaLog = log(log(log(log(log(log(log(log(finalStength / 0.32) + 1) + 1) + 1) + 1) + 1) + 1) + 1) + 1; + finalLight = 0.32 < finalStength ? normalizedLight * megaLog * 0.32 : finalLight; + + float finalAlpha = _EmissionMultiplier * emissionFactor; + o.sv_target.xyzw = float4(finalColor, 0.0) + float4(finalLight, finalAlpha); + + return o; + } + ENDCG + } + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/shaders/Dyson Shell Unlit REPLACE-Small.shader b/shaders/Dyson Shell Unlit REPLACE-Small.shader new file mode 100644 index 0000000..8a40c96 --- /dev/null +++ b/shaders/Dyson Shell Unlit REPLACE-Small.shader @@ -0,0 +1,751 @@ +Shader "VF Shaders/Dyson Sphere/Dyson Shell Unlit REPLACE Small" { + Properties { + _Color ("Color", Vector) = (1,1,1,1) + _MainTex ("Albedo (RGB)", 2D) = "white" {} + _NormalTex ("Normal Map", 2D) = "bump" {} + _MSTex ("Metallic Smoothness (RA)", 2D) = "white" {} + _EmissionTex ("Emission (RGB)", 2D) = "black" {} + _EmissionTex2 ("Emission Large (RGB)", 2D) = "black" {} + _NoiseTex ("Noise Texture (R)", 2D) = "gray" {} + _ColorControlTex ("Color Control", 2D) = "black" {} + _ColorControlTex2 ("Color Control Large", 2D) = "black" {} + _AlbedoMultiplier ("漫反射倍率", Float) = 1 + _NormalMultiplier ("法线倍率", Float) = 1 + _EmissionMultiplier ("自发光倍率", Float) = 5.5 + _CellSize ("细胞大小(是否有间隙)", Float) = 1 + } + SubShader { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Pass { + Tags { "LIGHTMODE" = "FORWARDBASE" "QUEUE" = "Geometry" "RenderType" = "DysonShell" } + Cull Off + Stencil { + CompFront Always + PassFront Replace + FailFront Keep + ZFailFront Keep + } + GpuProgramID 41389 + CGPROGRAM + #pragma vertex vert + #pragma geometry geom + #pragma fragment frag + #include "UnityCG.cginc" + #pragma target 5.0 + //#pragma enable_d3d11_debug_symbols + + struct v2g + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + //x [0,3] node index + //y [0,1] vert# / total#verts + float2 uv2 : TEXCOORD1; //u1.x is unused? + //x [0 or 1] (!s_outvmap.ContainsKey(item.Key)) ? 1 : 0) + //y [0,2] polygon index - which edge it is closest to? + float2 uv3 : TEXCOORD2; //axial coordinates on a grid of hexagons + }; + + struct g2f + { + float4 vertex : SV_POSITION; + float4 vertPos_axialCoords : TEXCOORD0; + float3 objectPos : TEXCOORD1; + float3 worldPos : TEXCOORD2; + float3 tangent : TEXCOORD3; + float3 binormal : TEXCOORD4; + float3 normal : TEXCOORD5; + float4 screenPos : TEXCOORD6; + float2 polyGroup_pctComplete : TEXCOORD7; + float4 color : TEXCOORD8; + }; + + struct fout + { + float4 sv_target : SV_Target0; + }; + + float4 _SunColor; + float4 _DysonEmission; + float3 _Global_DS_SunPosition; + float3 _Global_DS_SunPosition_Map; + int _Global_IsMenuDemo; + int _Global_DS_RenderPlace; // -1=Demo, 0=In-Game (Universe), 1=StarMap, or 2=DysonMap + int _Global_DS_HideFarSide; + int _Global_DS_PaintingLayerId; + int _Global_DS_PaintingGridMode; + float _Global_VMapEnabled; //(always 1f if gameData != null) + float _CellSize; ////always 1 except dyson-shell-unlit-0 which is 0.94 + int _Color32Int; + float _AlbedoMultiplier; + float _NormalMultiplier; + float _EmissionMultiplier; + float _State; // bitfield for selection/tool state + int _LayerId; + float _Radius; //Radius of dyson sphere + float _Scale; //(int)(Math.Pow(radius / 4000.0, 0.75) + 0.5); //4000 radius = 1. + float _GridSize; //_Scale * 80 + float4 _Center; //Center of the shell that this point is a member of. + // xaxis = normalize(cross(normalize(_Center), vector3.up)) + // yaxis = normalize(cross(xaxis, normalize(_Center))) + // t0axis = yaxis * _GridSize * rsqrt(3); + // t1axis = yaxis * _GridSize * rsqrt(3) * 0.5 - xaxis * _GridSize * 0.5; + // t2axis = yaxis * _GridSize * rsqrt(3) * 0.5 + xaxis * _GridSize * 0.5; + float3 _t0Axis; //in an axial coordinate system, the "q" axis. relative to center of shell. + float3 _t1Axis; //in an axial coordinate system, the "r" axis. relative to center of shell. + float3 _t2Axis; //in an axial coordinate system, the "s" axis. relative to center of shell. + float _PolyCount; //number of nodes that make of the shape of this shell + float _Clockwise; + float _NodeProgressArr[16]; + float4 _PolygonArr[16]; // points that make up the shape of the polygon. repeated PolyCount times. + float4 _PolygonNArr[16]; // normals + sampler2D _NoiseTex; + sampler2D _MainTex; + sampler2D _NormalTex; + sampler2D _MSTex; + sampler2D _EmissionTex; + sampler2D _EmissionTex2; + sampler2D _ColorControlTex; + sampler2D _ColorControlTex2; + + v2g vert(appdata_full v) + { + v2g o; + + o.vertex.xyzw = v.vertex.xyzw; + o.uv.xy = v.texcoord.xy; + o.uv2.xy = v.texcoord1.xy; + o.uv3.xy = v.texcoord2.xy; + + return o; + } + + [maxvertexcount(12)] + void geom(point v2g input[1], inout TriangleStream triStream) + { + g2f o; + + uint nodeIndex = (uint)input[0].uv.x; + float vertFillOrder = input[0].uv.y; //sorted by which vert should appear first, if this is vert 3 of 8, vertFillOrder = (3/8) = 0.375. + float pctNodeComplete = _NodeProgressArr[nodeIndex]; + float weighted_vertFillOrder = pow(vertFillOrder, 1.25); //fill early verts a little faster than later verts + uint renderPlace = asuint(_Global_DS_RenderPlace); + bool isDysonMap = renderPlace > 1.5; + + float hexPctComplete = saturate(pctNodeComplete + (_Scale/.28) * (pctNodeComplete - weighted_vertFillOrder)); + bool shouldRenderHex = hexPctComplete > 0.0001; + + if (isDysonMap || shouldRenderHex) { // Always render in DysonMap + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + + float triangleVertPos = (1.0 / 3.0) * _Scale; + float3 normal = normalize(mul((float3x3)unity_ObjectToWorld, input[0].vertex.xyz)); + + float3 worldMidPtPos = mul(unity_ObjectToWorld, input[0].vertex.xyz); + float scaleGridFactor = min(1.0, (min(1.0, 30.0 * saturate((length(worldMidPtPos) / (_GridSize * 18.0)) - 0.5)) * 0.07 + 1) - min(0.1, 0.2 / _Scale)) * saturate(length(worldMidPtPos) / (_GridSize * 1.5)); + + float distFromCam = length(_WorldSpaceCameraPos.xyz - input[0].vertex.xyz); + float cellSizeFalloff = 1.0 - saturate(distFromCam / 40000.0 - 0.075); + + float AngleCenterToPoint = dot(normalize(_Center.xyz), normalize(input[0].vertex.xyz)); + + AngleCenterToPoint = isDysonMap ? AngleCenterToPoint : AngleCenterToPoint * scaleGridFactor; + + float centerToEdgeLength = AngleCenterToPoint * lerp(1.0, _CellSize, cellSizeFalloff); + + float3 t0_up_pos = normalize(input[0].vertex.xyz + _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_up_pos = normalize(input[0].vertex.xyz + _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_up_pos = normalize(input[0].vertex.xyz + _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 t0_down_pos = normalize(input[0].vertex.xyz - _t0Axis.xyz * centerToEdgeLength) * _Radius; + float3 t1_down_pos = normalize(input[0].vertex.xyz - _t1Axis.xyz * centerToEdgeLength) * _Radius; + float3 t2_down_pos = normalize(input[0].vertex.xyz - _t2Axis.xyz * centerToEdgeLength) * _Radius; + float3 midPtPos = input[0].vertex.xyz; + + if (isDysonOrStarMap) { // not demoscene and not ingame, so starmap and dysonmap + t0_up_pos.xyz = t0_up_pos.xyz / 4000.0; + t1_up_pos.xyz = t1_up_pos.xyz / 4000.0; + t2_up_pos.xyz = t2_up_pos.xyz / 4000.0; + t0_down_pos.xyz = t0_down_pos.xyz / 4000.0; + t1_down_pos.xyz = t1_down_pos.xyz / 4000.0; + t2_down_pos.xyz = t2_down_pos.xyz / 4000.0; + midPtPos.xyz = midPtPos.xyz / 4000.0; + } + + float3 worldTangent = normalize(mul(unity_ObjectToWorld, t1_down_pos.xyz - t1_up_pos.xyz)); + float3 worldBinormal = normalize(mul(unity_ObjectToWorld, t0_up_pos.xyz - t0_down_pos.xyz)); + + //unpack and convert gamma to linear color + float4 gamma_color = float4(asuint(_Color32Int) & 255, (asuint(_Color32Int) >> 8) & 255, (asuint(_Color32Int) >> 16) & 255, (asuint(_Color32Int) >> 24) & 255) * (1.0f / 255); //asuint(_Color32Int)? + float4 linear_color = pow((gamma_color.xyzw + 0.055F)/1.055F, 2.4F); //GammaToLinearSpaceExact + + float4 worldPos = mul(unity_ObjectToWorld, float4(t0_up_pos.xyz, 1.0)); + float3 ray = worldPos.xyz - _WorldSpaceCameraPos.xyz; + float3 adjustedRay = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + float3 objPos = mul(unity_WorldToObject, worldPos.xyzw); + float3 t0up_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + float3 final_objpos = isInGame ? objPos.xyz : t0_up_pos.xyz; + + float4 t0up_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 t0up_screenPos = ComputeScreenPos(t0up_clipPos); + + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + //midPtPos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(midPtPos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 center_final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : midPtPos.xyz; + + float4 center_clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 center_screenPos = ComputeScreenPos(center_clipPos); + + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + + + + //t1_up_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + float3 final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_up_pos.xyz; + + float4 clipPos = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + float4 screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + + triStream.Append(o); + + // t2_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t2_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(-triangleVertPos, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t0_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t0_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, -triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t1_down_pos + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t1_down_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t1_down_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + triStream.RestartStrip(); + + //t1_down_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t1_down_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //midPtPos + o.vertex.xyzw = center_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, 0); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = midPtPos.xyz; + o.worldPos.xyz = center_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = center_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + worldPos.xyzw = mul(unity_ObjectToWorld, float4(t2_up_pos.xyz, 1.0)); + ray.xyz = worldPos.xyz - _WorldSpaceCameraPos.xyz; + adjustedRay.xyz = ray.xyz * ((10000 * (log(length(ray.xyz) / 10000.0) + 1)) / length(ray.xyz)); + ray.xyz = length(ray.xyz) > 10000 ? adjustedRay.xyz : ray.xyz; + worldPos.xyzw = _Global_VMapEnabled >= 1 ? float4(_WorldSpaceCameraPos.xyz + ray.xyz, 1.0) : worldPos.xyzw; + + objPos.xyz = mul(unity_WorldToObject, worldPos.xyzw); + final_worldpos = isInGame ? worldPos.xyz : objPos.xyz; + final_objpos = isInGame ? objPos.xyz : t2_up_pos.xyz; + + clipPos.xyzw = mul(unity_MatrixVP, mul(unity_ObjectToWorld, float4(final_objpos, 1.0))); + screenPos = ComputeScreenPos(clipPos); + + //t2_up_pos + o.vertex.xyzw = clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(triangleVertPos, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t2_up_pos.xyz; + o.worldPos.xyz = final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + //t0_up_pos + o.vertex.xyzw = t0up_clipPos.xyzw; + o.vertPos_axialCoords.xy = float2(0, triangleVertPos); + o.vertPos_axialCoords.zw = input[0].uv3.xy; + o.objectPos.xyz = t0_up_pos.xyz; + o.worldPos.xyz = t0up_final_worldpos.xyz; + o.tangent.xyz = worldTangent.xyz; + o.binormal.xyz = worldBinormal.xyz; + o.normal.xyz = normal.xyz; + o.screenPos = t0up_screenPos; + o.polyGroup_pctComplete.x = input[0].uv2.y; + o.polyGroup_pctComplete.y = hexPctComplete; + o.color.xyzw = linear_color.xyzw; + triStream.Append(o); + + } + return; + } + + fout frag(g2f i) + { + + fout o; + const float4 icb[16] = { + float4(16.0, 0.0, 0.0, 0.0), + float4(8.0, 0.0, 0.0, 0.0), + float4(14.0, 0.0, 0.0, 0.0), + float4(6.0, 0.0, 0.0, 0.0), + float4(4.0, 0.0, 0.0, 0.0), + float4(12.0, 0.0, 0.0, 0.0), + float4(2.0, 0.0, 0.0, 0.0), + float4(10.0, 0.0, 0.0, 0.0), + float4(13.0, 0.0, 0.0, 0.0), + float4(5.0, 0.0, 0.0, 0.0), + float4(15.0, 0.0, 0.0, 0.0), + float4(7.0, 0.0, 0.0, 0.0), + float4(1.0, 0.0, 0.0, 0.0), + float4(9.0, 0.0, 0.0, 0.0), + float4(3.0, 0.0, 0.0, 0.0), + float4(11.0, 0.0, 0.0, 0.0) + }; + + float2 triangleVertPos = i.vertPos_axialCoords.xy; + float2 axialCoords = i.vertPos_axialCoords.zw; + int polygonGroup = (int)((uint)(0.5 + i.polyGroup_pctComplete.x)); + float hexPctComplete = i.polyGroup_pctComplete.y; + + uint renderPlace = asuint(_Global_DS_RenderPlace); + + bool isDysonMap = renderPlace > 1.5; + bool isDysonOrStarMap = renderPlace > 0.5; + bool isInGame = renderPlace < 0.5; + bool isMenuDemo = 0.5 < asuint(_Global_IsMenuDemo); + + if ((int)(asint(_Global_DS_PaintingLayerId) != asint(_LayerId)) | (int)(asuint(_Global_DS_PaintingGridMode) > 0.5) ? asuint(_Global_DS_PaintingLayerId) > 0 ? isDysonMap : 0 : 0 != 0) discard; + + float3 rayPosToCamera = _WorldSpaceCameraPos.xyz - i.worldPos.xyz; + + //if a ray from the the vert to the camera and a ray from the vert to the sun are pointing in the same direction, must be far side. + bool isFarSide = dot(rayPosToCamera, _Global_DS_SunPosition_Map.xyz - i.worldPos.xyz) > 0; + bool hideFarSideEnabled = asuint(_Global_DS_HideFarSide) > 0.5; + if (isDysonMap && hideFarSideEnabled && isFarSide) discard; + + /* remove pixels that fall outside the bounds of the frame that surrounds this shell */ + uint polyCount = (uint)(0.5 + _PolyCount) < 1 ? 1 : min(380, (uint)(0.5 + _PolyCount)); + int polygonIndex = (int)polyCount + (int)(0.5 + polygonGroup); + + float3 prevLineNormal = _PolygonNArr[polygonIndex - 1].xyz; + float3 prevLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex - 1].xyz; + + float3 thisLineDir = _PolygonArr[polygonIndex + 1].xyz - _PolygonArr[polygonIndex].xyz; + float3 thisLineNormal = _PolygonNArr[polygonIndex].xyz; + + float3 nextLineDir = _PolygonArr[polygonIndex + 2].xyz - _PolygonArr[polygonIndex + 1].xyz; + float3 nextLineNormal = _PolygonNArr[polygonIndex + 1].xyz; + float3 nextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 1].xyz; + + float3 nextnextLineToPoint = i.objectPos.xyz - _PolygonArr[polygonIndex + 2].xyz; + + + float prevLineIsConcave = dot(thisLineDir, prevLineNormal); + float nextLineIsConcave = dot(nextLineDir, thisLineNormal); + // <0 means convex + // >0 means concave + // 0 means parallel + int prevLineIsConvex = prevLineIsConcave > 0 ? 1 : prevLineIsConcave < 0 ? -1 : 0; + int nextLineIsConvex = nextLineIsConcave > 0 ? 1 : nextLineIsConcave < 0 ? -1 : 0; + //set to int, flip sign. 1=convex, -1=concave + + float prevLineInside = dot(prevLineToPoint, prevLineNormal); + float thisLineInside = dot(nextLineToPoint, thisLineNormal); + float nextLineInside = dot(nextnextLineToPoint, nextLineNormal); + // inside if >0, outside if <0 + + prevLineIsConvex *= _Clockwise; + nextLineIsConvex *= _Clockwise; + prevLineInside *= _Clockwise; + thisLineInside *= _Clockwise; + nextLineInside *= _Clockwise; + // flip sign if counterclockwise (_Clockwise = -1) + + float insideBounds = -1; + if (nextLineIsConvex > 0 && prevLineIsConvex > 0) { + if (nextLineInside > 0 && thisLineInside > 0 && prevLineInside > 0) { + insideBounds = 1; + } else { + insideBounds = -1; + } + } else { + if (nextLineIsConvex > 0 && prevLineIsConvex <= 0) { + insideBounds = nextLineInside > 0 && (prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } else { + if (nextLineIsConvex <= 0 && prevLineIsConvex > 0) { + insideBounds = prevLineInside > 0 && (thisLineInside > 0 || nextLineInside > 0) ? 1 : -1; + } else { + insideBounds = (nextLineInside > 0 || prevLineInside > 0 || thisLineInside > 0) ? 1 : -1; + } + } + } + if (insideBounds < 0) discard; + /* end shell/frame bounds check */ + + + float distancePosToCamera = length(rayPosToCamera); + + float4 cubeCoords = _Scale * float4(0.666666687,0.333333343,-0.333333343,0.333333343) * axialCoords.xxyy; + cubeCoords.xy = cubeCoords.yx + cubeCoords.wz; + + float gridFalloff = 0.99 - saturate((distancePosToCamera / _GridSize) / 15.0 - 0.2) * 0.03; + + float2 adjustPoint = triangleVertPos.yx * gridFalloff + cubeCoords.xy; + adjustPoint.xy = adjustPoint.yx * float2(2,2) - adjustPoint.xy; + float adjustPoint_z = -adjustPoint.x - adjustPoint.y; + float2 roundedAdjustPoint = round(adjustPoint.xy); + float roundedAdjustPoint_z = round(adjustPoint_z); + float2 roundedPointDiff = -roundedAdjustPoint.yx - round(adjustPoint_z); + adjustPoint.xy = roundedAdjustPoint.xy < adjustPoint.xy ? adjustPoint.xy - roundedAdjustPoint.xy : roundedAdjustPoint.xy - adjustPoint.xy; + adjustPoint_z = roundedAdjustPoint_z < adjustPoint_z ? adjustPoint_z - roundedAdjustPoint_z : roundedAdjustPoint_z - adjustPoint_z; + adjustPoint.xy = adjustPoint_z < adjustPoint.xy ? adjustPoint.yx < adjustPoint.xy : 0; + + float alternatePointY = adjustPoint.y ? roundedPointDiff.y : roundedAdjustPoint.y; + float2 correctedCoords = roundedAdjustPoint.x + roundedAdjustPoint.y + roundedAdjustPoint_z != 0.000000 ? (adjustPoint.xx ? float2(roundedPointDiff.x, roundedAdjustPoint.y) : float2(roundedAdjustPoint.x, alternatePointY)) : roundedAdjustPoint.xy; + + float2 randomSampleCoords = float2(0.001953125,0.001953125) * correctedCoords.xy; + float random_num = tex2Dlod(_NoiseTex, float4(randomSampleCoords.xy, 0, 0)).x; + + + int bitmask; + float cutOut = 0; + if (hexPctComplete - random_num * 0.999 < 0.00005) { + if (isDysonMap) { + float2 pixelPos = (_ScreenParams.xy * (i.screenPos.xy / i.screenPos.ww)); + pixelPos = (int2)pixelPos; + bitmask = ((~(-1 << 2)) << 2) & 0xffffffff; // 12 + cutOut = (((uint)pixelPos.x << 2) & bitmask) | ((uint)0 & ~bitmask); + bitmask = ((~(-1 << 2)) << 0) & 0xffffffff; // 3 + cutOut = (((uint)pixelPos.y << 0) & bitmask) | ((uint)cutOut & ~bitmask); + if (0.2499 - (icb[cutOut].x * 0.0588) < 0) discard; + cutOut = 1; + } else { + if (-1 != 0) discard; + cutOut = 0; + } + } else { + cutOut = 0; + } + + float2 triPosAdjusted; + triPosAdjusted.x = triangleVertPos.x / _Scale + (2.0 * axialCoords.x - axialCoords.y) / 3.0; + triPosAdjusted.y = triangleVertPos.y / _Scale + (axialCoords.x + axialCoords.y) / 3.0; + + float lodBias = min(4, max(0, log(0.0001 * distancePosToCamera))); + + float4 albedoTex = tex2Dbias(_MainTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + + float4 normalTex = tex2Dbias(_NormalTex, float4(triangleVertPos.xy, 0, lodBias)).xyzw; + float3 unpackedNormal = UnpackNormal(normalTex); + + float2 msTex = tex2D(_MSTex, triangleVertPos.xy).xw; + + float3 emissionTex_A = tex2Dbias(_EmissionTex, float4(triangleVertPos.xy, 0, lodBias)).xyz; + float3 emissionTex_B = tex2Dbias(_EmissionTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).xyz; + + float3 emissionTex = lerp(emissionTex_A.xyz, emissionTex_B.xyz, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float3 emissionTexTwo = tex2Dbias(_EmissionTex2, float4(triPosAdjusted.xy, 0, lodBias)).xyz; + + float colorControlTex_A = tex2Dbias(_ColorControlTex, float4(triangleVertPos.xy, 0, lodBias)).x; + float colorControlTex_B = tex2Dbias(_ColorControlTex, float4(float2(1,1) - triangleVertPos.yx, 0, lodBias)).x; + float colorControlTex = lerp(colorControlTex_A, colorControlTex_B, sin(_Time.y + _Time.y) * 0.5 + 0.5); + float colorControlTexTwo = tex2Dbias(_ColorControlTex2, float4(triPosAdjusted.xy, 0, lodBias)).x; + + unpackedNormal.xy = (-1.5 * _NormalMultiplier) * unpackedNormal.xy; + float3 worldNormal = normalize(i.normal.xyz * unpackedNormal.z + i.tangent.xyz * unpackedNormal.x + i.binormal.xyz * unpackedNormal.y); + + float3 triPosNew; + triPosNew.x = 1.0 - abs(frac(0.5 * (0.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + triPosNew.y = 1.0 - abs(frac(0.5 * (0 + triPosAdjusted.y)) * 2.0 - 1.0); + triPosNew.z = 1.0 - abs(frac(0.5 * (1.6666666 + triPosAdjusted.x)) * 2.0 - 1.0); + + float2 newPosOne; + newPosOne.x = ((triPosNew.x + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosOne.y = (triPosNew.y - triPosNew.x) / sqrt(2); + + float2 newPosTwo; + newPosTwo.x = ((triPosNew.z + triPosNew.y) / sqrt(2)) / sqrt(3); + newPosTwo.y = (triPosNew.y - triPosNew.z) / sqrt(2); + + float3 viewDir = normalize(rayPosToCamera); + bool viewingSunFacingSide = dot(i.normal.xyz, viewDir.xyz) < 0; + + float emissionAnim = saturate(30.0 * (0.05 - abs(length(newPosOne.xy) - frac(2.9 * _Time.x)))) * min(1, 5 * (1 - frac(2.9 * _Time.x))) + + saturate(30.0 * (0.05 - abs(length(newPosTwo.xy) - frac(_Time.x * 3.7 + 0.5)))) * min(1, 5 * (1 - frac(_Time.x * 3.7 + 0.5))); + emissionAnim = viewingSunFacingSide ? saturate((emissionTexTwo.y * 2 + emissionTex.y) * emissionAnim) : 0; + + float3 dysonEmission = viewingSunFacingSide ? _DysonEmission.xyz : float3(1,1,1); + float colorControl = saturate(colorControlTex + colorControlTexTwo); + float3 colorOutwardFacing = lerp(colorControl * i.color.xyz, i.color.xyz, 0.01 / _EmissionMultiplier); + float3 emissionOutwardFacing = lerp(emissionTexTwo.xyz * float3(0.3, 0.3, 0.3) + emissionTex.xyz, colorOutwardFacing, i.color.w); + float3 emissionSunFacing = float3(3,3,3) * (emissionTexTwo.x + emissionTex.x) * dysonEmission.xyz; + float3 emission = viewingSunFacingSide ? emissionSunFacing.xyz : emissionOutwardFacing.xyz; + + emission = _EmissionMultiplier * lerp(emission.xyz, dysonEmission.xyz, emissionAnim); + + float3 albedo = _AlbedoMultiplier * albedoTex.xyz * lerp(float3(1,1,1), albedoTex.xyz, saturate(1.25 * (albedoTex.w - 0.1))); + float specularStrength = dot(albedo, float3(0.3, 0.6, 0.1)); + + float scaledDistancePosToCamera = isMenuDemo ? distancePosToCamera : isDysonOrStarMap ? 3999.9998 * distancePosToCamera : distancePosToCamera; + float scaleMetallic = isMenuDemo ? 0.1 : isDysonOrStarMap ? 0.93 : 0.7; + scaleMetallic = saturate(pow(0.25 * log(scaledDistancePosToCamera + 1) - 1.5, 3.0)) * scaleMetallic; + float multiplyEmission = isDysonMap ? 2.2 : isDysonOrStarMap ? 1.8 : 2.5; + + float3 shellColor = i.color.w > 0.5 ? i.color.xyz : (asint(_Global_DS_PaintingLayerId) == asint(_LayerId) ? float3(0, 0.3, 0.65) : float3(0, 0.8, 0.6)); + float3 shellEmissionColor = lerp(emission.xyz * multiplyEmission, shellColor, 0.8 * cutOut); + + specularStrength = _State > 0.5 ? 0 : 0.8 * specularStrength * (1.0 - cutOut); + float fadeOut = _State > 0.5 ? 0 : 0.03 * (1.0 - cutOut); + float metallic = _State > 0.5 ? 0 : msTex.x * (1.0 - scaleMetallic); + float smoothness = _State > 0.5 ? 0.5 : min(0.8, msTex.y); + + float3 defaultColor = isDysonMap ? i.color.xyz * (viewingSunFacingSide ? 2 : 1.5) : float3(0,0,0); + float3 highStateColor = i.color.w > 0.5 ? defaultColor : float3(2.59, 0.0525, 0.0875); + float3 medStateColor = i.color.w > 0.5 ? defaultColor : float3(0.525,0.875, 3.5); + float3 lowStateColor = i.color.w > 0.5 ? defaultColor : float3(0.35, 0.7, 3.5); + float3 zeroStateColor = i.color.w > 0.5 ? defaultColor : float3(1.05, 1.05, 1.05); + float3 finalColor = 3.5 < _State ? highStateColor : + 2.5 < _State ? medStateColor : + 1.5 < _State ? lowStateColor : + 0.5 < _State ? zeroStateColor : + shellEmissionColor; + + float emissionFactor = (int)(_State > 0.5) | (int)(cutOut > 0.5) ? (1.0 / _EmissionMultiplier) : saturate(colorControlTex + colorControlTexTwo.x); + float metallicFactor = saturate(metallic * 0.85 + 0.149); + + float perceptualRoughness = min(1, 1 - smoothness * 0.97); + float roughness = perceptualRoughness * perceptualRoughness; + float roughnessSqr = roughness * roughness; + + float NdotV = viewingSunFacingSide ? -dot(worldNormal.xyz, viewDir.xyz) : dot(worldNormal.xyz, viewDir.xyz); + worldNormal.xyz = viewingSunFacingSide ? -worldNormal.xyz : worldNormal.xyz; + + float3 lightDir = -i.normal.xyz; + float3 halfDir = normalize(normalize(rayPosToCamera) + lightDir.xyz); + + float NdotL = dot(worldNormal.xyz, lightDir.xyz); + float NdotH = dot(worldNormal.xyz, halfDir.xyz); + float VdotH = dot(viewDir, halfDir.xyz); + float clamp_NdotL = max(0, NdotL); + float clamp_NdotH = max(0, NdotH); + float clamp_VdotH = max(0, VdotH); + + float D = 0.25 * pow(rcp(clamp_NdotH * clamp_NdotH * (roughnessSqr - 1) + 1),2) * roughnessSqr; + + float gv = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, NdotV); + float gl = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1.0, clamp_NdotL); + float G = rcp(gv * gl); + + float fk = exp2((clamp_VdotH * -5.55472994 - 6.98316002) * clamp_VdotH); + float F = lerp(0.5 + metallicFactor, 1.0, fk); + + float sunStrength = isInGame ? pow(saturate(1.05 + dot(normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz), i.normal.xyz)), 0.4) : 1.0; + float3 sunColor = float3(1.5625,1.5625,1.5625) * _SunColor.xyz; + float intensity = saturate(pow(NdotL * 0.6 + 1, 3)); + float3 sunColorIntensity = float3(0.07, 0.07, 0.07) * _SunColor * (intensity * 1.5 + 1) * intensity; + float3 sunSpecular = sunColor.xyz * clamp_NdotL * specularStrength; + + float3 finalLight = lerp(1, specularStrength, metallicFactor) * fadeOut * sunColor.xyz * (F * D * G + (0.1 / UNITY_PI)) * clamp_NdotL; + finalLight = finalLight.xyz * lerp(metallicFactor, 1, specularStrength * 0.2); + finalLight = float3(5,5,5) * lerp(float3(1,1,1), _SunColor, float3(0.3,0.3,0.3)) * finalLight.xyz; + finalLight = (sunColorIntensity.xyz * specularStrength * (1 - metallicFactor * 0.6) + sunSpecular.xyz * pow(1 - metallicFactor, 0.6) + finalLight.xyz) * sunStrength; + + float finalStength = dot(finalLight, float3(0.3, 0.6, 0.1)); + float3 normalizedLight = finalLight / finalStength; + float megaLog = log(log(log(log(log(log(log(log(finalStength / 0.32) + 1) + 1) + 1) + 1) + 1) + 1) + 1) + 1; + finalLight = 0.32 < finalStength ? normalizedLight * megaLog * 0.32 : finalLight; + + float finalAlpha = _EmissionMultiplier * emissionFactor; + o.sv_target.xyzw = float4(finalColor, 0.0) + float4(finalLight, finalAlpha); + + return o; + } + ENDCG + } + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/thunderstore/dysonopt.png b/thunderstore/dysonopt.png new file mode 100644 index 0000000000000000000000000000000000000000..af58364b8a841c4097daf8a9d49a30de640095cd GIT binary patch literal 142860 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�Fd=%V{)00XKE9X22HU{tM-T(4p@i^3Kffa<1 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%0D9Z}WkzUy)8nphD+Pems8pB7pQEjlp%Y>hI~{(& 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