Last active
August 14, 2018 17:10
-
-
Save bricevdm/f914908ebe202875f52eefa2137576f2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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