这些是根据其他美术团队的需求开发shader的实验品。
Shader development prototypes according to the demand of other art teams.
这些是根据其他美术团队的需求开发shader的实验品。
Shader development prototypes according to the demand of other art teams.
Code Snippet below
float node_8816 = (sceneUVs.r+_ReflectionCoordinater);
float2 node_2055 = (float2(sceneUVs.r,sceneUVs.g)+(float2(node_8816,node_8816)*(float2(_normal_var.r,_normal_var.g)*_NormalJitter)));
half4 _ReflectionTex_var = tex2D(_ReflectionTex,node_2055);
fixed3 FlatMirror = ((_ReflectionTex_var.rgb+(pow((1.0 - lerp( _ReflectionTex_var.rgb.g, _ReflectionTex_var.rgb.r, _ChannelSwap )),exp2(_ReflectionBrightSubScale))*_ReflectionBrightSubScale))*_ReflectionsIntensity);
half Fresnel = dot(pow(1.0-max(0,dot(normalDirection, viewDirection)),exp2((1.0 - _ReflectionFresnel))),lightDirection);
float3 node_9903 = (FlatMirror*Fresnel);
half3 FlatMirrorBlended = saturate(max(_MainTex_var.rgb,node_9903));
half3 node_9232 = FlatMirrorBlended;
half3 Albedo = _MainTex_var.rgb;
float node_6753 = (i.uv0.g+(_ReflectionFadeOffset*0.5+0.0)).r;
half3 FlatMirrorFade = lerp(node_9232,Albedo,node_6753);
float3 diffuseColor = FlatMirrorFade;
I was used screen space light texture technique (matcap or light-cap) since from 2006 in years.
And then my new stuff of new matcap technique (I called dual matcap technique) since by 2015 in years When I developed android mobile game in Korea.
Basically matcap technique is So famous tweak shader lighting technique for mobile games.But I curious Could I use to dual side of matcap?
So here is results.
Complete code here.
Shader "ASE_DualMatcap"
{
Properties
{
_FrontParaboloid ("_FrontParaboloid", 2D) = "white" { }
_RearParaboloid ("_RearParaboloid", 2D) = "white" { }
_Albedo("Albedo", 2D) = "white" {}
_Float0("Float 0", Range( 0 , 2)) = 1
[HideInInspector] _texcoord( "", 2D ) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }
LOD 100
Cull Off
Pass
{
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 texcoord : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
uniform fixed4 _Color;
uniform sampler2D _FrontParaboloid;
uniform sampler2D _RearParaboloid;
uniform sampler2D _Albedo;
uniform float4 _Albedo_ST;
uniform float _Float0;
v2f vert ( appdata v )
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.texcoord.xy = v.texcoord.xy;
o.texcoord.zw = v.texcoord1.xy;
// ase common template code
v.vertex.xyz += float3(0,0,0) ;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
return o;
}
inline fixed4 texParaboloidXFliped(sampler2D front, sampler2D back, float3 refl)
{
if (refl.x > 0)
{
float2 frontUv;
frontUv.x = refl.z / (refl.x + 1);
frontUv.y = refl.y / (refl.x + 1);
frontUv = (frontUv * .5f) + 0.5f;
frontUv.x = 1 - frontUv.x;
return tex2D(front, frontUv);
}
else
{
float2 backUv;
backUv.x = refl.z / (1 - refl.x);
backUv.x *= -1;
backUv.y = refl.y / (1 - refl.x);
backUv = (backUv * .5f) + 0.5f;
backUv.x = backUv.x;
return tex2D(back, backUv);
}
}
fixed4 frag (v2f i ) : SV_Target
{
fixed4 parabolicOut;
// ase common template code
float2 uv_Albedo = i.texcoord.xy * _Albedo_ST.xy + _Albedo_ST.zw;
parabolicOut = ( float4(1,1,1,0) * ( tex2D( _Albedo, uv_Albedo ) * _Float0 ) );
//return myColorVar;
return parabolicOut * texParaboloidXFliped(_FrontParaboloid, _RearParaboloid, i.worldNormal);;
}
ENDCG
}
}
CustomEditor "ASEMaterialInspector"
}
概要。项目瀑布波纹效果的要求。内容。
参考游戏 : RIM2
Shader 的实现。使用不同的两张波纹(Ripple)纹理,各自设置不同的速度使波纹效果更自然。
为了让Mesh的波纹呈现向外围渐渐消失的效果,使用Vertex Color。
为了在Shader使波纹的边缘自然地Fade-out,Vertex color 要用 mask。
该着色器是使用“ Amplify Shader Editor”创建的。
This shader was created using the Amplify Shader Editor.
Shader "Water Ripple Shader"
{
Properties
{
_Cutoff( "Mask Clip Value", Float ) = 0.5
_RippleFoam("RippleFoam", 2D) = "white" {}
_MainFoamSpeed("Main Foam Speed", Float) = 0.1
_SecondFoamSpeed("Second Foam Speed", Float) = 0.1
_MainFoamScale("Main Foam Scale", Float) = 2
[HideInInspector] __dirty( "", Int ) = 1
}
SubShader
{
Tags{ "RenderType" = "TransparentCutout" "Queue" = "AlphaTest+0" "IgnoreProjector" = "True" "ForceNoShadowCasting" = "True" "IsEmissive" = "true" }
Cull Back
CGPROGRAM
#include "UnityShaderVariables.cginc"
#pragma target 3.5
#pragma multi_compile_instancing
#pragma only_renderers d3d11 glcore gles gles3 metal
#pragma surface surf Unlit keepalpha noshadow novertexlights nolightmap nodynlightmap nodirlightmap nometa noforwardadd vertex:vertexDataFunc
struct Input
{
float2 vertexToFrag32;
float2 vertexToFrag33;
float4 vertexColor : COLOR;
};
uniform float _MainFoamSpeed;
uniform float _MainFoamScale;
uniform sampler2D _RippleFoam;
uniform float _SecondFoamSpeed;
uniform float _Cutoff = 0.5;
void vertexDataFunc( inout appdata_full v, out Input o )
{
UNITY_INITIALIZE_OUTPUT( Input, o );
float temp_output_30_0 = ( _MainFoamSpeed * 0.15 );
float2 appendResult31 = (float2(temp_output_30_0 , temp_output_30_0));
float2 panner8 = ( ( appendResult31 * _Time.y ).x * float2( 0,1 ) + v.texcoord.xy);
float2 temp_output_22_0 = ( panner8 * _MainFoamScale );
o.vertexToFrag32 = temp_output_22_0;
float temp_output_15_0 = ( _SecondFoamSpeed * 0.15 );
float2 appendResult18 = (float2(temp_output_15_0 , temp_output_15_0));
o.vertexToFrag33 = ( temp_output_22_0 + ( appendResult18 * _Time.y ) );
}
inline fixed4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten )
{
return fixed4 ( 0, 0, 0, s.Alpha );
}
void surf( Input i , inout SurfaceOutput o )
{
o.Emission = float4(1,1,1,0).rgb;
o.Alpha = 1;
float lerpResult40 = lerp( 0.5 , ( tex2D( _RippleFoam, i.vertexToFrag32 ).g + tex2D( _RippleFoam, i.vertexToFrag33 ).r ) , i.vertexColor.r);
clip( lerpResult40 - _Cutoff );
}
ENDCG
}
CustomEditor "ASEMaterialInspector"
}
GI信息存储在Unity3D中的Baked Indirect中,使用Meta Pass来确定相邻的颜色值。评估最终结果的视觉效果时,比起真实值,控制更人为的颜色值的Color Bleeding强度,为了接近美术想要的最终品质,修改Unity3D提供的LightMap最终计算方式的过程。在创作早期原型时,使用Amplify Shader Editor等来快速实现,并与美术协商,以便将其添加到内部项目的lightmap计算中。
GI information saved in Baked Indirect of Unity3D is determined by using Meta Pass for adjacent color values.
When evaluating the visual effects of the final result, we control the Color Bleeding intensity of the adjacent color values more artificially than the realistic ones. Shows the process.
When building an initial prototype, you can quickly implement it using the Amplify Shader Editor, etc., and work with the art team to add it to the lightmap calculations for your internal project.
Light Probe data具有在lightAsset中以二进制形式存储的特性。
此外,将根据最后一个场景中的信息Replace所有合并的场景的Light Probe信息。
解决这一问题的基本方法是TextAsset里单独存储,每个Chunk分别进行管理。
此外,还可以实现编辑器扩展,以允许美术团队修改SH细节值。
Light Probe data has the property of being stored as binary in lightAsset.
It will also replace the light probe information of all merged scenes based on the information of the last scene.
The basic way to solve this problem is to save as TextAsset and manage each chunk separately.
It also implements an editor extension that allows the art team to modify the detailed SH values.
#if USE_SECOND_DIRECTIONAL_LIGHT
half2 RoL = max(0, half2(dot(ReflectionVector, DirectionalLightDirection), dot(ReflectionVector, _WorldSpaceLightPos1.xyz)));
half2 PhongSpecular = PhongApprox(Roughness, RoL);
half3 Directional = (Shadow * NoL) * DirectionalLightColor * (DiffuseColor + SpecularColor * PhongSpecular.x);
half NoL2 = max(0, dot(normalWorld, _WorldSpaceLightPos1.xyz));
Directional += NoL2 * _LightColor1 * (DiffuseColor + SpecularColor * PhongSpecular.y);
#else
half3 halfDir = normalize(DirectionalLightDirection + s.viewdir);
half RoL = max(0, dot(ReflectionVector, DirectionalLightDirection));
half RoLDual = max(0, dot(ReflectionVector , -s.viewdir * halfDir));
half3 Directional = (Shadow * NoL) * DirectionalLightColor * (DiffuseColor + SpecularColor * (PhongApprox(Roughness,RoL)));
#if defined(USE_BACKLIGHT_SPECUAR)
Directional = (Shadow * NoL) * DirectionalLightColor * (DiffuseColor + SpecularColor * (PhongApprox(Roughness,RoL) + (PhongApprox(Roughness, RoLDual))));
#endif
#endif
开发瞳孔时,我特别重视的是,能够准确地引导出美术的最终要求。
使用前两个Mesh的方法是由美术队自制的,是消费两个Draw-Call的,没有特别的折射感,所以和美术简单讨论后使用了两个Specular,但是从实际的太阳光源的位置计算出来,其中一个是根据用户的视角计算的,即镜头视角。
我为美术提供的最终目标是Horizon Zero Dawn。
在实现过程中,我们合并了两个Draw-call,最大限度地降低了精度,消除了所有的GGX运算,只使用Normalized Blinn-Phong Specular实现。
ALU在处理折射时有所增加,但删除了依赖于PBR的某些部分,使得整体ALU比正常的PBR少了一些,实现了CustomUV,从而减少了Pixel Shader Stage计算的部分。
现在,我们使用Replection Cubemap来实现油膜的光泽度,而在下一个优化版本中,将更改为Dual Parabolic Reflection,以进一步优化它。
创作原型时,使用Amplify Shader Editor来实现了它。
实现了Eye Refraction function, Mode写为Create的话之后在代码中会以函数形式来记录。
写最终代码的时候,有着更易读的优点。
An important part of my development of the pupils was to pinpoint exactly what the final requirements of the art team were.
The first two meshes were used by the art team voluntarily, but the two draw-calls were consumed and there was no refraction, so we simply discussed with the art team and then used two specular One is calculated from the position of the actual solar light source and the other is calculated from the point of view of the camera, that is, the camera point of view.
I also had to find the overall feeling of completeness, and my final goal for the art team was Horizon Zero Dawn.
In the implementation process, we merged two draw-calls into one, and we reduced the precision as much as possible, eliminated all GGX operations, and implemented only with Normalized Blinn-Phong Specular.
The ALU increased slightly when refracting, but by removing some of the PBR dependent parts, the overall ALU was reduced compared to the normal PBR, and the CustomUV implementation reduced some of the computation on the Pixel Shader Stage.Currently, the reflection cube map is used to realize the gloss of the retina. In the next optimized version, it will be changed to Dual Parabolic Reflection to optimize it further.
最好使用简单的纹理开发原型,以便艺术团队清楚地了解实现意图。
在这种程度上,我和美术讨论了如何改善眼球光照处理,并不断改善。
通常,Cube-Map reflection主要用于角色选择窗口。
在实际游戏中,通过仅选择视觉上不明显的部分来删除命令,并制作一个Shader for LOD MATERIAL。当前尽量不把Sub shader划分为多个。
It is a good idea to develop prototypes with simple textures so that the art team knows their implementation intent.
At this point, I discussed further with the art team to discuss how to improve the pupil lighting process and to continue to develop.
Normally Cube-Map reflection is only used in the character selection window.
In real gameplay, we’ll only remove parts that aren’t visually obvious and remove commands and create another shader for LOD MATERIAL.We are not dividing the currently available Sub shader into several.
Energy conserved specular blinn-phong implementation record
///////////////////////////////////////////////////////////////////////////////
// Lighting Functions //
///////////////////////////////////////////////////////////////////////////////
half3 LightingLambert(half3 lightColor, half3 lightDir, half3 normal)
{
half NdotL = saturate(dot(normal, lightDir));
#ifdef ENERGY_CONSERVED_DIFFUSE
return (1.0 / PI ) * lightColor * NdotL;
#else
return lightColor * NdotL;
#endif
}
half3 LightingSpecular(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specular, half smoothness)
{
float3 halfVec = SafeNormalize(float3(lightDir) + float3(viewDir));
half NdotH = saturate(dot(normal, halfVec)); //specualrDot
half modifier = 0;
#ifdef ENERGY_CONSERVED_BLINNPHONG_2PI
//PI is already defined location from "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
half norm = (smoothness + 2 ) / (2 * PI ); //refer document by "http://mathinfo.univ-reims.fr/IMG/pdf/Using_the_modified_Phong_reflectance_model_for_Physically_based_rendering_-_Lafortune.pdf"
modifier = pow(NdotH, smoothness) * norm;
#else
modifier = pow(NdotH, smoothness);
#endif
#ifdef ENERGY_CONSERVED_BLINNPHONG_8PI
half norm = (smoothness + 2)*(smoothness + 4 ) / ((8 * PI )*(2-(smoothness/2) + smoothness)); //refer document by "http://mathinfo.univ-reims.fr/IMG/pdf/Using_the_modified_Phong_reflectance_model_for_Physically_based_rendering_-_Lafortune.pdf"
modifier = pow(NdotH, smoothness) * norm;
#else
modifier = pow(NdotH, smoothness);
#endif
half3 specularReflection = specular.rgb * modifier;
return lightColor * specularReflection;
}
half3 LightingPhysicallyBased(BRDFData brdfData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
{
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = lightColor * (lightAttenuation * NdotL);
return DirectBDRF(brdfData, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}
half3 LightingPhysicallyBased(BRDFData brdfData, Light light, half3 normalWS, half3 viewDirectionWS)
{
return LightingPhysicallyBased(brdfData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS);
}
half3 VertexLighting(float3 positionWS, half3 normalWS)
{
half3 vertexLightColor = half3(0.0, 0.0, 0.0);
#ifdef _ADDITIONAL_LIGHTS_VERTEX
uint lightsCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < lightsCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, positionWS);
half3 lightColor = light.color * light.distanceAttenuation;
vertexLightColor += LightingLambert(lightColor, light.direction, normalWS);
}
#endif
return vertexLightColor;
}
Energy conserved experimental code block.
half3 GlossyEnvironmentReflectionExt(half3 reflectVector, half smoothness, half occlusion)
{
#if !defined(_ENVIRONMENTREFLECTIONS_OFF)
half mip = smoothness;
half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip);
#if !defined(UNITY_USE_NATIVE_HDR)
half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#else
half3 irradiance = encodedIrradiance.rbg;
#endif
return irradiance * occlusion;
#endif // GLOSSY_REFLECTIONS
return _GlossyEnvironmentColor.rgb * occlusion;
}
half4 UniversalFragmentBlinnPhongExtend(InputData inputData, half3 reflectVector, half3 diffuse, half4 specularGloss, half smoothness, half reflectionRoughness, half3 emission, half occlusion,half alpha)
{
Light mainLight = GetMainLight(inputData.shadowCoord);
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
half3 diffuseColor = 1;
diffuseColor = inputData.bakedGI + LightingLambertExt(attenuatedLightColor, mainLight.direction, inputData.normalWS);
diffuseColor *=occlusion;
half3 specularColor = LightingSpecularExtend(attenuatedLightColor, mainLight.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
diffuseColor +=GlossyEnvironmentReflectionExt(reflectVector, reflectionRoughness, occlusion);
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
diffuseColor += LightingLambertExt(attenuatedLightColor, light.direction, inputData.normalWS);
specularColor += LightingSpecularExtend(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
}
#endif
#ifdef _ADDITIONAL_LIGHTS_VERTEX
diffuseColor += inputData.vertexLighting;
#endif
half3 finalColor = diffuseColor * diffuse + emission;
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
finalColor += specularColor;
#endif
return half4(finalColor, alpha);
}
Specular Reflectance experimental code block.
The game I’m developing now implements a point light that doesn’t work at all in the rendering core.
In order to achieve the permeation effect, the LUT of the Ramp method was used to express the depth of ice chunks inherently, and the Glitz phenomenon caused by scattering of ice or snow surface was implemented to give the user a visually interesting feeling.
目前正在开发的游戏在rendering core里Point light完全不能启用。
为了获得透射效果,使用了Ramp形式的LUT来表现冰块具有固有的深度,并通过实现由冰块或眼睛表面散射而形成的Glitz现象,增强了视觉上的趣味感。
而且,由于它通常是透过冰块的材质,所以阴影的强度比普通物件弱很多,一般情况下,方向光的阴影强度大部分使用1,修改后其他所有对象也会受到影响。
选择简单的方法在GetMainLightShadowParams() 函数中定义,在特定shader中放置关键字时,可以降低阴影浓度以进行处理。
In addition, the shadow density is weaker than normal objects because it is usually a transparent material of ice. In general, the shadow intensity of directional light is mostly 1, and all other objects are affected.I chose a simple method and defined it inside the GetMainLightShadowParams () function so that if I put keywords inside a specific shader, it handles it by lowering the shadow density.
Development of ice effect that can be calculated sufficiently with mobile hardware performance. This is mainly used for developing dungeon battle scenes.
Dungeon combat scenes are loaded independently and remove special effects related to weather changes or other environmental changes like other open scenes.
The overall performance was measured and the effect was expressed boldly.
冰效应的发展,可以通过移动硬件性能进行充分计算。
这主要用于开发地牢战斗场景。
地牢战斗场景是独立加载的,并且会删除与天气变化或其他环境变化(如其他开放场景)有关的特殊效果。
测量总体性能,并大胆表达效果。
//Parralex thickness shader here to start.
float2 uv = input.uv.xy * float2( 1,1 ) + float2( 0,0 );
float2 uv_BottomDepthMap = input.uv.xy * _BottomDepthMap_ST.xy + _BottomDepthMap_ST.zw;
float3 tanToWorld0 = float3( WorldSpaceTangent.x, WorldSpaceBiTangent.x, WorldSpaceNormal.x );
float3 tanToWorld1 = float3( WorldSpaceTangent.y, WorldSpaceBiTangent.y, WorldSpaceNormal.y );
float3 tanToWorld2 = float3( WorldSpaceTangent.z, WorldSpaceBiTangent.z, WorldSpaceNormal.z );
float3 ViewDirTS = tanToWorld0 * WorldSpaceViewDirection.x + tanToWorld1 * WorldSpaceViewDirection.y + tanToWorld2 * WorldSpaceViewDirection.z;
ViewDirTS = normalize(ViewDirTS); //Parallex ice ground viewDir according to tangent
float4 mask_Var = tex2D(_Mask , uv);
float2 plx_bottom = ( ( mask_Var.b - 1 ) * ( ViewDirTS.xy / ViewDirTS.z ) * OutterDepthScale ) + uv;
float2 uv_MiddleDepthMap = input.uv.xy * _MiddleDepthMap_ST.xy + _MiddleDepthMap_ST.zw;
float2 plx_middle = ( ( mask_Var.g - 1 ) * ( ViewDirTS.xy / ViewDirTS.z ) * _MiddleDepthScale ) + uv;
float4 combinedMiddleBottomAlbedo = lerp( ( tex2D( _BottomMap, plx_bottom ) * _BottomDark ) , ( tex2D( _MiddleMap, plx_middle ) * _MidDark ) , tex2D( _Mask, plx_middle ).r);
float4 albedoCombined = lerp( combinedMiddleBottomAlbedo , half4(0,0,0,1) , mask_Var.r);
float2 uv_normalTop = input.uv.xy * _normalTop_ST.xy + _normalTop_ST.zw;
float2 uv_RoughnessMap = input.uv.xy * _RoughnessMap_ST.xy + _RoughnessMap_ST.zw;
float4 roughness_Var = tex2D( _RoughnessMap, uv_RoughnessMap );
float3 normalCombined = lerp( float3(0,0,1) , UnpackNormalScale( tex2D( _normalTop, uv_normalTop ), 1.0f ) , ( mask_Var.g * roughness_Var ).rgb);