Skip to content

Instantly share code, notes, and snippets.

@bricevdm
Last active August 14, 2018 17:10
Show Gist options
  • Save bricevdm/f914908ebe202875f52eefa2137576f2 to your computer and use it in GitHub Desktop.
Save bricevdm/f914908ebe202875f52eefa2137576f2 to your computer and use it in GitHub Desktop.
Shader "Custom/Phong Tessellation Deferred"
{
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
[NoScaleOffset][Normal] _NormalTex ("Normal (RGB)", 2D) = "bump" {}
_NormalFactor ("Normal Strength", Range(0, 2)) = 1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_TessellationFactor ("Tessellation Factor", Range(0, 64)) = 4
}
CGINCLUDE
#include "HLSLSupport.cginc"
#include "UnityShaderVariables.cginc"
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "UnityPBSLighting.cginc"
#define WorldReflectionVector(data,normal) data.worldRefl
#define WorldNormalVector(data,normal) normal
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _NormalTex;
struct VS_CONTROL_POINT_OUTPUT
{
float4 vertex : SV_POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
half3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
half3 sh : TEXCOORD3; // SH
};
struct HS_CONSTANT_DATA_OUTPUT
{
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
float3 vTangent[4] : TANGENT;
float2 vUV[4] : TEXCOORD;
float3 vTanUCorner[4] : TANUCORNER;
float3 vTanVCorner[4] : TANVCORNER;
float4 vCWts : TANWEIGHTS;
};
// vertex shader
VS_CONTROL_POINT_OUTPUT vert_surf (appdata_full v) {
VS_CONTROL_POINT_OUTPUT o = (VS_CONTROL_POINT_OUTPUT)0;
o.vertex = v.vertex;
o.normal = v.normal;
o.tangent = v.tangent;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex).xy;
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = worldPos;
o.worldNormal = worldNormal;
float3 viewDirForLight = UnityWorldSpaceViewDir(worldPos);
o.sh = ShadeSH3Order (half4(worldNormal, 1.0));
return o;
}
half _TessellationFactor;
half _NormalFactor;
HS_CONSTANT_DATA_OUTPUT constantsHS (InputPatch<VS_CONTROL_POINT_OUTPUT,3> V)
{
HS_CONSTANT_DATA_OUTPUT output = (HS_CONSTANT_DATA_OUTPUT)0;
output.edge[0] = output.edge[1] = output.edge[2] = _TessellationFactor;
output.inside = _TessellationFactor;
return output;
}
half _Glossiness;
half _Metallic;
fixed4 _Color;
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[patchconstantfunc("constantsHS")]
[outputcontrolpoints(3)]
VS_CONTROL_POINT_OUTPUT hull_shader (InputPatch<VS_CONTROL_POINT_OUTPUT,3> V, uint ID : SV_OutputControlPointID)
{
return V[ID];
}
[domain("tri")]
VS_CONTROL_POINT_OUTPUT domain_shader (HS_CONSTANT_DATA_OUTPUT input, const OutputPatch<VS_CONTROL_POINT_OUTPUT,3> P, float3 K : SV_DomainLocation)
{
appdata_full ds = (appdata_full)0;
//ds.vertex = UnityObjectToClipPos(P[0].vertex * K.x + P[1].vertex * K.y + P[2].vertex * K.z);
ds.normal = P[0].normal * K.x + P[1].normal * K.y + P[2].normal * K.z;
ds.tangent = P[0].tangent * K.x + P[1].tangent * K.y + P[2].tangent * K.z;
ds.texcoord.xy = P[0].uv.xy * K.x + P[1].uv.xy * K.y + P[2].uv.xy * K.z;
float3 posVtx = P[0].vertex * K.x + P[1].vertex * K.y + P[2].vertex * K.z;
// https://github.com/NVIDIAGameWorks/FaceWorks/blob/master/samples/d3d11/shaders/tess_ds.hlsl
// Calculate deltas to project onto three tangent planes
float3 vecProj0 = dot(P[0].vertex - posVtx, P[0].normal) * P[0].normal;
float3 vecProj1 = dot(P[1].vertex - posVtx, P[1].normal) * P[1].normal;
float3 vecProj2 = dot(P[2].vertex - posVtx, P[2].normal) * P[2].normal;
// Lerp between projection vectors
float3 vecOffset = K.x * vecProj0 + K.y * vecProj1 + K.z * vecProj2;
// Add a fraction of the offset vector to the lerped position
posVtx += 0.5 * vecOffset;
ds.vertex = UnityObjectToClipPos(posVtx);
return vert_surf(ds);
}
// fragment shader
void frag_surf (VS_CONTROL_POINT_OUTPUT IN,
out half4 outDiffuse : SV_Target0,
out half4 outSpecSmoothness : SV_Target1,
out half4 outNormal : SV_Target2,
out half4 outEmission : SV_Target3)
{
float3 worldPos = IN.worldPos;
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
#ifdef UNITY_COMPILER_HLSL
SurfaceOutputStandard o = (SurfaceOutputStandard)0;
#else
SurfaceOutputStandard o;
#endif
half3 nml = normalize(IN.normal);
half3 tgt = normalize(IN.tangent.xyz);
half3 btg = cross(nml, tgt) * IN.tangent.w;
half4 s1 = tex2D(_MainTex, IN.uv);
half3 s2 = UnpackNormal(tex2D(_NormalTex, IN.uv));
s2.xy *= _NormalFactor;
o.Albedo = s1.rgb * _Color.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Emission = 0.0;
o.Alpha = 0.0;
o.Occlusion = 1.0;
//o.Normal = IN.worldNormal;
o.Normal = tgt * s2.x + btg * s2.y + nml * s2.z;
o.Normal = normalize(o.Normal);
o.Normal = UnityObjectToWorldNormal(o.Normal);
// Setup lighting environment
UnityGI gi;
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
gi.indirect.diffuse = 0;
gi.indirect.specular = 0;
gi.light.color = 0;
gi.light.dir = half3(0,1,0);
gi.light.ndotl = LambertTerm (o.Normal, gi.light.dir);
// Call GI (lightmaps/SH/reflections) lighting function
UnityGIInput giInput;
UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
giInput.light = gi.light;
giInput.worldPos = worldPos;
giInput.worldViewDir = worldViewDir;
giInput.atten = 1.0;
giInput.ambient = IN.sh;
giInput.probeHDR[0] = unity_SpecCube0_HDR;
giInput.probeHDR[1] = unity_SpecCube1_HDR;
#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
#endif
#if UNITY_SPECCUBE_BOX_PROJECTION
giInput.boxMax[0] = unity_SpecCube0_BoxMax;
giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
giInput.boxMax[1] = unity_SpecCube1_BoxMax;
giInput.boxMin[1] = unity_SpecCube1_BoxMin;
giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
#endif
LightingStandard_GI(o, giInput, gi);
// call lighting function to output g-buffer
outEmission = LightingStandard_Deferred (o, worldViewDir, gi, outDiffuse, outSpecSmoothness, outNormal);
outDiffuse.a = 1.0;
#ifndef UNITY_HDR_ON
outEmission.rgb = exp2(-outEmission.rgb);
#endif
}
ENDCG
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
Pass {
Name "DEFERRED"
Tags { "LightMode" = "Deferred" }
CGPROGRAM
#pragma vertex vert_surf
#pragma hull hull_shader
#pragma domain domain_shader
#pragma fragment frag_surf
#pragma target 5.0
#pragma exclude_renderers nomrt
#pragma multi_compile_prepassfinal noshadow
ENDCG
}
}
FallBack "Diffuse"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment