Jiangman (Lobi) Zhao

Project

Unity Shading

Car painting

Car Scene
bakeDistance
Red Flame
//////////////////// fragment shader snippet ////////////////////
...

float speed = frac(_Time.x * + _lavaSpeed);
float4 wave = tex2D(_lavawaveTex, (i.texcoord.zw + float2(0, speed)) * 2) * 2 - 1;
wave = wave.r * _lavaWave;
float4 gas = tex2D(_lavawaveTex, float2(i.texcoord.z * _gasOffset.x, i.texcoord.w * _gasOffset.y + frac(_Time.y * + _gasOffset.z)));
float4 lava = tex2D(_lavaTex, float2(i.texcoord.zw + wave.xy));
float4 mask = tex2D(_lavaTex, i.texcoord.zw);
lava = (lava.r + gas.g * _gasOffset.w) * _lavaCol * mask.g;

...
Lava Storm
Edge Loop
Dragon Scale
Stripe
stylized Multiple Pass
vertex Noise
//////////////////// vertex shader snippet ////////////////////
...

// make noise in worldSpace
float speed = frac(_Time.y * _speed);
float3 blend = v.vertex.xyz * _scale;
float4 noiseXY = tex2Dlod(_Noise, float4(blend.xy + speed, 0, 0));
float4 noiseYZ = tex2Dlod(_Noise, float4(blend.yz + speed, 0, 0));
float4 noiseXZ = tex2Dlod(_Noise, float4(blend.xz + speed, 0, 0));
float4 noise = noiseXY;

// lerp
noise = lerp(noise, noiseXZ, o.normal.y);
noise = lerp(noise, noiseYZ, o.normal.x);
o.color = v.color;
noise *= o.color;

//noise plus v.vertex
v.vertex += v.normal * (noise * _range);
o.pos = UnityObjectToClipPos(v.vertex);

...
fixed4 frag(v2f i) : SV_Target
{
    // WAVE cubemap
    float speed = frac(_Time.y * _speed);
    float3 flowDir = tex2D(_fmap, float2(i.texcoord.x * _offset.x + speed, i.texcoord.y * _offset.y)) * 2 - 1;
    flowDir *= _strength;
    float offset0 = frac(_Time.w * 0.5 + 0.5);
    float offset1 = frac(_Time.w * 0.5 + 1.0);
    float offsetlerp = abs((0.5 - offset0) / 0.5);
    fixed4 msk = tex2D(_MaskTex, i.texcoord);
    fixed4 refl0 = tex2Dproj(_ReflectionTex, UNITY_PROJ_COORD(i.refl) + float4(flowDir.xy * offset0, 0, 0));
    fixed4 refl1 = tex2Dproj(_ReflectionTex, UNITY_PROJ_COORD(i.refl) + float4(flowDir.xy * offset1, 0, 0));
    fixed4 refl = lerp(refl0, refl1, offsetlerp);
    refl.a *= msk.r * _Alpha * i.color.a;
    return refl;
}

Card battle

In game battle
low cost shadow

Tools Development

auto usd files
usd sources
c++ imageBlur
Qt Python Layout
Qt Python Layout
c++ Curve Editor
OpenGl fun

rigging

Facial rigging

FacialRiggingTest
facerigging

Dynamic bone

Grooming

Create In Maya
Rendering In Unreal
Short Fur

Modeling

chess Game Online

Avatar Store
Character HairStyle
Character HairStyle
Teahouse
Chinese garden

substance workflow

Hard surface texture
Surface Textures
Vehicle
Vehicle Texture

PhotoScan workflow

PBR Fiber Photo-Scan
Fire Hydrant
Tree Trunk

Patent

cabin Screen-shoot

terrain shadow case

  1. Set a camera as the light position, get a renderTexture
building shadow case
Cabin Render Texture
  1. Shading and sampling RT
    // project RenderTexture in world position
    v2f vert(appdata v)
    {
        fixed4 tex = tex2D(_MainTex, i.texcoord);
        fixed spec = tex.a;
    
        float2 shadow_uv = mul(_ShadowVPMatrix, i.worldPos).xy * 0.5 + 0.5;
        fixed atten = tex2D(_CurrentShadowmap, shadow_uv).r;
        fixed4 shadow_color = lerp(_ShadowCol, fixed4(1, 1, 1, 1), atten);
        //blend shadow and texture
        tex = _MainColor * _DirectionalLightColor * shadow_color * tex;
    
        half4 normalMap = tex2D(_BumpMap, i.texcoord);
        half3 normalDir = normalize(UnpackNormal(normalMap));
        half3 viewDir = normalize(i.viewDir);
        half3 lightDir = normalize(i.lightDir);
        half3 h = normalize(viewDir + lightDir);
        float r = max(0, dot(h, normalDir));
        tex += _SpecularCol * spec * pow(r, 48);
        return tex;
    }

    element shadow case

    Cabin Building
    1. Bake 4 directional shadow in solo channel
    Directional Shadow
    1. Shading and sampling RGBA channel shadow, and then dye color to them
      fixed4 frag(v2f i) : COLOR
      {
          fixed4 tex = tex2D(_MainTex, i.texcoord.xy);
          //added shadow information
          fixed4 lm = tex2D(_ShasowTex, i.texcoord.zw);
      
          fixed shadowvalue = dot(lm, _ShadowDir);
      
          tex = lerp(tex * shadowvalue * _ShadowCol, tex, shadowvalue);
          tex = lerp(tex, tex * _LightPower, shadowvalue * 1.8);
      
          #ifdef _GRADIENT_ON
              tex *= i.gradient;
          #endif
      
          return tex;
      }

      elements batch

      • Generating UV3 to show shadow channel, and then to deal static batch.
      Player Building
      Running Batched

      about me

      Education

      University of Pennsylvania. USA, PA

      • Computer Graphics and Game Technology Sep 2024 - Oct 2026

      • Computer and Information Technology Sep 2023 - Jul 2024

      Skills

      Programming Skills

      • C++, C, Assembly, Python, Java, OpenGL, GLSL

      DevTools

      • Snapdragon Profiler, Unity, Unreal Engine5, Qt creator, cMake, Maya, Substance Designer

      Core Skills

      • Computer Graphic, Developed and optimized mobile application, Scripting, Shader-Programming

      Contact