je viens de faire un géometry shader dérivé du Standard d'unity5, je n'ai pas implémenté la pass Deferred et META mais juste les 3première pass. Le reste pourrait subir le même traitement.
Appliqué sur une sphère ça donne :
j'ai implémenté le tuto DX10 ici : https://msdn.microsoft.com/en-us/librar ... 85%29.aspx
ça donne un truc du genre, je ne maitrise pas encore, dont tout commentaire / critique / amélioration est le bienvenu. Mon but etant ensuite de m'essayer a faire un shader de fourrure avec la methode Shell & Fins.
Code : Tout sélectionner
Shader "Custom/extendStandardShaderTest" {
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_Explode ("Explode factor", Range(0.0, 4.0)) = 1.0
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
_SpecColor("Specular", Color) = (0.2,0.2,0.2)
_SpecGlossMap("Specular", 2D) = "white" {}
_BumpScale("Scale", Float) = 1.0
_BumpMap("Normal Map", 2D) = "bump" {}
_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
_ParallaxMap ("Height Map", 2D) = "black" {}
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DetailMask("Detail Mask", 2D) = "white" {}
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
_DetailNormalMapScale("Scale", Float) = 1.0
_DetailNormalMap("Normal Map", 2D) = "bump" {}
[Enum(tex,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
// UI-only data
[HideInInspector] _EmissionScaleUI("Scale", Float) = 0.0
[HideInInspector] _EmissionColorUI("Color", Color) = (1,1,1)
// Blending state
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
}
CGINCLUDE
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
ENDCG
SubShader
{
Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
LOD 300
// ------------------------------------------------------------------
// Base forward pass (directional light, emission, lightmaps, ...)
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardBase" }
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma vertex vertFwdBase
#pragma fragment fragForwardBase
#pragma geometry geom
#include "UnityCG.cginc"
#include "HLSLSupport.cginc"
#include "UnityStandardCore.cginc"
#pragma debug
float _Explode;
struct VertexOutputFwdBase
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndParallax[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax]
half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UV
SHADOW_COORDS(6)
UNITY_FOG_COORDS(7)
float4 posWorld : TEXCOORD8;
};
VertexOutputFwdBase vertFwdBase (VertexInput v)
{
VertexOutputFwdBase o;
UNITY_INITIALIZE_OUTPUT(VertexOutputFwdBase, o);
float4 posWorld = mul(_Object2World, v.vertex);
#if UNITY_SPECCUBE_BOX_PROJECTION
o.posWorld = posWorld;
#endif
//o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.pos = v.vertex;
o.tex = TexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[2].xyz = normalWorld;
#endif
//We need this for shadow receving
TRANSFER_SHADOW(o);
// Static lightmaps
#ifndef LIGHTMAP_OFF
o.ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
o.ambientOrLightmapUV.zw = 0;
// Sample light probe for Dynamic objects only (no static or dynamic lightmaps)
#elif UNITY_SHOULD_SAMPLE_SH
#if UNITY_SAMPLE_FULL_SH_PER_PIXEL
o.ambientOrLightmapUV.rgb = 0;
#elif (SHADER_TARGET < 30)
o.ambientOrLightmapUV.rgb = ShadeSH9(half4(normalWorld, 1.0));
#else
// Optimization: L2 per-vertex, L0..L1 per-pixel
o.ambientOrLightmapUV.rgb = ShadeSH3Order(half4(normalWorld, 1.0));
#endif
// Add approximated illumination from non-important point lights
#ifdef VERTEXLIGHT_ON
o.ambientOrLightmapUV.rgb += Shade4PointLights (
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, posWorld, normalWorld);
#endif
#endif
#ifdef DYNAMICLIGHTMAP_ON
o.ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#endif
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
o.tangentToWorldAndParallax[0].w = viewDirForParallax.x;
o.tangentToWorldAndParallax[1].w = viewDirForParallax.y;
o.tangentToWorldAndParallax[2].w = viewDirForParallax.z;
#endif
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
// Geometry Shader
[maxvertexcount(12)]
void geom( triangle VertexOutputFwdBase input[3], inout TriangleStream<VertexOutputFwdBase> outStream )
{
VertexOutputFwdBase output;
UNITY_INITIALIZE_OUTPUT(VertexOutputFwdBase, output);
// Calculate the face normal
float3 faceEdgeA = input[1].pos - input[0].pos;
float3 faceEdgeB = input[2].pos - input[0].pos;
float3 faceNormal = normalize( cross(faceEdgeA, faceEdgeB) );
float3 ExplodeAmt = faceNormal*_Explode;
// Calculate the face center
float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz)/3.0;
float2 centerTex = (input[0].tex + input[1].tex + input[2].tex)/3.0;
centerPos += faceNormal*_Explode;
// Output the pyramid
for( int looper=0; looper<3; looper++ )
{
output.pos = input[looper].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[looper].tex;
output.eyeVec = input[looper].eyeVec;
output.tangentToWorldAndParallax = input[looper].tangentToWorldAndParallax;
output.ambientOrLightmapUV = input[looper].ambientOrLightmapUV;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
uint iNext = looper+1;
if(iNext>2)
{
iNext=0;
}
output.pos = input[iNext].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[iNext].tex;
output.eyeVec = input[iNext].eyeVec;
output.tangentToWorldAndParallax = input[iNext].tangentToWorldAndParallax;
output.ambientOrLightmapUV = input[iNext].ambientOrLightmapUV;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
output.pos = float4(centerPos,1) + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = float4(centerTex ,0,0);
output.eyeVec = input[looper].eyeVec;
output.tangentToWorldAndParallax = input[looper].tangentToWorldAndParallax;
output.ambientOrLightmapUV = input[looper].ambientOrLightmapUV;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
outStream.RestartStrip();
}
for(int cpt=2; cpt>=0; cpt-- )
{
output.pos = input[cpt].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[cpt].tex;
output.eyeVec = input[cpt].eyeVec;
output.tangentToWorldAndParallax = input[cpt].tangentToWorldAndParallax;
output.ambientOrLightmapUV = input[cpt].ambientOrLightmapUV;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
}
outStream.RestartStrip();
}
ENDCG
}
// ------------------------------------------------------------------
// Additive forward pass (one light per pass)
Pass
{
Name "FORWARD_DELTA"
Tags { "LightMode" = "ForwardAdd" }
Blend [_SrcBlend] One
Fog { Color (0,0,0,0) } // in additive pass fog should be black
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma target 3.0
// GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#include "UnityStandardCore.cginc"
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma vertex vertFwdAdd
#pragma fragment fragForwardAdd
#pragma geometry geom
#pragma multi_compile_fwdadd_fullshadows
#pragma multi_compile_fog
float _Explode;
// ------------------------------------------------------------------
// Additive forward pass (one light per pass)
struct VertexOutputFwdAdd
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:lightDir]
LIGHTING_COORDS(5,6)
UNITY_FOG_COORDS(7)
// next ones would not fit into SM2.0 limits, but they are always for SM3.0+
#if defined(_PARALLAXMAP)
half3 viewDirForParallax : TEXCOORD8;
#endif
};
VertexOutputFwdAdd vertFwdAdd (VertexInput v)
{
VertexOutputFwdAdd o;
UNITY_INITIALIZE_OUTPUT(VertexOutputFwdAdd, o);
float4 posWorld = mul(_Object2World, v.vertex);
o.pos = v.vertex;
o.tex = TexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndLightDir[0].xyz = tangentToWorld[0];
o.tangentToWorldAndLightDir[1].xyz = tangentToWorld[1];
o.tangentToWorldAndLightDir[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndLightDir[0].xyz = 0;
o.tangentToWorldAndLightDir[1].xyz = 0;
o.tangentToWorldAndLightDir[2].xyz = normalWorld;
#endif
//We need this for shadow receving
TRANSFER_VERTEX_TO_FRAGMENT(o);
float3 lightDir = _WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w;
#ifndef USING_DIRECTIONAL_LIGHT
lightDir = NormalizePerVertexNormal(lightDir);
#endif
o.tangentToWorldAndLightDir[0].w = lightDir.x;
o.tangentToWorldAndLightDir[1].w = lightDir.y;
o.tangentToWorldAndLightDir[2].w = lightDir.z;
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
#endif
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
// Geometry Shader
[maxvertexcount(12)]
void geom( triangle VertexOutputFwdAdd input[3], inout TriangleStream<VertexOutputFwdAdd> outStream )
{
VertexOutputFwdAdd output;
UNITY_INITIALIZE_OUTPUT(VertexOutputFwdAdd, output);
// Calculate the face normal
float3 faceEdgeA = input[1].pos - input[0].pos;
float3 faceEdgeB = input[2].pos - input[0].pos;
float3 faceNormal = normalize( cross(faceEdgeA, faceEdgeB) );
float3 ExplodeAmt = faceNormal*_Explode;
// Calculate the face center
float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz)/3.0;
float2 centerTex = (input[0].tex + input[1].tex + input[2].tex)/3.0;
centerPos += faceNormal*_Explode;
// Output the pyramid
for( int looper=0; looper<3; looper++ )
{
output.pos = input[looper].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[looper].tex;
output.eyeVec = input[looper].eyeVec;
output.tangentToWorldAndLightDir = input[looper].tangentToWorldAndLightDir;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
uint iNext = looper+1;
if(iNext>2)
{
iNext=0;
}
output.pos = input[iNext].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[iNext].tex;
output.eyeVec = input[iNext].eyeVec;
output.tangentToWorldAndLightDir = input[iNext].tangentToWorldAndLightDir;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
output.pos = float4(centerPos,1) + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = float4(centerTex ,0,0);
output.eyeVec = input[looper].eyeVec;
output.tangentToWorldAndLightDir = input[looper].tangentToWorldAndLightDir;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
outStream.RestartStrip();
}
for(int cpt=2; cpt>=0; cpt-- )
{
output.pos = input[cpt].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.tex = input[cpt].tex;
output.eyeVec = input[cpt].eyeVec;
output.tangentToWorldAndLightDir = input[cpt].tangentToWorldAndLightDir;
TRANSFER_SHADOW(output);
UNITY_TRANSFER_FOG(output,output.pos);
outStream.Append( output );
}
outStream.RestartStrip();
}
ENDCG
}
// ------------------------------------------------------------------
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Offset 1, 1
Fog {Mode Off}
ZWrite On
ZTest LEqual
Cull Off
CGPROGRAM
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers gles
// -------------------------------------
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma multi_compile_shadowcaster
#pragma vertex vertShadowCast
#pragma fragment fragShadowCast
#pragma geometry geom
#include "UnityCG.cginc"
#include "UnityStandardShadow.cginc"
float _Explode;
struct VertexOutputShadowCast
{
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
V2F_SHADOW_CASTER_NOPOS
};
//float4 _MainTex_ST;
VertexOutputShadowCast vertShadowCast (appdata_base v)
{
VertexOutputShadowCast o;
o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
o.pos = v.vertex;
//TRANSFER_SHADOW_CASTER_NOPOS(o,o.pos)
return o;
}
// Geometry Shader
[maxvertexcount(12)]
void geom( triangle VertexOutputShadowCast input[3], inout TriangleStream<VertexOutputShadowCast> outStream )
{
VertexOutputShadowCast output;
// Calculate the face normal
float3 faceEdgeA = input[1].pos - input[0].pos;
float3 faceEdgeB = input[2].pos - input[0].pos;
float3 faceNormal = normalize( cross(faceEdgeA, faceEdgeB) );
float3 ExplodeAmt = faceNormal*_Explode;
// Calculate the face center
float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz)/3.0;
float2 centerTex = (input[0].uv0 + input[1].uv0 + input[2].uv0)/3.0;
centerPos += faceNormal*_Explode;
// Output the pyramid
for( int looper=0; looper<3; looper++ )
{
output.pos = input[looper].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.uv0 = input[looper].uv0;
outStream.Append( output );
uint iNext = looper+1;
if(iNext>2)
{
iNext=0;
}
output.pos = input[iNext].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.uv0 = input[iNext].uv0;
outStream.Append( output );
output.pos = float4(centerPos,1) + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.uv0 = centerTex;
outStream.Append( output );
outStream.RestartStrip();
}
for(int cpt=2; cpt>=0; cpt-- )
{
output.pos = input[cpt].pos + float4(ExplodeAmt,0);
output.pos = mul(UNITY_MATRIX_MVP, output.pos);
output.uv0 = input[cpt].uv0;
outStream.Append( output );
}
outStream.RestartStrip();
}
fixed4 fragShadowCast (VertexOutputShadowCast i) : COLOR
{
half alpha = tex2D(_MainTex, i.uv0).a * _Color.a;
clip (alpha - _Cutoff);
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
/*
// ------------------------------------------------------------------
// Deferred pass
Pass
{
Name "DEFERRED"
Tags { "LightMode" = "Deferred" }
CGPROGRAM
#pragma target 3.0
// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
#pragma exclude_renderers nomrt gles
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _PARALLAXMAP
#pragma multi_compile ___ UNITY_HDR_ON
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
#pragma vertex vertDeferred
#pragma fragment fragDeferred
#include "UnityStandardCore.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Extracts information for lightmapping, GI (emission, albedo, ...)
// This pass it not used during regular rendering.
Pass
{
Name "META"
Tags { "LightMode"="Meta" }
Cull Off
CGPROGRAM
#pragma vertex vert_meta
#pragma fragment frag_meta
#pragma shader_feature _EMISSION
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#include "UnityStandardMeta.cginc"
ENDCG
}
*/
}
//CustomEditor "StandardShaderGUI"
}
si quelqu'un vois comment faire autrement je suis prenneur!