当前位置:网站首页>Character shader exercise
Character shader exercise
2022-07-29 07:57:00 【TingQiaoQiao】
Follow the train of thought of Zhuang Tong Dota Character material
1.1 Handle the map
The map inside has the problem of upside down or left-right reverse , So you need to first process the image into the same position as the color map and normal map , And then the others RampTexture To put WrapMode Set to Clamp Pattern .
Untreated black spots will appear

After processing RampTexture It will show normal effect

1.2 View design documents , Analyze the lighting model and mapping effect
Because considering that the color reflected by diffuse reflection and specular reflection of metal and non-metal is different , So first calculate the different colors produced by specular reflection and specular reflection , Later, multiply the color into the calculated lighting model .
float3 diffuseColor = lerp(var_MainTexture,float3(0.0,0.0,0.0), var_Metellic);
float3 specularColor = lerp(var_MainTexture, float3(0.4, 0.4, 0.4), var_TintMaskTexture) * var_SpecIntTexture; 1.3 Illumination model
1.3.1 Diffuse reflection
// Diffuse reflection of main light source
float halfLambert =ldotn * 0.5 + 0.5;
float3 lambertColor = tex2D(_DiffuseColor,float2(halfLambert,0.5));
float3 lightDiffuseColor = _LightColor * lambertColor * diffuseColor * _LightDiffuseStrength;
// Ambient light diffuse
float maskUp = max(0,nDirWS.g);
float maskDown = max(0, -nDirWS.g) ;
float maskMiddle = 1 - maskUp - maskDown;
float3 ambiendDiffuseColor =( maskUp * _AmbientDiffuseColor_Up + maskDown * _AmbientDiffuseColor_Down + _AmbientDiffuseColor_Middle * maskMiddle ) * diffuseColor * _AmbientDiffuseStrength;Diffuse reflection of main light source

Diffuse reflection of ambient light

1.3.2 Specular reflection
// Main light source specular
float Phong = pow(max(0, lrdotv), var_SpecPowTexture * _LightSpecularPow);
float specular = Phong * halfLambert;
float FresnelSpecular = lerp(var_FresnelSpecular,0.0, var_Metellic);
//float specular_Fresnel = tex2D(_FresnelSpecular, float2(specular, 0.5));// It doesn't seem to be able to sample like that , There is a very magical effect
float specular_Fresnel = max(specular, FresnelSpecular) * _LightSpecularStrength;
float3 lightSpecularColor = _LightColor * specular_Fresnel * specularColor;
// Ambient light specular
float reflect = max(var_Metellic, FresnelSpecular) * var_SpecIntTexture;
float3 envSpecularColor = reflect * specularColor * var_CubeMap * _EnvSpecularStength;Specular reflection of the main light source

Specular reflection of ambient light

If you use ramptexture Use highlights as samples , It will produce an effect similar to that the whole is metal

Because Fresnel effect usually appears only with some smooth materials , So we should use the metal range mask to control the Fresnel ramptexture Conduct lerp once
var_FresnelRim No, lerp once

After processing

1.3.3 Contour light and self illumination
// Contour light
float FresnelRim = lerp(var_FresnelRim, 0.0, var_Metellic);
float3 rimLight = var_RimIntTexture * FresnelRim * max(0, nDirWS.g) * _RimStrength * _RimColor;
// Spontaneous light
float3 emission = diffuseColor * var_EmissionTexture * _EmissionStrength;
1.3.4 Mix lighting and output

1.4 Code
notes : Because it is more intuitive and can not think about the conversion between parameters , So I didn't synthesize multiple maps into one map , You can see that each map is sampled once , Then all parameter types are used uniformly float, Some can be used half perhaps fixed To replace .
Shader "Unlit/Body Shader"
{
Properties{
// Open attribute control
[Header(Texture)]
_MainTexture(" Main map ",2D) = "white"{}
_OpacityTexture(" Transparency maps ",2D) = "white"{}
_NormalTexture(" Normal map ",2D) = "bump"{}
_SpecIntTexture(" Highlight intensity map ",2D) = "white"{}
_RimIntTexture(" Edge light intensity map ",2D) = "white"{}
_TintMaskTexture(" Dye mask map ",2D) = "white"{}
_SpecPowTexture(" Highlight power map ",2D) = "white"{}
_CubeMap(" Environmental ball ",cube) = "_skybox"{}
_DiffuseColor(" Diffuse color map ",2D) = "grey"{}
_FresnelRim(" Fresnel edge light map ",2D) = "white"{}
_FresnelSpecular(" Fresnel highlight map ",2D) = "white"{}
_Metellic(" Metal range mask ",2D) = "grey"{}
_EmissionTexture(" irradiance map ",2D) = "white"{}
[Header(Slider)]
_Cutoff(" Transparency map threshold ",Range(0,1)) = 0.5
_LightDiffuseStrength(" Diffuse reflection intensity of main light ",Range(0,5)) = 2
_LightSpecularStrength(" Highlight reflection intensity of main light ", Range(0,5)) = 2
_LightSpecularPow(" Highlight power of main light ", Range(0,10)) = 5
_AmbientDiffuseStrength(" Ambient diffuse intensity ",Range(0,1)) = 0.8
_EnvSpecularStength(" Specular intensity of ambient light ",Range(1,10)) = 5
_RimStrength(" Edge light intensity ",Range(0,5)) = 2
_EmissionStrength(" Self luminous intensity ",Range(0,5)) = 2
[Header(Color)]
_LightColor(" The color of the light ", color) = (1.0,1.0,1.0,1.0)
_AmbientDiffuseColor_Up(" Ambient light diffuses the upper light ",color) = (1.0,1.0,1.0,1.0)
_AmbientDiffuseColor_Middle(" Ambient diffuse mid light ",color) = (1.0,1.0,1.0,1.0)
_AmbientDiffuseColor_Down(" Ambient diffuse lower light ",color) = (1.0,1.0,1.0,1.0)
_RimColor(" Edge light color ",color) = (1.0,1.0,0.0,1.0)
}
SubShader{
Tags {
"RenderType" = "Opaque"
}
Pass {
Name "FORWARD"
Tags {
"LightMode" = "ForwardBase"
}
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "AutoLight.cginc"
#include "UnityCG.cginc"
#include "Lighting.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
// Defining attributes
uniform sampler2D _MainTexture;
uniform sampler2D _OpacityTexture;
uniform float _Cutoff;
uniform sampler2D _NormalTexture;
uniform float _LightDiffuseStrength;
uniform sampler2D _SpecIntTexture;
uniform sampler2D _RimIntTexture;
uniform sampler2D _TintMaskTexture;
uniform sampler2D _SpecPowTexture;
uniform samplerCUBE _CubeMap;
uniform sampler2D _FresnelRim;
uniform sampler2D _FresnelSpecular;
uniform sampler2D _Metellic;
uniform sampler2D _DiffuseColor;
uniform float3 _LightColor;
uniform float3 _AmbientDiffuseColor_Up;
uniform float3 _AmbientDiffuseColor_Middle;
uniform float3 _AmbientDiffuseColor_Down;
uniform float _AmbientDiffuseStrength;
uniform float _LightSpecularPow;
uniform float _LightSpecularStrength;
uniform float _EnvSpecularStength;
uniform float3 _RimColor;
uniform float _RimStrength;
uniform sampler2D _EmissionTexture;
uniform float _EmissionStrength;
// Input structure
struct VertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv0 : TEXCOORD0;
};
// Output structure
struct VertexOutput {
float4 pos : SV_POSITION;
float3 posWS : TEXCOORD0;
float2 uv0 : TEXCOORD1;
float3 nDirWS : TEXCOORD2;
float3 tDirWS : TEXCOORD3;
float3 bDirWS : TEXCOORD4;
LIGHTING_COORDS(5, 6)
};
// Pixels shader
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);
TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
// The vertices shader
float4 frag(VertexOutput i) : COLOR {
// Vector preparation
float3 nDirTS = UnpackNormal(tex2D(_NormalTexture,i.uv0)).rgb; // Get normal information
float3x3 TBN = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
float3 nDirWS = normalize(mul(nDirTS, TBN));
float3 lDirWS = _WorldSpaceLightPos0.xyz;
float3 lrDirWS = reflect(lDirWS,nDirWS);
float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);
float3 vrDirWS = normalize(reflect(-vDirWS, nDirWS));
// Intermediate quantity preparation
float ldotn = dot(lDirWS,nDirWS); // The dot multiplier required by half Lambert
float lrdotv = dot(lrDirWS, vDirWS); //Phong Required dot multiplication
float ndotv = (nDirWS,vDirWS); // Point multiplier required by contour light
// Texture sampling
float3 var_MainTexture = tex2D(_MainTexture, i.uv0); // Sample color texture
float var_OpacityTexture = tex2D(_OpacityTexture, i.uv0);// Transparent map sampling
float var_SpecIntTexture = tex2D(_SpecIntTexture, i.uv0); // Sample highlight texture , As a highlight, you need to increase the intensity
float var_RimIntTexture = tex2D(_RimIntTexture, i.uv0); // Edge light texture , As a mask, judge where to highlight
float var_TintMaskTexture = tex2D(_TintMaskTexture, i.uv0); // Dye mask texture , As
float var_SpecPowTexture = tex2D(_SpecPowTexture, i.uv0); // Sampling highlight power , Use it as a template to control the roughness
float var_FresnelRim = tex2D(_FresnelRim, i.uv0); // Fresnel edge light ramptexture
float var_FresnelSpecular = tex2D(_FresnelSpecular, i.uv0); // Fresnel highlights ramptexture
float3 var_CubeMap = texCUBElod(_CubeMap, float4(vrDirWS, lerp(7.0, 0.0, var_SpecIntTexture))).rgb;
float var_Metellic = tex2D(_Metellic, i.uv0);
float var_EmissionTexture = tex2D(_EmissionTexture, i.uv0);
// shadow
float shadow = LIGHT_ATTENUATION(i);
// Illumination model
// Because the colors of specular reflection and diffuse reflection are different , In specular reflection, the metal will show its true color , Nonmetals will appear black and white ; In diffuse reflection, metal diffuse reflection is less , Darker map
float3 diffuseColor = lerp(var_MainTexture,float3(0.0,0.0,0.0), var_Metellic); // use lerp Interpolation , If matellic by 0 The place will reflect its primary color , If it is 1 The reaction is black ,matellic=0.5 Ooh, other decimals are interpolated to calculate the weight of their offset
float3 specularColor = lerp(var_MainTexture, float3(0.4, 0.4, 0.4), var_TintMaskTexture) * var_SpecIntTexture; // Interpolation calculation is carried out through the metal reflective mask , And multiply it by the map with highlights , So as to imitate its reflection color under the light source
// Diffuse reflection of main light source
float halfLambert =ldotn * 0.5 + 0.5; // Half Lambert effect is much better than Lambert effect , Lambert effect is a little terrible
float3 lambertColor = tex2D(_DiffuseColor,float2(halfLambert,0.5));
float3 lightDiffuseColor = _LightColor * lambertColor * diffuseColor * _LightDiffuseStrength;
// Ambient light diffuse
float maskUp = max(0,nDirWS.g);
float maskDown = max(0, -nDirWS.g) ;
float maskMiddle = 1 - maskUp - maskDown;
float3 ambiendDiffuseColor =( maskUp * _AmbientDiffuseColor_Up + maskDown * _AmbientDiffuseColor_Down + _AmbientDiffuseColor_Middle * maskMiddle ) * diffuseColor * _AmbientDiffuseStrength;
// Main light source specular
float Phong = pow(max(0, lrdotv), var_SpecPowTexture * _LightSpecularPow);
float specular = Phong * halfLambert;
float FresnelSpecular = lerp(var_FresnelSpecular,0.0, var_Metellic);
//float specular_Fresnel = tex2D(_FresnelSpecular, float2(specular, 0.5));// It doesn't seem to be able to sample like that , There is a very magical effect
float specular_Fresnel = max(specular, FresnelSpecular) * _LightSpecularStrength;
float3 lightSpecularColor = _LightColor * specular_Fresnel * specularColor;
// Ambient light specular
float reflect = max(var_Metellic, FresnelSpecular) * var_SpecIntTexture;
float3 envSpecularColor = reflect * specularColor * var_CubeMap * _EnvSpecularStength;
// Contour light
float FresnelRim = lerp(var_FresnelRim, 0.0, var_Metellic);
float3 rimLight = var_RimIntTexture * FresnelRim * max(0, nDirWS.g) * _RimStrength * _RimColor;
// Spontaneous light
float3 emission = diffuseColor * var_EmissionTexture * _EmissionStrength;
// Mixed light source
float3 finalColor = (lightDiffuseColor + lightSpecularColor) * shadow + envSpecularColor + envSpecularColor + rimLight + emission;
// Transparent shear
clip(var_OpacityTexture - _Cutoff);
return fixed4(finalColor,1);
}
ENDCG
}
}
FallBack "Legacy Shaders/Transparent/Cutout/VertexLit"
}
边栏推荐
- [paper reading | cryoet] gum net: fast and accurate 3D subtomo image alignment and average unsupervised geometric matching
- Excellent urban design ~ good! Design # visualization radio station will be broadcast soon
- String类
- Better performance and simpler lazy loading of intersectionobserverentry (observer)
- 工业互联网行至深水区,落地的路要怎么走?
- What is the use of chat robots? What type? After reading these, you will understand!
- For the application challenge of smart city, shengteng AI gives a new solution
- In the MySQL connector of flynk CDC, the MySQL field is varbinary, which is officially
- [cryoelectron microscope | paper reading] a feature guided, focused 3D signal permutation method for subtogram averaging
- MySQL 45 | 08 is the transaction isolated or not?
猜你喜欢
![[lecture notes] how to do in-depth learning in poor data?](/img/7d/5767c078600bd88b7d2146069f4f40.jpg)
[lecture notes] how to do in-depth learning in poor data?

Sqlmap(SQL注入自动化工具)

Realize the effect of changing some colors of a paragraph of text
![[paper reading | cryoelectron microscope] interpretation of the new subtomogram averaging method in relion 4.0](/img/8d/03e63d651b713f547b090e6e740b06.png)
[paper reading | cryoelectron microscope] interpretation of the new subtomogram averaging method in relion 4.0

Amaze UI 图标查询

Up sampling deconvolution operation

Chaos and future of domestic digital collections

Mqtt server setup and mqtt.fx testing

Excellent urban design ~ good! Design # visualization radio station will be broadcast soon

MySQL uses date_ FORMAT(date,'%Y-%m')
随机推荐
下推分析的限制
Vmstat memory consumption query
Chaos and future of domestic digital collections
Record of problems caused by PIP upgrade damage
Amaze UI 图标查询
你学习·我奖励,21天学习挑战赛 | 等你来战
[WPF] realize language switching through dynamic / static resources
[密码学实验] 0x00 安装NTL库
Sqlmap (SQL injection automation tool)
10 practical uses of NFT
Phased learning about the entry-level application of SQL Server statements - necessary for job hunting (I)
IonIcons图标大全
MySQL 45讲 | 08 事务到底是隔离的还是不隔离的?
Basic introduction to pod
Sort out the two NFT pricing paradigms and four solutions on the market
Resize2fs: bad magic number in super block
[cryoelectron microscope] relion4.0 pipeline command summary (self use)
Keyboard processing in jetpack compose
Mutationobserver document learning
[paper reading] tomoalign: a novel approach to correcting sample motion and 3D CTF in cryoet