diff --git a/README.md b/README.md
index 545b4a0..50bbf7b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# SphereOpt
-**SphereOpt v0.8.1 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.**
+**SphereOpt v0.8.2 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).
@@ -13,6 +13,9 @@ In a new game with a large and densely packed sphere containing 5,240 shells, fr
- does not support painting/colors on shells. this was just an additional layer of complexity that I haven't dug into yet. planning to have this in before 1.0.
## Changelog
+- v0.8.2
+ - fixes bright green glow on unbuilt frames/nodes in the dyson sphere editor
+ - slight performance increase
- v0.8.1
- fixes error when using shells on the 10th dyson sphere layer.
- v0.8.0
diff --git a/SphereOpt.csproj b/SphereOpt.csproj
index 575aa55..a36c76a 100644
--- a/SphereOpt.csproj
+++ b/SphereOpt.csproj
@@ -4,7 +4,7 @@
net472
SphereOpt
Optimize Dyson Sphere rendering
- 0.8.1
+ 0.8.2
true
latest
x64
diff --git a/shaders/CGIncludes/DSPCommon.cginc b/shaders/CGIncludes/DSPCommon.cginc
new file mode 100644
index 0000000..bb43f86
--- /dev/null
+++ b/shaders/CGIncludes/DSPCommon.cginc
@@ -0,0 +1,107 @@
+#include "UnityCG.cginc"
+
+struct GPUOBJECT
+{
+ uint objId;
+ float3 pos;
+ float4 rot;
+};
+
+struct AnimData
+{
+ float time;
+ float prepare_length;
+ float working_length;
+ uint state;
+ float power;
+};
+
+inline float3 rotate_vector_fast(float3 v, float4 r){
+ return v + cross(2.0 * r.xyz, cross(r.xyz, v) + r.w * v);
+}
+
+inline float SchlickFresnel_Approx(float F0, float vDotH)
+{
+ return F0 + (1 - F0) * exp2((-5.55473 * vDotH - 6.98316) * vDotH);
+}
+
+inline float3 calculateLightFromHeadlamp(float4 headlampPos, float3 upDir, float3 lightDir, float3 worldNormal) {
+ float isHeadlampOn = headlampPos.w >= 0.5 ? 1.0 : 0.0;
+ if (headlampPos.w < 0.5) return float3(0, 0, 0);
+
+ float distanceFromHeadlamp = length(headlampPos) - 5.0;
+ float headlampVisibility = saturate(distanceFromHeadlamp);
+ float daylightDimFactor = saturate(dot(-upDir, lightDir) * 5.0);
+
+ float3 directionToPlayer = headlampPos - upDir * distanceFromHeadlamp;
+ float distObjToPlayer = length(directionToPlayer);
+ directionToPlayer /= distObjToPlayer;
+
+ float falloff = pow(max((20.0 - distObjToPlayer) * 0.05, 0), 2);
+ float3 lightColor = float3(1.3, 1.1, 0.6);
+
+ float lightIntensity = headlampVisibility * daylightDimFactor * falloff * saturate(dot(directionToPlayer, worldNormal));
+ float3 computedLight = lightIntensity * lightColor;
+
+ return distObjToPlayer < 0.001 ? daylightDimFactor * lightColor : computedLight;
+}
+
+inline float distributionGGX(float roughness, float nDotH) {
+ float a = roughness; //NDF formula says `a` should be roughness^2
+ //"We also adopted Disney’s reparameterization of α = Roughness2."
+ //but a = Roughness here
+ float denom = rcp(nDotH * nDotH * (a * a - 1.0) + 1); //r0.w
+ return denom * denom * a * a; //r0.w
+ //missing (1/PI) *
+}
+
+inline float geometrySchlickGGX(float roughness, float nDotV, float nDotL) {
+ float k = pow(roughness * roughness + 1.0, 2) * 0.125; //r2.w does "roughness" mean perceptualroughness^2 or ^4?
+ //"We also chose to use Disney’s modification to reduce “hotness” by remapping roughness using (Roughness+1)/2 before squaring."
+ //but this is doing (Roughness^2+1)/2 before squaring
+ float ggxNV = nDotV * (1.0 - k) + k; //r5.x
+ float ggxNL = nDotL * (1.0 - k) + k; //r1.z
+ return rcp(ggxNL * ggxNV); //r1.x
+ //missing (nDotL * nDotV) *
+}
+
+inline float GGX(float roughness, float metallic, float nDotH, float nDotV, float nDotL, float vDotH) {
+
+ float D = distributionGGX(roughness, nDotH);
+ float G = geometrySchlickGGX(roughness, nDotV, nDotL); //r1.x
+ float F = SchlickFresnel_Approx(metallic, vDotH);
+
+ return (D * F * G) / 4.0;
+ //should be (4.0 * nDotV * nDotL)
+}
+
+inline float3 calculateBinormal(float4 tangent, float3 normal ) {
+ float sign = tangent.w * unity_WorldTransformParams.w;
+ float3 binormal = cross(normal.xyz, tangent.xyz) * sign;
+ return binormal;
+}
+
+UNITY_DECLARE_TEXCUBE(_Global_PGI);
+
+/* What image is reflected in metallic surfaces and how reflective is it? */
+inline float3 reflection(float perceptualRoughness, float3 metallicLow, float3 upDir, float3 viewDir, float3 worldNormal, out float reflectivity) {
+ float upDirMagSqr = dot(upDir, upDir);
+ bool validUpDirY = upDirMagSqr > 0.01 && upDir.y < 0.9999;
+ float3 xaxis = validUpDirY ? normalize(cross(upDir.zxy, float3(0, 0, 1))) : float3(0, 1, 0);
+ bool validUpDirXY = dot(xaxis, xaxis) > 0.01 && upDirMagSqr > 0.01;
+ float3 zaxis = validUpDirXY ? normalize(cross(xaxis.yzx, upDir)) : float3(0, 0, 1);
+
+ float3 worldReflect = reflect(-viewDir, worldNormal);
+ float3 reflectDir;
+ reflectDir.x = dot(worldReflect.zxy, -xaxis);
+ reflectDir.y = dot(worldReflect, upDir);
+ reflectDir.z = dot(worldReflect, -zaxis);
+
+ float reflectLOD = 10.0 * pow(perceptualRoughness, 0.4);
+ float3 g_PGI = UNITY_SAMPLE_TEXCUBE_LOD(_Global_PGI, reflectDir, reflectLOD);
+
+ float scaled_metallicLow = metallicLow * 0.7 + 0.3;
+ reflectivity = scaled_metallicLow * (1.0 - perceptualRoughness);
+
+ return g_PGI * reflectivity;
+}
\ No newline at end of file
diff --git a/shaders/Frame Inst REPLACE.shader b/shaders/Frame Inst REPLACE.shader
index 0a2446c..5efb8f3 100644
--- a/shaders/Frame Inst REPLACE.shader
+++ b/shaders/Frame Inst REPLACE.shader
@@ -1,16 +1,9 @@
Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
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" {}
- _Size ("Size", Float) = 400
- _Thickness ("Thickness", Float) = 100
- _AlbedoMultiplier ("漫反射倍率", Float) = 1
- _NormalMultiplier ("法线倍率", Float) = 1
- _EmissionMultiplier ("自发光倍率", Float) = 5.5
- _AlphaClip ("透明通道剪切", Float) = 0
}
SubShader {
LOD 200
@@ -23,8 +16,9 @@ Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
+ #include "CGIncludes/DSPCommon.cginc"
#pragma target 5.0
- //#pragma enable_d3d11_debug_symbols
+ #pragma enable_d3d11_debug_symbols
struct Segment {
uint layer;
@@ -63,11 +57,6 @@ Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
float4 _SunColor;
float4 _DysonEmission;
- float4 _Color;
- float _AlbedoMultiplier;
- float _NormalMultiplier;
- float _EmissionMultiplier;
- float _AlphaClip;
int _Global_DS_EditorMaskL;
int _Global_DS_GameMaskL;
int _Global_DS_HideFarSide;
@@ -124,10 +113,10 @@ Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
float3 worldPos = mul(unity_ObjectToWorld, float4(vertPos.xyz, 1));
float3 worldNormal = normalize(mul((float3x3)unity_ObjectToWorld, objNormal.xyz));
float3 worldTangent = normalize(mul((float3x3)unity_ObjectToWorld, objTangent.xyz));
- float3 worldBinormal = cross(worldNormal.xyz, worldTangent.xyz) * unity_WorldTransformParams.w * v.tangent.w;
+ float3 worldBinormal = calculateBinormal(float4(worldTangent, v.tangent.w), worldNormal);
float invFrameRadius = rsqrt(dot(vertPos.xyz, vertPos.xyz));
- float falloffDistance = pow(1 + min(4, max(0, (5000 * invFrameRadius) - 0.2)), 2);
+ float falloffDistance = pow(1 + min(4, max(0, 5000 * invFrameRadius - 0.2)), 2);
uint renderPlace = asuint(_Global_DS_RenderPlace);
@@ -135,7 +124,8 @@ Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
float3 rayViewToPos = worldPos.xyz - _WorldSpaceCameraPos.xyz;
float distViewToPos = length(rayViewToPos.xyz);
- float scaled_distViewToPos = 10000 * (log(0.0001 * distViewToPos) + 1) / distViewToPos;
+ //float scaled_distViewToPos = 10000 * (log(0.0001 * distViewToPos) + 1) / distViewToPos;
+ float scaled_distViewToPos = (10000.0 * log(distViewToPos) - 82103.4) / distViewToPos;
rayViewToPos.xyz = distViewToPos > 10000 ? rayViewToPos.xyz * scaled_distViewToPos : rayViewToPos.xyz;
worldPos = _WorldSpaceCameraPos.xyz + rayViewToPos.xyz;
@@ -169,202 +159,171 @@ Shader "VF Shaders/Dyson Sphere/Frame Inst REPLACE" {
fout frag(v2f i, float4 screenPos : SV_POSITION)
{
- fout o;
-
- const float4 icb[16] = { { 1.000000, 0, 0, 0},
- { 9.000000, 0, 0, 0},
- { 3.000000, 0, 0, 0},
- { 11.000000, 0, 0, 0},
- { 13.000000, 0, 0, 0},
- { 5.000000, 0, 0, 0},
- { 15.000000, 0, 0, 0},
- { 7.000000, 0, 0, 0},
- { 4.000000, 0, 0, 0},
- { 12.000000, 0, 0, 0},
- { 2.000000, 0, 0, 0},
- { 10.000000, 0, 0, 0},
- { 16.000000, 0, 0, 0},
- { 8.000000, 0, 0, 0},
- { 14.000000, 0, 0, 0},
- { 6.000000, 0, 0, 0} };
-
- float layer = round(i.lightray_layer.w);
- layer = (uint)layer;
-
- float shift_layer = 1 << (int)layer;
-
- float gameMask = (int)shift_layer & asint(_Global_DS_GameMaskL);
- float editorMask = (int)shift_layer & asint(_Global_DS_EditorMaskL);
-
- float3 worldPos;
- worldPos.x = i.tbnw_matrix_x.w;
- worldPos.y = i.tbnw_matrix_y.w;
- worldPos.z = i.tbnw_matrix_z.w;
-
- float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos.xyz);
- float3 lightDir = normalize(_Global_DS_SunPosition_Map.xyz - worldPos.xyz);
- float VdotL = dot(viewDir, lightDir);
-
- bool shouldHide = asuint(_Global_DS_HideFarSide) > 0.5 && VdotL > 0;
- bool notPaintingLayer = (int)layer != asint(_Global_DS_PaintingLayerId) && asuint(_Global_DS_PaintingLayerId) > 0;
- uint renderPlace = asuint(_Global_DS_RenderPlace);
- if ((renderPlace < 1.5 && (uint)gameMask <= 0) || notPaintingLayer || shouldHide || (uint)editorMask <= 0) discard;
-
- float3 mstex = tex2D(_MSTex, i.u_v_index.xy).xwy;
+ fout o;
+
+ int layer = round(i.lightray_layer.w);
+ int layerMask = 1 << layer;
+
+ bool showLayerInGame = (layerMask & asint(_Global_DS_GameMaskL)) > 0;
+ bool showLayerInEditor = (layerMask & asint(_Global_DS_EditorMaskL)) > 0;
+
+ float3 worldPos;
+ worldPos.x = i.tbnw_matrix_x.w;
+ worldPos.y = i.tbnw_matrix_y.w;
+ worldPos.z = i.tbnw_matrix_z.w;
+
+ float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
+ float3 lightDir = normalize(-i.lightray_layer.xyz);
+
+ bool isFarSide = dot(viewDir, lightDir) > 0;
+ bool hideFarSide = asuint(_Global_DS_HideFarSide) > 0.5;
+ hideFarSide = hideFarSide && isFarSide;
+ bool isPainting = asuint(_Global_DS_PaintingLayerId) > 0;
+ bool notPaintingLayer = layer != asint(_Global_DS_PaintingLayerId);
+ bool hideNotPaintingLayer = notPaintingLayer && isPainting;
+
+ bool showInEditor = !(hideNotPaintingLayer || hideFarSide) && showLayerInEditor;
+
+ uint renderPlace = asuint(_Global_DS_RenderPlace);
+ bool isShowing = renderPlace < 1.5 ? showLayerInGame : showInEditor;
+ if (!isShowing) discard;
+
+ uint instIndex = (uint)(i.u_v_index.z + 0.5);
+
+ uint state = _InstBuffer[instIndex].state;
+ float progress0 = _InstBuffer[instIndex].progress0;
+ float progress1 = _InstBuffer[instIndex].progress1;
+ float progress = progress0 + progress1;
- if (mstex.z < _AlphaClip - 0.001) discard;
-
- uint instIndex = (uint)(i.u_v_index.z + 0.5);
- uint state = _InstBuffer[instIndex].state;
- float progress0 = _InstBuffer[instIndex].progress0;
- float progress1 = _InstBuffer[instIndex].progress1;
-
- uint2 bitmask;
- float progress = progress0 + progress1;
- float cutOut = 0;
- if (progress < 0.01) {
+ float isPlanned = 0;
+ if (progress < 0.01) {
+ if (renderPlace > 1.5) {
+ if (state < 0.5) {
+ uint2 pixelPos = screenPos.xy;
+ int mask = (pixelPos.x & 1) - (pixelPos.y & 1);
+ if (mask != 0) discard;
+ }
+ isPlanned = 1;
+ } else {
+ discard;
+ }
+ }
+
+ uint color = _InstBuffer[instIndex].color;
+ float4 gamma_color = ((asuint(color) >> int4(0,8,16,24)) & int4(255,255,255,255)) / 255.0;
+ float4 painted_color = float4(GammaToLinearSpace(gamma_color.xyz), gamma_color.w);
+
+ float3 emissionTex = tex2Dbias(_EmissionTex, float4(i.u_v_index.xy, 0, -1)).xyz;
+ float emissionLuminance = dot(emissionTex.xyz, float3(0.3, 0.6, 0.1));
+ float3 emissionColor = lerp(_DysonEmission.xyz * emissionLuminance, painted_color.xyz * emissionLuminance, painted_color.w);
+ float emissionBoost = renderPlace > 0.5 ? 9.0 : 6.0;
+ emissionColor = emissionColor * emissionBoost;
+
+ float3 albedo = tex2D(_MainTex, i.u_v_index.xy).xyz;
+ float albedoLuminance = dot(albedo.xyz, float3(0.3, 0.6, 0.1));
+
UNITY_BRANCH
if (renderPlace < 1.5) {
- discard;
+ float3 standardStrength = lerp(albedoLuminance, painted_color.xyz, painted_color.w * 0.2);
+ float3 boostedStrength = lerp(albedoLuminance, painted_color.xyz * albedoLuminance, painted_color.w * 0.2);
+ albedo = lerp(standardStrength, boostedStrength, 0.7);
+ } else {
+ albedoLuminance = albedoLuminance * (1.0 - isPlanned);
+ float3 standardStrength = lerp(albedoLuminance, painted_color.xyz, painted_color.w * 0.3);
+ float3 boostedStrength = lerp(albedoLuminance, painted_color.xyz * albedoLuminance, painted_color.w * 0.3);
+ albedo = lerp(standardStrength, boostedStrength, 0.6);
+
+ bool usePaintedColor = painted_color.w > 0.5;
+ float paintedColorLuminance = dot(painted_color.xyz, float3(0.3, 0.6, 0.1));
+ float paintedColorLumAdjust = min(1.0, 0.1 / paintedColorLuminance);
+
+ float3 dysonEditorDefaultColor = usePaintedColor ? painted_color.xyz : float3(0, 3, 0.75);
+ emissionColor = lerp(emissionColor, dysonEditorDefaultColor, isPlanned);
+
+ float3 dysonEditorPaintedTint = float3(5,5,5) * painted_color.xyz * paintedColorLumAdjust;
+ float3 dysonEditorHoverDeleteColor = float3(3.7, 0.075, 0.125);
+ dysonEditorHoverDeleteColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverDeleteColor;
+ float3 dysonEditorHoverWhileSelectedColor = float3(0.75, 1.25, 3.9);
+ dysonEditorHoverWhileSelectedColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverWhileSelectedColor;
+ float3 dysonEditorSelectedColor = float3(0.5, 1.0, 3.85);
+ dysonEditorSelectedColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorSelectedColor;
+ float3 dysonEditorHoverColor = float3(3.5, 2.0, 1.0);
+ dysonEditorHoverColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverColor;
+
+ emissionColor = state > 0.5 ? dysonEditorHoverColor : emissionColor; //state == 1 (hover select)
+ emissionColor = state > 1.5 ? dysonEditorSelectedColor : emissionColor; //state == 2 (selected)
+ emissionColor = state > 2.5 ? dysonEditorHoverWhileSelectedColor : emissionColor; //state == 3 (hover select while selected)
+ emissionColor = state > 3.5 ? dysonEditorHoverDeleteColor : emissionColor; //state == 4 (hover delete)
}
- else {
- if (state < 0.5) {
- int2 screen = (_ScreenParams.yx * screenPos.yx);
- bitmask.y = ((~(-1 << 2)) << 2) & 0xffffffff; screen.y = (((uint)screen.y << 2) & bitmask.y) | ((uint)0 & ~bitmask.y);
- bitmask.x = ((~(-1 << 2)) << 0) & 0xffffffff; screen.x = (((uint)screen.x << 0) & bitmask.x) | ((uint)screen.y & ~bitmask.x);
- screen.x = 0.499 - icb[bitmask.x].x * 0.0588235296;
- if (screen.x < 0) discard;
- }
- cutOut = 1;
- }
- }
-
- float4 maintex = tex2D(_MainTex, i.u_v_index.xy).xyzw;
- float3 normaltex = tex2Dbias(_NormalTex, float4(i.u_v_index.xy, 0, -1)).xyw;
-
- float3 unpackedNormal;
- normaltex.x = normaltex.x * normaltex.z;
- unpackedNormal.xy = normaltex.xy * float2(2,2) - float2(1,1);
- unpackedNormal.z = sqrt(1 - min(1, dot(unpackedNormal.xy, unpackedNormal.xy)));
- unpackedNormal.xy = _NormalMultiplier * unpackedNormal.xy;
-
- float3 emissiontex = tex2Dbias(_EmissionTex, float4(i.u_v_index.xy, 0, -1)).xyz;
- float3 emissionLuminance = dot(emissiontex.xyz, float3(0.3, 0.6, 0.1));
-
- uint color = _InstBuffer[instIndex].color;
-
- float4 gamma_color = ((asuint(color) >> int4(0,8,16,24)) & int4(255,255,255,255)) / 255.0;
- float4 linear_color = float4(GammaToLinearSpace(gamma_color.xyz), gamma_color.w);
-
- float3 emission = _EmissionMultiplier * lerp(_DysonEmission.xyz * emissionLuminance, linear_color.xyz * emissionLuminance, linear_color.www);
-
- float3 albedoColor = lerp(float3(1,1,1), _Color.xyz, saturate(1.25 * (maintex.w - 0.1))) * _AlbedoMultiplier * maintex.xyz;
-
-
- float3 tangentNormal = normalize(unpackedNormal);
-
- float emissionMod = renderPlace > 0.5 ? 4.5 : 3.0;
-
- float3 defaultColor = float3(0,0,0);
- float3 highStateColor = float3(0,0,0);
- float3 medStateColor = float3(0,0,0);
- float3 lowStateColor = float3(0,0,0);
- float3 finalColor;
-
- UNITY_BRANCH
- if (renderPlace < 1.5)
- {
- float albedoLuminance = dot(albedoColor.xyz, float3(0.3, 0.6, 0.1));
- float3 colorLerp1 = lerp(albedoLuminance, linear_color.xyz, linear_color.w * 0.2);
- float3 colorLerp2 = albedoLuminance * lerp(float3(1,1,1), linear_color.xyz, linear_color.w * 0.2);
- albedoColor.xyz = lerp(colorLerp1, colorLerp2, 0.7);
- finalColor = emission * emissionMod;
- }
- else
- {
- float albedoLuminance = dot(albedoColor.xyz, float3(0.3, 0.6, 0.1)) * (1.0 - cutOut);
- float3 colorLerp1 = lerp(albedoLuminance, linear_color.xyz, linear_color.w * 0.3);
- float3 colorLerp2 = albedoLuminance * lerp(float3(1,1,1), linear_color.xyz, linear_color.w * 0.3);
- albedoColor.xyz = lerp(colorLerp1, colorLerp2, 0.6);
- emission = lerp(emission * emissionMod, linear_color.w > 0.5 ? linear_color.xyz : float3(0, 3, 0.75), cutOut);
- defaultColor = float3(5,5,5) * linear_color.xyz * min(1, 0.1 / dot(linear_color.xyz, float3(0.3, 0.6, 0.1)));
- highStateColor = linear_color.w > 0.5 ? defaultColor : float3(3.7, 0.075, 0.125);
- medStateColor = linear_color.w > 0.5 ? defaultColor : float3(0.75, 1.25, 3.9);
- lowStateColor = linear_color.w > 0.5 ? defaultColor : float3(0.5, 1.0, 3.85);
- finalColor = linear_color.w > 0.5 ? defaultColor : float3(3.5, 2.0, 1.0);
-
- finalColor = state > 0.5 ? finalColor : emission;
- finalColor = state > 1.5 ? lowStateColor : finalColor;
- finalColor = state > 2.5 ? medStateColor : finalColor;
- finalColor = state > 3.5 ? highStateColor : finalColor;
- }
-
-
- float3 rayPosToCam = _WorldSpaceCameraPos.xyz - worldPos.xyz;
- float3 worldViewDir = normalize(rayPosToCam);
-
- //float shadowMaskAttenuation = UnitySampleBakedOcclusion(float2(0,0), worldPos);
-
- float3 worldNormal;
- worldNormal.x = dot(i.tbnw_matrix_x.xyz, tangentNormal);
- worldNormal.y = dot(i.tbnw_matrix_y.xyz, tangentNormal);
- worldNormal.z = dot(i.tbnw_matrix_z.xyz, tangentNormal);
- worldNormal.xyz = normalize(worldNormal.xyz);
-
- float lengthLightRay = length(i.lightray_layer.xyz);
-
- float metallic = saturate(mstex.x * 0.85 + 0.149);
- float perceptualRoughness = saturate(1 - mstex.y * 0.97);
-
- float roughness = pow(perceptualRoughness, 2);
- float roughnessSqr = pow(roughness, 2);
-
- float3 sunViewDir = normalize(float3(0,3,0) + _WorldSpaceCameraPos.xyz);
-
- float3 worldLightDir = -normalize(i.lightray_layer.xyz);
- float3 halfDir = normalize(worldViewDir + worldLightDir);
-
- float NdotV = dot(worldNormal.xyz, worldViewDir.xyz);
- float NdotSV = dot(worldNormal.xyz, sunViewDir.xyz);
- float NdotL = dot(worldNormal.xyz, worldLightDir.xyz);
- float NdotH = dot(worldNormal.xyz, halfDir.xyz);
- float VdotH = dot(worldViewDir.xyz, halfDir.xyz);
- float clamp_NdotL = max(0, NdotL);
- float clamp_NdotH = max(0, NdotH);
- float clamp_VdotH = max(0, VdotH);
- float clamp_NdotSV = max(0, NdotSV);
- float clamp_NdotV = max(0, NdotV);
-
- float D = 0.25 * pow(rcp(pow(clamp_NdotH,2) * (roughnessSqr - 1) + 1),2) * roughnessSqr;
-
- float gv = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1, clamp_NdotV);
- float gl = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1, clamp_NdotL);
- float G = rcp(gv * gl);
-
- float fk = exp2((-6.98316002 + clamp_VdotH * -5.55472994) * clamp_VdotH);
- float F = lerp(0.5 + metallic, 1, fk);
-
- float sunStrength = renderPlace < 0.5 ? pow(saturate(1.02 + dot(normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz), -worldLightDir.xyz)), 0.4) : 1;
- float3 sunColor = float3(1.25,1.25,1.25) * _SunColor.xyz * lengthLightRay;
- float intensity = renderPlace > 1.5 ? saturate(pow(NdotL * 0.5 + 0.6, 3)) + clamp_NdotSV : saturate(pow(NdotL * 0.5 + 0.6, 3));
- float3 sunLight = float3(0.2, 0.2, 0.2) * _SunColor.xyz * lerp(1, lengthLightRay, intensity) * intensity;
- float3 anotherLight = float3(0.3, 0.3, 0.3) * lerp(float3(1,1,1), albedoColor.xyz, metallic) * sunColor.xyz;
- float3 ggx = anotherLight.xyz * (F * D * G + (1.0 / (10 * UNITY_PI))) * clamp_NdotL;
-
- float3 finalLight = (sunLight.xyz * albedoColor.xyz * (1 - metallic * 0.6) + sunColor.xyz * clamp_NdotL * albedoColor.xyz * pow(1 - metallic, 0.6) + lerp(metallic, 1, albedoColor.xyz * 0.2) * ggx.xyz) * sunStrength;
-
- float luminance = dot(finalLight.xyz, float3(0.3, 0.6, 0.1));
-
- float3 lightNormalized = finalLight.xyz / luminance;
- float bigLog = log(log(luminance) + 1) + 1;
-
- finalLight.xyz = luminance > 1 ? lightNormalized.xyz * bigLog : finalLight.xyz;
-
- o.sv_target.xyz = finalLight.xyz + finalColor.xyz;
- o.sv_target.w = 1;
- return o;
+
+ float3 viewFromSunDir = normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz);
+ float sideInView = dot(viewFromSunDir.xyz, -lightDir); // 1 if top of frame is facing player, 0 if viewing side on, -1 if bottom of frame is facing player (directly behind sun)
+ float innerFalloff = pow(saturate(1.02 + sideInView), 0.4); // 1 until view side on, then falloff as we view the bottom of frame until it moves behind the star. minimum .2
+ innerFalloff = renderPlace < 0.5 ? innerFalloff : 1;
+
+ float3 unpackedNormal = UnpackNormal(tex2Dbias(_NormalTex, float4(i.u_v_index.xy, 0, -1)));
+ float3 tangentNormal = normalize(unpackedNormal);
+
+ float3 worldNormal;
+ worldNormal.x = dot(i.tbnw_matrix_x.xyz, tangentNormal);
+ worldNormal.y = dot(i.tbnw_matrix_y.xyz, tangentNormal);
+ worldNormal.z = dot(i.tbnw_matrix_z.xyz, tangentNormal);
+ worldNormal.xyz = normalize(worldNormal.xyz);
+
+ float nDotL = dot(worldNormal.xyz, lightDir.xyz);
+
+ float3 halfDir = normalize(viewDir + lightDir);
+
+ float ambientLightFalloff = saturate(pow(nDotL * 0.5 + 0.6, 3.0)); //expo: -1=0, 0=0.2, 0.8=1
+ float3 editorViewDir = normalize(float3(0,3,0) + _WorldSpaceCameraPos.xyz);//direction to camera but slightly higher
+ float editorNDotV = max(0, dot(worldNormal.xyz, editorViewDir));
+ ambientLightFalloff = renderPlace > 1.5 ? ambientLightFalloff + editorNDotV : ambientLightFalloff;
+
+ float nDotV = max(0, dot(worldNormal.xyz, viewDir.xyz));
+ float nDotH = max(0, dot(worldNormal.xyz, halfDir.xyz));
+ float vDotH = max(0, dot(viewDir.xyz, halfDir.xyz));
+ float clamped_nDotL = max(0, nDotL);
+
+ float2 msTex = tex2D(_MSTex, i.u_v_index.xy).xw;
+ float metallic = saturate(msTex.x * 0.85 + 0.149);
+ float perceptualRoughness = saturate(1 - msTex.y * 0.97);
+ float roughness = perceptualRoughness * perceptualRoughness;
+ float scaledMetallic = 0.5 + metallic;
+ float specularTerm = GGX(roughness, scaledMetallic, nDotH, nDotV, clamped_nDotL, vDotH);
+
+ float starLightStrength = length(i.lightray_layer.xyz);
+
+ float3 ambientLightStrength = lerp(1.0, starLightStrength, ambientLightFalloff);
+ float3 ambientLight = float3(0.2, 0.2, 0.2) * _SunColor.xyz * ambientLightStrength * ambientLightFalloff;
+ float3 ambientColor = ambientLight.xyz * albedo.xyz;
+
+ float3 sunColor = _SunColor.xyz * starLightStrength;
+ sunColor.xyz = float3(1.25, 1.25, 1.25) * sunColor.xyz;
+ float3 highlightColor = sunColor * clamped_nDotL * albedo.xyz;
+
+ float3 specularColor = float3(0.3, 0.3, 0.3) * lerp(float3(1,1,1), albedo.xyz, metallic);
+ specularColor = specularColor.xyz * sunColor;
+ float INV_TEN_PI = 0.0318309888;
+ specularColor.xyz = specularColor.xyz * clamped_nDotL * (specularTerm + INV_TEN_PI);
+
+ float3 specColorMod = 0.2 * albedo.xyz * (1.0 - metallic) + metallic;
+ specularColor = specularColor * specColorMod.xyz;
+
+ float3 finalColor = ambientColor.xyz * (1.0 - metallic * 0.6)
+ + highlightColor.xyz * pow(1.0 - metallic, 0.6)
+ + specularColor.xyz;
+ finalColor = finalColor.xyz * innerFalloff;
+
+ float finalColorLuminance = dot(finalColor.xyz, float3(0.3, 0.6, 0.1));
+ finalColor.xyz = finalColorLuminance > 1 ? (finalColor.xyz / finalColorLuminance) * (log(log(finalColorLuminance) + 1) + 1) : finalColor.xyz;
+
+ finalColor.xyz = finalColor.xyz + emissionColor;
+
+ o.sv_target.xyz = finalColor;
+ o.sv_target.w = 1;
+ return o;
}
ENDCG
}
}
-}
+}
\ No newline at end of file
diff --git a/shaders/Node Inst REPLACE.shader b/shaders/Node Inst REPLACE.shader
index 9f6f4ae..e2bc908 100644
--- a/shaders/Node Inst REPLACE.shader
+++ b/shaders/Node Inst REPLACE.shader
@@ -1,16 +1,9 @@
Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
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" {}
- _Size ("Size", Float) = 400
- _Thickness ("Thickness", Float) = 100
- _AlbedoMultiplier ("漫反射倍率", Float) = 1
- _NormalMultiplier ("法线倍率", Float) = 1
- _EmissionMultiplier ("自发光倍率", Float) = 5.5
- _AlphaClip ("透明通道剪切", Float) = 0
}
SubShader {
LOD 200
@@ -23,13 +16,9 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
- #include "AutoLight.cginc"
+ #include "CGIncludes/DSPCommon.cginc"
#pragma target 5.0
- //#pragma enable_d3d11_debug_symbols
-
- float3 rotate_vector_fast(float3 v, float4 r){
- return v + cross(2.0 * r.xyz, cross(r.xyz, v) + r.w * v);
- }
+ #pragma enable_d3d11_debug_symbols
struct Segment {
uint layer;
@@ -41,10 +30,6 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
int color;
};
- struct Layer {
- float4x4 objectToWorld;
- };
-
struct appdata_part {
float4 vertex : POSITION;
float4 tangent : TANGENT;
@@ -58,12 +43,10 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
float4 tbnw_matrix_x : TEXCOORD0;
float4 tbnw_matrix_y : TEXCOORD1;
float4 tbnw_matrix_z : TEXCOORD2;
- float4 screenPos : TEXCOORD3;
float4 u_v_radius_state : TEXCOORD4;
float4 lightray_layer : TEXCOORD5;
float2 progress : TEXCOORD6;
float4 color : TEXCOORD7;
- float4 shadowCoords : TEXCOORD8;
};
struct fout
@@ -76,11 +59,6 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
float4 _SunColor;
float4 _DysonEmission;
- float4 _Color;
- float _AlbedoMultiplier;
- float _NormalMultiplier;
- float _EmissionMultiplier;
- float _AlphaClip;
int _Global_DS_EditorMaskL;
int _Global_DS_GameMaskL;
int _Global_DS_HideFarSide;
@@ -146,8 +124,6 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
transformTangent.xyz = v.tangent.xxx * x_axis.xyz + transformTangent.xyz;
transformTangent.xyz = v.tangent.zzz * z_axis.xyz + transformTangent.xyz;
- //unity_ObjectToWorld = _ObjectToWorld;
-
float3 worldPos = mul(unity_ObjectToWorld, float4(transformPos.xyz, 1));
float3 worldNormal = mul((float3x3)unity_ObjectToWorld, transformNormal.xyz);
float3 worldTangent = mul((float3x3)unity_ObjectToWorld, transformTangent.xyz);
@@ -170,11 +146,9 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
worldNormal = normalize(worldNormal.xyz);
worldTangent = normalize(worldTangent.xyz);
- float3 worldBinormal = cross(worldNormal.xyz, worldTangent.xyz) * v.tangent.w * unity_WorldTransformParams.w;
+ float3 worldBinormal = calculateBinormal(float4(worldTangent, v.tangent.w), worldNormal);
+
- o.screenPos.xyzw = ComputeScreenPos(clipPos.xyzw);
- o.shadowCoords.xyz = ShadeSH9(float4(worldNormal.xyz, 1));
- o.shadowCoords.w = 1.0;
o.position.xyzw = clipPos.xyzw;
o.tbnw_matrix_x.x = worldTangent.x;
@@ -197,176 +171,159 @@ Shader "VF Shaders/Dyson Sphere/Node Inst REPLACE" {
return o;
}
- fout frag(v2f i)
+ fout frag(v2f i, float4 screenPos : SV_POSITION)
{
- const float4 icb[16] = { { 1.000000, 0, 0, 0},
- { 9.000000, 0, 0, 0},
- { 3.000000, 0, 0, 0},
- { 11.000000, 0, 0, 0},
- { 13.000000, 0, 0, 0},
- { 5.000000, 0, 0, 0},
- { 15.000000, 0, 0, 0},
- { 7.000000, 0, 0, 0},
- { 4.000000, 0, 0, 0},
- { 12.000000, 0, 0, 0},
- { 2.000000, 0, 0, 0},
- { 10.000000, 0, 0, 0},
- { 16.000000, 0, 0, 0},
- { 8.000000, 0, 0, 0},
- { 14.000000, 0, 0, 0},
- { 6.000000, 0, 0, 0} };
-
fout o;
- float layer = round(i.lightray_layer.w);
- layer = (uint)layer;
-
- float shift_layer = 1 << (int)layer;
- uint renderPlace = asuint(_Global_DS_RenderPlace);
- bool isInGameOrStarMap = renderPlace < 1.5;
-
- float gameMask = (int)shift_layer & asint(_Global_DS_GameMaskL);
- float editorMask = (int)shift_layer & asint(_Global_DS_EditorMaskL);
+ int layer = round(i.lightray_layer.w);
+ int layerMask = 1 << layer;
+
+ bool showLayerInGame = (layerMask & asint(_Global_DS_GameMaskL)) > 0;
+ bool showLayerInEditor = (layerMask & asint(_Global_DS_EditorMaskL)) > 0;
float3 worldPos;
worldPos.x = i.tbnw_matrix_x.w;
worldPos.y = i.tbnw_matrix_y.w;
worldPos.z = i.tbnw_matrix_z.w;
- float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos.xyz);
- float3 lightDir = normalize(_Global_DS_SunPosition_Map.xyz - worldPos.xyz);
- float VdotL = dot(viewDir, lightDir);
+ float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
+ float3 lightDir = normalize(-i.lightray_layer.xyz);
- bool shouldHide = asuint(_Global_DS_HideFarSide) > 0.5 && VdotL > 0;
- bool notPaintingLayer = (int)layer != asint(_Global_DS_PaintingLayerId) && asuint(_Global_DS_PaintingLayerId) > 0;
- if ((isInGameOrStarMap && (uint)gameMask <= 0) || notPaintingLayer || shouldHide || (uint)editorMask <= 0) discard;
-
- float3 mstex = tex2D(_MSTex, i.u_v_radius_state.xy).xwy;
-
- if (mstex.z < _AlphaClip - 0.001) discard;
+ bool isFarSide = dot(viewDir, lightDir) > 0;
+ bool hideFarSide = asuint(_Global_DS_HideFarSide) > 0.5;
+ hideFarSide = hideFarSide && isFarSide;
+ bool isPainting = asuint(_Global_DS_PaintingLayerId) > 0;
+ bool notPaintingLayer = layer != asint(_Global_DS_PaintingLayerId);
+ bool hideNotPaintingLayer = notPaintingLayer && isPainting;
+
+ bool showInEditor = !(hideNotPaintingLayer || hideFarSide) && showLayerInEditor;
+
+ uint renderPlace = asuint(_Global_DS_RenderPlace);
+ bool isShowing = renderPlace < 1.5 ? showLayerInGame : showInEditor;
+ if (!isShowing) discard;
- uint2 bitmask;
- float cutOut = 0;
+ float isPlanned = 0;
if (i.progress.x < 0.01) {
- if (renderPlace > 1.5) {
- if (i.u_v_radius_state.w < 0.5) {
- int2 screen = _ScreenParams.yx * (i.screenPos.yx / i.screenPos.ww);
- bitmask.y = ((~(-1 << 2)) << 2) & 0xffffffff; screen.y = (((uint)screen.y << 2) & bitmask.y) | ((uint)0 & ~bitmask.y);
- bitmask.x = ((~(-1 << 2)) << 0) & 0xffffffff; screen.x = (((uint)screen.x << 0) & bitmask.x) | ((uint)screen.y & ~bitmask.x);
- screen.x = 0.499 - icb[screen.x].x / 17.0;
- if (screen.x < 0) discard;
+ if (renderPlace > 1.5) {
+ if (i.u_v_radius_state.w < 0.5) {
+ uint2 pixelPos = screenPos.xy;
+ int mask = (pixelPos.x & 1) - (pixelPos.y & 1);
+ if (mask != 0) discard;
+ }
+ isPlanned = 1;
+ } else {
+ discard;
}
- cutOut = 1;
- } else {
- if (-1 != 0) discard;
- }
}
- float4 maintex = tex2D(_MainTex, i.u_v_radius_state.xy).xyzw;
- float3 normaltex = tex2Dbias(_NormalTex, float4(i.u_v_radius_state.xy, 0, -1)).xyw;
-
- float3 unpackedNormal;
- normaltex.x = normaltex.x * normaltex.z;
- unpackedNormal.xy = normaltex.xy * float2(2,2) - float2(1,1);
- unpackedNormal.z = sqrt(1 - min(1, dot(unpackedNormal.xy, unpackedNormal.xy)));
- unpackedNormal.xy = _NormalMultiplier * unpackedNormal.xy;
- float3 tangentNormal = normalize(unpackedNormal);
-
+ float4 painted_color = i.color;
+
float3 emissiontex = tex2Dbias(_EmissionTex, float4(i.u_v_radius_state.xy, 0, -1)).xyz;
- float3 emissionTintGreen = dot(emissiontex.xyz, float3(0.3, 0.6, 0.1));
- float fade = min(1, 0.5 / dot(i.color.xyz, float3(0.3, 0.6, 0.1)));
- float3 emission = lerp(emissiontex.xyz, emissionTintGreen * i.color.xyz, i.color.www) * fade;
- float albedoAlpha = saturate(1.25 * (maintex.w - 0.1));
- float3 albedoColor = (1 - cutOut) * lerp(float3(1,1,1), _Color.xyz, albedoAlpha) * _AlbedoMultiplier * maintex.xyz;
-
- float adjustColorAlpha = isInGameOrStarMap ? 0.2 : 0.6;
- float colorAlpha = i.color.w * adjustColorAlpha;
- albedoColor.xyz = lerp(lerp(albedoColor.xyz, i.color.xyz, colorAlpha), lerp(albedoColor.xyz, i.color.xyz * albedoColor.xyz, colorAlpha), isInGameOrStarMap ? 0.7 : 1);
- emission.xyz = lerp(_EmissionMultiplier * emission.xyz, i.color.w > 0.5 ? i.color.xyz : float3(0, 3, 0.75), cutOut);
-
- float3 defaultColor = isInGameOrStarMap ? float3(0,0,0) : float3(5,5,5) * i.color.xyz * fade;
- float3 highStateColor = i.color.w > 0.5 ? defaultColor : isInGameOrStarMap ? float3(0,0,0) : float3(3.7, 0.075, 0.125);
- float3 medStateColor = i.color.w > 0.5 ? defaultColor : isInGameOrStarMap ? float3(0,0,0) : float3(0.75, 1.25, 3.9);
- float3 lowStateColor = i.color.w > 0.5 ? defaultColor : isInGameOrStarMap ? float3(0,0,0) : float3(0.5, 1, 3.85);
-
- float state = i.u_v_radius_state.w;
- float3 finalColor = i.color.w > 0.5 ? defaultColor : isInGameOrStarMap ? float3(0,0,0) : float3(3.5, 2, 1);
- finalColor = state > 0.5 ? finalColor : emission;
- finalColor = state > 1.5 ? lowStateColor : finalColor;
- finalColor = state > 2.5 ? medStateColor : finalColor;
- finalColor = state > 3.5 ? highStateColor : finalColor;
-
- float3 rayPosToCam = _WorldSpaceCameraPos.xyz - worldPos.xyz;
- float3 worldViewDir = normalize(rayPosToCam);
-
- float shadowMaskAttenuation = UnitySampleBakedOcclusion(float2(0,0), worldPos);
-
+ float3 emissionLuminance = dot(emissiontex.xyz, float3(0.3, 0.6, 0.1));
+ float paintedColorLuminance = dot(painted_color.xyz, float3(0.3, 0.6, 0.1));
+ float paintedColorLumAdjust = min(1, 0.5 / paintedColorLuminance);
+ float3 emissionColor = lerp(emissiontex.xyz, emissionLuminance * painted_color.xyz, painted_color.www) * paintedColorLumAdjust;
+
+ float3 albedo = tex2D(_MainTex, i.u_v_radius_state.xy).xyz;
+
+ UNITY_BRANCH
+ if (renderPlace < 1.5) {
+ float3 standardStrength = lerp(albedo, painted_color.xyz, painted_color.w * 0.2);
+ float3 boostedStrength = lerp(albedo, painted_color.xyz * albedo, painted_color.w * 0.2);
+ albedo = lerp(standardStrength, boostedStrength, 0.7);
+ } else {
+ albedo = albedo * (1.0 - isPlanned);
+ float3 standardStrength = lerp(albedo, painted_color.xyz, painted_color.w * 0.3);
+ float3 boostedStrength = lerp(albedo, painted_color.xyz * albedo, painted_color.w * 0.3);
+ albedo = lerp(standardStrength, boostedStrength, 0.6);
+
+ bool usePaintedColor = painted_color.w > 0.5;
+ float paintedColorLuminance = dot(painted_color.xyz, float3(0.3, 0.6, 0.1));
+ float paintedColorLumAdjust = min(1.0, 0.5 / paintedColorLuminance);
+
+ float3 dysonEditorDefaultColor = usePaintedColor ? painted_color.xyz : float3(0, 3, 0.75);
+ emissionColor = lerp(emissionColor, dysonEditorDefaultColor, isPlanned);
+
+ float3 dysonEditorPaintedTint = float3(5,5,5) * painted_color.xyz * paintedColorLumAdjust;
+ float3 dysonEditorHoverDeleteColor = float3(3.7, 0.075, 0.125);
+ dysonEditorHoverDeleteColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverDeleteColor;
+ float3 dysonEditorHoverWhileSelectedColor = float3(0.75, 1.25, 3.9);
+ dysonEditorHoverWhileSelectedColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverWhileSelectedColor;
+ float3 dysonEditorSelectedColor = float3(0.5, 1.0, 3.85);
+ dysonEditorSelectedColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorSelectedColor;
+ float3 dysonEditorHoverColor = float3(3.5, 2.0, 1.0);
+ dysonEditorHoverColor = usePaintedColor ? dysonEditorPaintedTint : dysonEditorHoverColor;
+
+ emissionColor = i.u_v_radius_state.w > 0.5 ? dysonEditorHoverColor : emissionColor; //state == 1 (hover select)
+ emissionColor = i.u_v_radius_state.w > 1.5 ? dysonEditorSelectedColor : emissionColor; //state == 2 (selected)
+ emissionColor = i.u_v_radius_state.w > 2.5 ? dysonEditorHoverWhileSelectedColor : emissionColor; //state == 3 (hover select while selected)
+ emissionColor = i.u_v_radius_state.w > 3.5 ? dysonEditorHoverDeleteColor : emissionColor; //state == 4 (hover delete)
+ }
+
+ float3 viewFromSunDir = normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz);
+ float sideInView = dot(viewFromSunDir.xyz, -lightDir); // 1 if top of frame is facing player, 0 if viewing side on, -1 if bottom of frame is facing player (directly behind sun)
+ float innerFalloff = pow(saturate(1.02 + sideInView), 0.4); // 1 until view side on, then falloff as we view the bottom of frame until it moves behind the star. minimum .2
+ innerFalloff = renderPlace < 0.5 ? innerFalloff : 1;
+
+ float3 unpackedNormal = UnpackNormal(tex2Dbias(_NormalTex, float4(i.u_v_radius_state.xy, 0, -1)));
+ float3 tangentNormal = normalize(unpackedNormal);
+
float3 worldNormal;
worldNormal.x = dot(i.tbnw_matrix_x.xyz, tangentNormal);
worldNormal.y = dot(i.tbnw_matrix_y.xyz, tangentNormal);
worldNormal.z = dot(i.tbnw_matrix_z.xyz, tangentNormal);
worldNormal.xyz = normalize(worldNormal.xyz);
+
+ float nDotL = dot(worldNormal.xyz, lightDir.xyz);
- float lengthLightRay = length(i.lightray_layer.xyz);
- float3 worldLightDir = -i.lightray_layer.xyz / lengthLightRay;
-
- float3 sunColor = _SunColor.xyz * lengthLightRay;
+ float3 halfDir = normalize(viewDir.xyz + lightDir.xyz);
+
+ float ambientLightFalloff = saturate(pow(nDotL * 0.5 + 0.6, 3.0)); //expo: -1=0, 0=0.2, 0.8=1
+ float3 editorViewDir = normalize(float3(0,3,0) + _WorldSpaceCameraPos.xyz);//direction to camera but slightly higher
+ float editorNDotV = max(0, dot(worldNormal.xyz, editorViewDir));
+ ambientLightFalloff = renderPlace > 1.5 ? ambientLightFalloff + editorNDotV : ambientLightFalloff;
+
+ float nDotV = max(0, dot(worldNormal.xyz, viewDir.xyz));
+ float nDotH = max(0, dot(worldNormal.xyz, halfDir.xyz));
+ float vDotH = max(0, dot(viewDir.xyz, halfDir.xyz));
+ float clamped_nDotL = max(0, nDotL);
- float metallic = saturate(mstex.x * 0.85 + 0.15);
+ float2 mstex = tex2D(_MSTex, i.u_v_radius_state.xy).xw;
+ float metallic = saturate(mstex.x * 0.85 + 0.149);
float perceptualRoughness = saturate(1 - mstex.y * 0.97);
-
- float3 halfDir = normalize(worldViewDir.xyz + worldLightDir.xyz);
-
- float roughness = pow(perceptualRoughness, 2);
- float roughnessSqr = pow(roughness, 2);
-
- float3 lightToCam = normalize(_WorldSpaceCameraPos.xyz - _Global_DS_SunPosition.xyz);
-
+ float roughness = perceptualRoughness * perceptualRoughness;
+ float scaledMetallic = 0.5 + metallic;
+ float specularTerm = GGX(roughness, scaledMetallic, nDotH, nDotV, clamped_nDotL, vDotH);
+
+ float starLightStrength = length(i.lightray_layer.xyz);
+
+ float3 ambientLightStrength = lerp(1.0, starLightStrength, ambientLightFalloff);
+ float3 ambientLight = float3(0.2, 0.2, 0.2) * _SunColor.xyz * ambientLightStrength * ambientLightFalloff;
+ float3 ambientColor = ambientLight.xyz * albedo.xyz;
+
+ float3 sunColor = _SunColor.xyz * starLightStrength;
sunColor.xyz = float3(1.25, 1.25, 1.25) * sunColor.xyz;
- float anotherFalloff = renderPlace < 0.5 ? pow(saturate(1.02 + dot(lightToCam.xyz, worldLightDir)), 0.4) : 1.0;
-
- float3 sunViewDir = normalize(float3(0,3,0) + _WorldSpaceCameraPos.xyz);
-
- float NdotV = dot(worldNormal.xyz, worldViewDir.xyz);
- float NdotL = dot(worldNormal.xyz, worldLightDir.xyz);
- float NdotH = dot(worldNormal.xyz, halfDir.xyz);
- float VdotH = dot(worldViewDir.xyz, halfDir.xyz);
- float NdotSV = dot(worldNormal.xyz, sunViewDir.xyz);
- float clamp_NdotV = max(0, NdotV);
- float clamp_NdotL = max(0, NdotL);
- float clamp_NdotH = max(0, NdotH);
- float clamp_VdotH = max(0, VdotH);
- float clamp_NdotSV = max(0, NdotSV);
-
- float NdotLFalloff = saturate(pow(NdotL * 0.5 + 0.6, 3));
- float lightFalloff = renderPlace > 1.5 ? NdotLFalloff + clamp_NdotSV : NdotLFalloff;
-
- sunColor.xyz = sunColor.xyz * shadowMaskAttenuation;
-
- float D = 0.25 * pow(rcp(pow(clamp_NdotH,2) * (roughnessSqr - 1) + 1),2) * roughnessSqr;
-
- float gv = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1, clamp_NdotV);
- float gl = lerp(pow(roughnessSqr + 1, 2) * 0.125, 1, clamp_NdotL);
- float G = rcp(gv * gl);
-
- float fk = exp2((-6.98316002 + clamp_VdotH * -5.55472994) * clamp_VdotH);
- float F = lerp(0.5 + metallic, 1, fk);
-
- float3 sunLight = float3(0.2, 0.2, 0.2) * _SunColor.xyz * lerp(1, lengthLightRay, lightFalloff) * lightFalloff;
- float3 anotherLight = float3(0.5, 0.5, 0.5) * lerp(float3(1,1,1), albedoColor.xyz, metallic) * sunColor.xyz;
- float3 ggx = anotherLight.xyz * (D * F * G + (1.0 / (10 * UNITY_PI))) * clamp_NdotL;
-
- float3 finalLight = (sunLight.xyz * albedoColor.xyz * (1 - metallic * 0.6) + sunColor.xyz * clamp_NdotL * albedoColor.xyz * pow(1 - metallic, 0.6) + lerp(metallic, 1, 0.2 * albedoColor) * ggx.xyz) * anotherFalloff;
-
- float lightStrength = dot(finalLight.xyz, float3(0.3, 0.6, 0.1));
-
- float3 normalizedLight = finalLight.xyz / lightStrength;
- float bigLog = log(log(lightStrength) + 1) + 1;
-
- finalLight.xyz = 1 < lightStrength ? normalizedLight.xyz * bigLog : finalLight.xyz;
-
- o.sv_target.xyz = albedoColor.xyz * i.shadowCoords.xyz + finalLight.xyz + finalColor.xyz;
- o.sv_target.w = 1;
+ float3 highlightColor = sunColor * clamped_nDotL * albedo.xyz;
+
+ float3 specularColor = float3(0.3, 0.3, 0.3) * lerp(float3(1,1,1), albedo.xyz, metallic);
+ specularColor = specularColor.xyz * sunColor;
+ float INV_TEN_PI = 0.0318309888;
+ specularColor.xyz = specularColor.xyz * clamped_nDotL * (specularTerm + INV_TEN_PI);
+
+ float3 specColorMod = 0.2 * albedo.xyz * (1.0 - metallic) + metallic;
+ specularColor = specularColor * specColorMod.xyz;
+
+ float3 finalColor = ambientColor.xyz * (1.0 - metallic * 0.6)
+ + highlightColor.xyz * pow(1.0 - metallic, 0.6)
+ + specularColor.xyz;
+ finalColor = finalColor.xyz * innerFalloff;
+ float finalColorLuminance = dot(finalColor.xyz, float3(0.3, 0.6, 0.1));
+ finalColor.xyz = finalColorLuminance > 1 ? (finalColor.xyz / finalColorLuminance) * (log(log(finalColorLuminance) + 1) + 1) : finalColor.xyz;
+
+ finalColor.xyz = finalColor.xyz + emissionColor;
+
+ o.sv_target.xyz = finalColor;
+ o.sv_target.w = 1;
return o;
}
ENDCG
diff --git a/thunderstore/manifest.json b/thunderstore/manifest.json
index 02d16d9..60bfe65 100644
--- a/thunderstore/manifest.json
+++ b/thunderstore/manifest.json
@@ -1,6 +1,6 @@
{
"name": "SphereOpt",
- "version_number": "0.8.1",
+ "version_number": "0.8.2",
"website_url": "https://github.com/andyoneal/SphereOpt",
"description": "Improves performance when rendering Dyson Spheres",
"dependencies": [