Game Development 8 min read

Recreating the Genshin Impact Login Screen with Three.js Shaders

This article walks through how to replicate Genshin Impact's login interface using three.js, custom GLSL shaders, instanced meshes, and post‑processing effects, providing detailed code snippets and explanations for background gradients, cloud layers, pillars, light beams, stars, fog, and rendering optimizations.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Recreating the Genshin Impact Login Screen with Three.js Shaders

Background

The background is a three‑color gradient created with a Shader using the smoothstep function together with the UV coordinate's y component.

float y=1.-uv.y;
float mask1=1.-smoothstep(0.,stop1,y);
float mask2=smoothstep(0.,stop1,y)*(1.-smoothstep(stop1,stop2,y));
float mask3=smoothstep(stop1,stop2,y);
col+=col1*mask1;
col+=col2*mask2;
col+=col3*mask3;

Background Cloud

The cloud layer consists of two planar meshes, each with its own mask texture. The mask texture's red channel is sampled as the alpha value, and a base color is applied.

vec2 uv=vUv;
vec4 tex=texture(uTexture,uv);
float alpha=tex.r*.4;
vec3 col=vec3(1.8);
gl_FragColor=vec4(col,alpha);

A second plane mixes two colors using the mix function.

vec3 col=vec3(.090,.569,.980);
col=mix(col,vec3(.93),vec3(pow(tex.r,.4)));

Pillars

Raw pillar data consists of many random mesh entries (model name, position, rotation, scale). These are grouped into logical collections, then rendered with THREE.InstancedMesh to efficiently draw many instances with varying transforms.

Cloud Layer

Instanced meshes are also used for the cloud layer. The UV coordinates are randomized in the vertex shader to give each cloud a unique pattern.

vec2 distortUV(vec2 uv,vec2 offset){
    vec2 wh=vec2(2.,4.);
    uv/=wh;
    float rn=ceil(random(offset)*wh.x*wh.y);
    vec2 cell=vec2(1.,1.)/wh;
    uv+=vec2(cell.x*mod(rn,wh.x),cell.y*(ceil(rn/wh.x)-1.));
    return uv;
}

void main(){
    ...
    vUv=distortUV(uv,instPosition.xy);
    ...
}

Light Beam

The light beam material also uses a mask texture. A smoothstep mask softens the beam edges.

float mask1=1.;
mask1*=smoothstep(0.,.5,uv.y);
mask1*=smoothstep(0.,.1,uv.x);
mask1*=smoothstep(1.,.9,uv.x);

Stars

Stars are rendered with THREE.Points . Each particle’s position is random, and the shader samples a mask texture with a randomized UV to display three different star shapes.

float seed=random(vRandom);
float randId=floor(seed*3.)/3.;
float mask=texture(uTexture,vec2(uv.x/3.+randId,uv.y)).r;

Fog

Fog is generated in the shader using noise functions to create a volumetric effect.

float getNoise(vec3 p){
    float noise=0.;
    noise=saturate(cnoise(p*vec3(.012,.012,0.)+vec3(iTime*.25))+.2);
    noise+=saturate(cnoise(p*vec3(.004,.004,0.)-vec3(iTime*.15))+.1);
    noise=saturate(noise);
    noise*=(1.-smoothstep(-5.,45.,p.y));
    noise*=(smoothstep(-200.,-35.,p.y));
    noise*=(smoothstep(0.,40.,p.x)+(1.-smoothstep(-40.,-0.,p.x)));
    return noise;
}

Rendering Optimization

The scene uses THREE.Fog to soften distant pillars, and post‑processing effects from the postprocessing library: a BloomEffect and a ToneMappingEffect with the ACES_FILMIC curve.

Material shaders are modified via onBeforeCompile to replace the default lighting with a toon‑style shading:

float dotNL_toon=smoothstep(.25,.27,dotNL);
vec3 irradiance=dotNL_toon*directLight.color;

Other Details

Complex animations for doors and paths are omitted; refer to the project source for additional comments.

Source Code

GitHub repository: https://github.com/alphardex/genshin-replica

graphicsgame developmentThree.jsWebGLshaderInstancedMesh
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.