Search Unity

Question Shell texturing not work

Discussion in 'Shaders' started by MatheusMarkies, Aug 24, 2020.

  1. MatheusMarkies

    MatheusMarkies

    Joined:
    Apr 16, 2017
    Posts:
    67
    I'm following a Shell texturing tutorial to create fur, and apply it to unity.
    However, you are not creating the layers correctly.

    Tutorial: https://xbdev.net/directx3dx/specialX/Fur/

    My Shader:
    Code (CSharp):
    1. #ifndef LIT_PASS_INCLUDED
    2. #define LIT_PASS_INCLUDED
    3.  
    4. #include "../../ShaderLibrary/Surface.hlsl"
    5. #include "../../ShaderLibrary/Shadows.hlsl"
    6. #include "../../ShaderLibrary/Light.hlsl"
    7. #include "../../ShaderLibrary/BRDF.hlsl"
    8. #include "../../ShaderLibrary/GI.hlsl"
    9. #include "../../ShaderLibrary/Lighting.hlsl"
    10. #include "../../ShaderLibrary/Simplex3D.hlsl"
    11. #include "../../ShaderLibrary/ClearCoat.hlsl"
    12.  
    13. float4 _Time;
    14.  
    15. TEXTURE2D(_FurColor);
    16. SAMPLER(sampler_FurColor);
    17.  
    18. UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)
    19. UNITY_DEFINE_INSTANCED_PROP(float, _FurLength)
    20. UNITY_DEFINE_INSTANCED_PROP(float, _FurThinness)
    21. UNITY_DEFINE_INSTANCED_PROP(float3, _Gravity)
    22. UNITY_DEFINE_INSTANCED_PROP(float, _Cutoff)
    23. UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)
    24.  
    25. struct Attributes {
    26.     float3 positionOS : POSITION;
    27.     float3 normalOS : NORMAL;
    28.     float4 tangentOS : TANGENT;
    29.     float2 baseUV : TEXCOORD0;
    30.     float2 lightmapUV: TEXCOORD1;
    31.     float2 dynamicLightmapUV : TEXCOORD2;
    32.     UNITY_VERTEX_INPUT_INSTANCE_ID
    33. };
    34.  
    35. struct Varyings {
    36.     float4 positionCS : SV_POSITION;
    37.     float3 positionWS : VAR_POSITION;
    38.     float3 normalWS : VAR_NORMAL;
    39.     float4 tangentWS : VAR_TANGENT;
    40.     float2 baseUV : VAR_BASE_UV;
    41.  
    42.     UNITY_VERTEX_INPUT_INSTANCE_ID
    43. };
    44.  
    45. Varyings LitPassVertex (Attributes input) {
    46. UNITY_SETUP_INSTANCE_ID(input);
    47.     Varyings output;
    48.  
    49.   float3  P = input.positionOS + (input.normalOS * UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _FurLength)); // <--- Layers
    50.  
    51.     //float3 Gravity = UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _Gravity);
    52.  
    53.     //float k = pow(1, 3);
    54.  
    55.     //Gravity = TransformObjectToWorld(Gravity);
    56.     //P = P + Gravity * k;
    57.  
    58.     output.positionWS = TransformObjectToWorld(float4(P, 1.0f));
    59.     //output.positionCS = mul(mul(output.positionWS,normalize(_WorldSpaceCameraPos - output.positionWS)), _ProjectionParams);
    60.     output.positionCS = TransformWorldToHClip(float4(output.positionWS,1));
    61.     output.normalWS = TransformObjectToWorldNormal(input.normalOS);
    62.     output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
    63.     output.baseUV = input.baseUV * UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _FurThinness);
    64.  
    65.     return output;
    66. }
    67.  
    68. float4 LitPassFragment(Varyings input) : SV_TARGET{
    69. UNITY_SETUP_INSTANCE_ID(input);
    70.  
    71.     //float4 finalColor = UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial,_FurColor);
    72.     float4 FurColour = SAMPLE_TEXTURE2D(_FurColor, sampler_FurColor, input.baseUV);
    73.  
    74.     clip(FurColour.a - UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _Cutoff));
    75.  
    76. return float4(FurColour);
    77. }
    78.  
    79. #endif
    asgtsafg.PNG asgtsafg2.PNG Capturar3.PNG
    It does not replicate the noise layers to create the desired effect.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    You're missing one very important aspect of that tutorial. The shader it's presenting is for a single layer. It's expecting the user to rendering the individual layers manually. In Unity this would be equivalent to having multiple game objects & materials each with slightly different fur lengths. That shader does not itself handle the creation of multiple layers.
     
  3. MatheusMarkies

    MatheusMarkies

    Joined:
    Apr 16, 2017
    Posts:
    67
    I got it, Thanks!

    How could I do this on unity?
    And how could I get the layers to be generated by the shader?

    Sorry I started a short time ago at HLSL so I still have a lot of difficulties.:confused:
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    The options are:

    1) Actually have multiple spheres & materials. Most versatile. Also most annoying to use. Also only option if you want point lights to look correct while using alpha blending instead of alpha testing.

    2) Assign the fur material to the sphere multiple times. The Material array will re render the mesh for ever material in the list. Then adjust the fur length for each using
    MaterialPropertyBlock
    s and
    rend.SetPropertyBlock(matBlock, i)
    for each index of the array. Also versatile, allows for a dynamic number of layers, but does require c# coding. Also potentially supports instancing.
    https://docs.unity3d.com/ScriptReference/MaterialPropertyBlock.html
    https://docs.unity3d.com/ScriptReference/Renderer.SetPropertyBlock.html

    3) Use a shader with multiple passes, each with a hard coded multiplier on the fur length. Easiest to use once setup since it's all in-shader. But you have a fixed number of layers, and guaranteed won't instance. Also won't support instancing, at all.

    4) Use a geometry shader stage to amplify the geometry. Also only requires the shader to work, and does support a dynamic number of layers! Doesn't work on a lot of mobile devices, including anything recent from Apple.
     
    MatheusMarkies likes this.
  5. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    5) like 1 but only one material, encode the length on the vertex data, the shader read it and adjust length, allow painting length locally.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,339
    This would either need to be done by having multiple otherwise identical models with slightly different vertex data, or use a c# script to update the duplicate mesh's vertex data.

    Once you're going down this route you might as well just model the shells into the mesh manually.