All of my custom shaders show pink but don’t show any error at all.
Is manually rewriting them in ShaderGraph really the only way to convert?
See this thing for instance, a whole afternoon and I am not even 1/3 of the way converting it:
Shader "Guedez/Terrain/AtlasShader"
{
Properties
{
_ALBH("Albedo(3) + Height (Array)", 2DArray) = "" {}
_NRSM("Normal(2) + Smooth + Metalic (Array)", 2DArray) = "" {}
_P___("Parallax + (3) (RGB)", 2D) = "black" {}
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
}
LOD 200
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
#pragma exclude_renderers gles
#pragma surface surf StandardDefaultGI fullforwardshadows vertex:vert
#pragma require 2darray
#pragma target 3.5
#include "UnityStandardUtils.cginc"
#include "UnityPBSLighting.cginc"
#pragma multi_compile HAS_HEIGHT _
#pragma multi_compile HAS_SECOND_TEXTURE HAS_THIRD_TEXTURE _
float2 hash2D2D (float2 s)
{
//magic numbers
return frac(sin(fmod(float2(dot(s, float2(127.1,311.7)), dot(s, float2(269.5,183.3))), 3.14159))*43758.5453);
}
//stochastic sampling
float4 tex2DStochastic(UNITY_ARGS_TEX2DARRAY(tex), float3 UV)
{
//triangle vertices and blend weights
//BW_vx[0...2].xyz = triangle verts
//BW_vx[3].xy = blend weights (z is unused)
float4x3 BW_vx;
//uv transformed into triangular grid space with UV scaled by approximation of 2*sqrt(3)
float2 skewUV = mul(float2x2 (1.0 , 0.0 , -0.57735027 , 1.15470054), UV.xy * 3.464);
//vertex IDs and barycentric coords
float2 vxID = float2 (floor(skewUV));
float3 barry = float3 (frac(skewUV), 0);
barry.z = 1.0-barry.x-barry.y;
BW_vx = ((barry.z>0) ?
float4x3(float3(vxID, 0), float3(vxID + float2(0, 1), 0), float3(vxID + float2(1, 0), 0), barry.zyx) :
float4x3(float3(vxID + float2 (1, 1), 0), float3(vxID + float2 (1, 0), 0), float3(vxID + float2 (0, 1), 0), float3(-barry.z, 1.0-barry.y, 1.0-barry.x)));
//calculate derivatives to avoid triangular grid artifacts
float2 dx = ddx(UV.xy);
float2 dy = ddy(UV.xy);
//blend samples with calculated weights
//mul(tex2D(tex, UV + hash2D2D(BW_vx[0].xy), dx, dy), BW_vx[3].x)//, dx, dy
return mul(UNITY_SAMPLE_TEX2DARRAY(tex, float3(UV + hash2D2D(BW_vx[0].xy), UV.z)), BW_vx[3].x) +
mul(UNITY_SAMPLE_TEX2DARRAY(tex, float3(UV + hash2D2D(BW_vx[1].xy), UV.z)), BW_vx[3].y) +
mul(UNITY_SAMPLE_TEX2DARRAY(tex, float3(UV + hash2D2D(BW_vx[2].xy), UV.z)), BW_vx[3].z);
}
half4 PBS(half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness, half3 normal, half3 viewDir, UnityLight light, UnityIndirect gi) {
half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
half3 halfDir = Unity_SafeNormalize(light.dir + viewDir);
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0
#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
// The amount we shift the normal toward the view vector is defined by the dot product.
half shiftAmount = dot(normal, viewDir);
normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
// A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
//normal = normalize(normal);
half nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
#else
half nv = abs(dot(normal, viewDir)); // This abs allow to limit artifact
#endif
half nl = saturate(dot(normal, light.dir));
half nh = saturate(dot(normal, halfDir));
half lv = saturate(dot(light.dir, viewDir));
half lh = saturate(dot(light.dir, halfDir));
// Diffuse term
half diffuseTerm = DisneyDiffuse(1, nl, lh, perceptualRoughness) * nl;
// Specular term
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
// BUT 1) that will make shader look significantly darker than Legacy ones
// and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
#if UNITY_BRDF_GGX
half V = SmithJointGGXVisibilityTerm(nl, nv, roughness);
half D = GGXTerm(nh, roughness);
#else
// Legacy
half V = SmithBeckmannVisibilityTerm(nl, nv, roughness);
half D = NDFBlinnPhongNormalizedTerm(nh, PerceptualRoughnessToSpecPower(perceptualRoughness));
#endif
half specularTerm = V * D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later
#ifdef UNITY_COLORSPACE_GAMMA
specularTerm = sqrt(max(1e-4h, specularTerm));
#endif
// specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
specularTerm = max(0, specularTerm * nl);
#if defined(_SPECULARHIGHLIGHTS_OFF)
specularTerm = 0.0;
#endif
// surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
half surfaceReduction;
#ifdef UNITY_COLORSPACE_GAMMA
surfaceReduction = 1.0 - 0.28 * roughness * perceptualRoughness; // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
#else
surfaceReduction = 1.0 / (roughness * roughness + 1.0); // fade \in [0.5;1]
#endif
// To provide true Lambert lighting, we need to be able to kill specular completely.
specularTerm *= any(specColor) ? 1.0 : 0.0;
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
half3 color = diffColor * (gi.diffuse + light.color * diffuseTerm)
+ specularTerm * light.color * FresnelTerm(specColor, lh)
+ surfaceReduction * gi.specular * FresnelLerp(specColor, grazingTerm, nv);
return half4(color, 1);
}
inline half4 LightingStandardDefaultGI(SurfaceOutputStandard s, half3 viewDir, UnityGI gi) {
s.Normal = normalize(s.Normal);
half oneMinusReflectivity;
half3 specColor;
s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
half outputAlpha;
s.Albedo = PreMultiplyAlpha(s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
half4 c = PBS(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
c.a = outputAlpha;
return c;
}
inline void LightingStandardDefaultGI_GI(SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi) {
LightingStandard_GI(s, data, gi);
}
struct appdata {
float4 vertex : POSITION; // The vertex position in model space.
float3 normal : NORMAL; // The vertex normal in model space.
float4 texcoord : TEXCOORD0; // The first UV coordinate.
float4 texcoord1 : TEXCOORD1; // The second UV coordinate.
float4 texcoord2 : TEXCOORD2; // The third UV coordinate.
float4 texcoord3 : TEXCOORD3; // The fourfth UV coordinate.
float4 texcoord4 : TEXCOORD4; // The fifth UV coordinate. // requires Unity 2018.2+
//float4 texcoord5 : TEXCOORD5; // The sixth UV coordinate. // requires Unity 2018.2+
//float4 texcoord6 : TEXCOORD6; // The seventh UV coordinate. // requires Unity 2018.2+
//float4 texcoord7 : TEXCOORD7; // The eigthieth UV coordinate. // requires Unity 2018.2+ // maximum amount of channels supported
float4 tangent : TANGENT; // The tangent vector in Model Space (used for normal mapping).
float4 color : COLOR; // Per-vertex color
};
struct Input {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float4 color : COLOR;
float2 tc0;
#if HAS_SECOND_TEXTURE
float2 tc1;
#endif
#if HAS_THIRD_TEXTURE
float2 tc1;
float2 tc2;
#endif
float _MainTexture;
float _MainTexture2;
float _MainTexture3;
float3 viewDir;
};
void vert(inout appdata v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
o.tc0 = v.texcoord.xy;
o._MainTexture = (int)v.texcoord3.x;
#if HAS_SECOND_TEXTURE
o.tc1 = v.texcoord1.xy;
o._MainTexture2 = (int)v.texcoord3.y;
#endif
#if HAS_THIRD_TEXTURE
o.tc1 = v.texcoord1.xy;
o.tc2 = v.texcoord2.xy;
o._MainTexture2 = (int)v.texcoord3.y;
o._MainTexture3 = (int)v.texcoord4.x;
#endif
}
sampler2D _P___;
UNITY_DECLARE_TEX2DARRAY(_ALBH);
UNITY_DECLARE_TEX2DARRAY(_NRSM);
float3 packNormal(fixed2 pnormal) {
//pnormal.rg = pow(pnormal.rg, 0.5);
fixed3 normal;
normal.x = (pnormal * 2) - 1;
normal.y = 0;
normal.z = sqrt(1 - normal.x * normal.x);
return normalize(normal);
//return UnpackNormal(float4(1, pnormal.x, pnormal.x, pnormal.y));
}
void surf(Input IN, inout SurfaceOutputStandard o) {
const half paralaxDiv = 10;
half len = tex2D(_P___, half2(0, 0)).g * 256.0;
//float4 tex2DStochastic(UNITY_PASS_TEX2DARRAY(_ALBH), float3(IN.tc0, IN._MainTexture))
fixed4 albh = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc0, IN._MainTexture));
half origH1;
IN.tc0 += ParallaxOffset(origH1 = albh.a, tex2D(_P___, half2((IN._MainTexture + 0.5) / len, 0.5)).r / paralaxDiv, IN.viewDir);
albh = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc0, IN._MainTexture));
fixed4 nrsm = pow(UNITY_SAMPLE_TEX2DARRAY(_NRSM, float3(IN.tc0 , IN._MainTexture)),0.5);
fixed3 normal = packNormal(nrsm.rg);
#if HAS_SECOND_TEXTURE
fixed4 albh2 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc1, IN._MainTexture2));
half origH2;
IN.tc1 += ParallaxOffset(origH2 = albh2.a, tex2D(_P___, half2((IN._MainTexture2 + 0.5) / len, 0.5)).r / paralaxDiv, IN.viewDir);
albh2 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc1, IN._MainTexture2));
fixed4 nrsm2 = pow(UNITY_SAMPLE_TEX2DARRAY(_NRSM, float3(IN.tc1 , IN._MainTexture2)),0.5);
fixed3 normal2 = packNormal(nrsm2.rg);
#endif
#if HAS_THIRD_TEXTURE
fixed4 albh2 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc1, IN._MainTexture2));
half origH2;
IN.tc1 += ParallaxOffset(origH2 = albh2.a, tex2D(_P___, half2((IN._MainTexture2 + 0.5) / len, 0.5)).r / paralaxDiv, IN.viewDir);
albh2 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc1, IN._MainTexture2));
fixed4 nrsm2 = pow(UNITY_SAMPLE_TEX2DARRAY(_NRSM, float3(IN.tc1 , IN._MainTexture2)),0.5);
fixed3 normal2 = packNormal(nrsm2.rg);
fixed4 albh3 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc2, IN._MainTexture3));
half origH3;
IN.tc2 += ParallaxOffset(origH3 = albh3.a, tex2D(_P___, half2((IN._MainTexture3 + 0.5) / len, 0.5)).r / paralaxDiv, IN.viewDir);
albh3 = UNITY_SAMPLE_TEX2DARRAY(_ALBH, float3(IN.tc2, IN._MainTexture3));
fixed4 nrsm3 = pow(UNITY_SAMPLE_TEX2DARRAY(_NRSM, float3(IN.tc2 , IN._MainTexture3)),0.5);
fixed3 normal3 = packNormal(nrsm3.rg);
#endif
#if HAS_SECOND_TEXTURE
IN.color.r = (log(IN.color.r * 3 + 1) / log(4)) / 2;
float dif = -((1 - IN.color.r) * origH1 - IN.color.r * origH2) * 50 + 0.5;
float lerp2 = clamp(dif, 0, 1);
albh = lerp(albh, albh2, lerp2);
nrsm.ab = lerp(nrsm.ab, nrsm2.ab, lerp2);
normal = lerp(normal, normal2, lerp2);
//albh.rgb = IN.color.rrr;
#endif
#if HAS_THIRD_TEXTURE
float4 color = IN.color;
IN.color.r = color.r - (color.g * color.a);
IN.color.r = (log(IN.color.r * 3 + 1) / log(4)) / 2;
float dif = -((1 - IN.color.r) * origH1 - IN.color.r * origH2) * 50 + 0.5;
float lerp2 = clamp(dif, 0, 1);
albh = lerp(albh, albh2, lerp2);
nrsm.ab = lerp(nrsm.ab, nrsm2.ab, lerp2);
normal = lerp(normal, normal2, lerp2);
IN.color.g = color.g - (color.g * color.b);
IN.color.g = (log(IN.color.g * 3 + 1) / log(4)) / 2;
dif = -((1 - IN.color.g) * origH1 - IN.color.g * origH3) * 50 + 0.5;
lerp2 = clamp(dif, 0, 1);
albh = lerp(albh, albh3, lerp2);
nrsm.ab = lerp(nrsm.ab, nrsm3.ab, lerp2);
normal = lerp(normal, normal3, lerp2);
//albh.rgb = IN.color.rrr;
//albh.g = IN.color.g-IN.color.b;
//albh.r = IN.color.r-IN.color.a;
#endif
//o.Albedo = parrall.rrr;
o.Albedo = albh.rgb;
o.Normal = normal;
o.Metallic = nrsm.a;
o.Smoothness = nrsm.b;
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}