Three.js is a good framework to make a landing page with 3D object & visual effecting.
This is a function to render 3D text with shader programming.
let AddText = (scene, font , fontsize, position, text) =>
{
let vTxShader=`
varying vec3 vWorldPosition;
varying vec4 fragCoord;
varying vec2 vUv;
uniform vec3 iResolution;
uniform float iTime;
varying vec4 fragColor;
uniform float iFontsize;
uniform vec3 iPosition;
#define PI 3.14159265358979
#define P2 6.28318530717959
float Pow5 (float x)
{
return x*x * x*x * x;
}
float saturate(float x)
{
return max(0., min(1., x));
}
vec3 F_Schlick1(float u, vec3 f0, float f90) {
return f0 + (vec3(f90) - f0) * pow(1.0 - u, 5.0);
}
float F_Schlick2(float u, float f0) {
float f = pow(1.0 - u, 5.0);
return f + f0 * (1.0 - f);
}
vec3 F_Schlick(vec3 f0, float f90, float u) {
return f0 + (f90 - f0) * exp2((-5.55473f * u - 6.98316f) * u); //native_powr(1.f - u, 5.f);
}
float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness) {
float energyBias = mix(0., 0.5, linearRoughness);
float energyFactor = mix(1.0, 1.0 / 1.51, linearRoughness);
float fd90 = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
vec3 f0 = vec3(1.0f, 1.0f, 1.0f);
float lightScatter = F_Schlick(f0, fd90, NdotL).r;
float viewScatter = F_Schlick(f0, fd90, NdotV).r;
return lightScatter * viewScatter * energyFactor;
}
float DisneyDiffuse(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
{
float fd90 = 0.5 + 2. * LdotH * LdotH * perceptualRoughness;
// Two schlick fresnel term
float lightScatter = (1. + (fd90 - 1.) * Pow5(1. - NdotL));
float viewScatter = (1. + (fd90 - 1.) * Pow5(1. - NdotV));
return lightScatter * viewScatter;
}
float ggxNormalDistribution( float NdotH, float roughness )
{
float a2 = roughness * roughness;
float d = ((NdotH * a2 - NdotH) * NdotH + 1.);
return a2 / (d * d * PI);
}
float ggxSchlickMaskingTerm(float NdotL, float NdotV, float roughness)
{
float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - roughness) + roughness);
float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - roughness) + roughness);
float G = 0.5/(GGXV + GGXL);
return G;
}
vec3 schlickFresnel(vec3 f0, float lDotH)
{
return f0 + (vec3(1.0f, 1.0f, 1.0f) - f0) * pow(1.0f - lDotH, 5.0f);
}
float D_GGX(float NoH, float roughness) {
float a = NoH * roughness;
float k = roughness / (1.0 - NoH * NoH + a * a);
return k * k * (1.0 / PI);
}
float V_Kelemen(float LoH) {
return 0.25 / (LoH * LoH);
}
float Fd_Lambert() {
return 1.0 / PI;
}
float V_SmithGGXCorrelated(float NoV, float NoL, float roughness) {
float a2 = roughness * roughness;
float GGXV = NoL * sqrt(NoV * NoV * (1.0 - a2) + a2);
float GGXL = NoV * sqrt(NoL * NoL * (1.0 - a2) + a2);
return 0.5 / (GGXV + GGXL);
}
float roughnessValue = 1.1;
vec3 WorldSpaceCameraPos = vec3(0.1, 0.8, 0.8);
vec3 lightpos = vec3(0., 4., -8.);
vec3 baseColor = vec3(0.9, .45, .1);
float lightColor = 3.5;
float clearCoat = 0.5;
float transparent = .8;
void main() {
vUv = uv;
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
vWorldPosition = vec3(-worldPosition.z, worldPosition.y, -worldPosition.x);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vec3 origin = (vec4(iPosition,1.0) * modelMatrix).xyz + vec3(iFontsize/2.5, 5.0, 2.0);
WorldSpaceCameraPos += origin;
lightpos += origin;
float linearRoughness = roughnessValue * roughnessValue;
vec3 normalDirection = normalize(worldPosition.xyz);
vec3 viewDirection = normalize(WorldSpaceCameraPos-worldPosition.xyz);
vec3 lightDirection = normalize(lightpos-worldPosition.xyz);
vec3 halfDirection = normalize(lightDirection + viewDirection );
float NdotL = saturate(dot(normalDirection, lightDirection));
float NdotV = saturate(dot(normalDirection, viewDirection));
float VdotH = saturate(dot(viewDirection, halfDirection));
float NdotH = saturate(dot(normalDirection, halfDirection));
float LdotH = saturate(dot(lightDirection, halfDirection));
float diffuse = Fr_DisneyDiffuse(NdotV, NdotL, LdotH, linearRoughness);
vec3 diffuseColor = baseColor * diffuse/PI;
vec3 F = schlickFresnel(baseColor, LdotH);
float D = ggxNormalDistribution(NdotH, linearRoughness);
float G = ggxSchlickMaskingTerm(NdotL, NdotV, linearRoughness);
vec3 specularReflection = lightColor * baseColor * (F * D * G);
float clearCoatPerceptualRoughness = clamp(roughnessValue, 0.089, 1.0);
float clearCoatRoughness = clearCoatPerceptualRoughness * clearCoatPerceptualRoughness;
float f0 = 0.04;
float Dc = D_GGX(NdotH, clearCoatRoughness);
float Vc = V_Kelemen(LdotH);
float Fc = F_Schlick2(f0, LdotH) * clearCoat; // clear coat strength
float Frc = (Dc * Vc) * Fc;
vec3 Fd = diffuseColor * Fd_Lambert();
float V = V_SmithGGXCorrelated(NdotV, NdotL, clearCoatRoughness);
vec3 Fr = (Dc * V) * F;
vec3 CoatColor = baseColor * ((Fd + Fr * (1.0 - Fc)) * (1.0 - Fc) + Frc);
float alpha = transparent;//baseColor.a;
vec3 specularColor = specularReflection;
vec4 glassColor = vec4(diffuseColor + specularColor, alpha);
fragColor = vec4(diffuseColor, 1.0);
fragColor = vec4(specularReflection, 1.0);
fragColor = glassColor;
fragCoord = gl_Position;
}
`;
let fTxShader=`
varying vec4 fragColor;
void main(void)
{
gl_FragColor = fragColor;
}
`;
txtMaterial.push(new THREE.ShaderMaterial({
side: THREE.DoubleSide,
uniforms: {
iResolution: {
value: new THREE.Vector3(window.innerWidth , window.innerHeight, 1)
},
iTime: {
value: time
},
iFontsize: {
value: fontsize
},
iPosition: {
value: position
}
},
vertexShader: vTxShader,
fragmentShader: fTxShader
})
);
const textGeometry = new TextGeometry( text, {
font: font,
size: fontsize,
height: fontsize,
curveSegments: 20,
bevelEnabled: true,
bevelThickness: fontsize*.5,
bevelSize: fontsize/10.0,
bevelOffset: 0.0,
bevelSegments: 20
} );
var textmesh = new THREE.Mesh( textGeometry, [txtMaterial[txtMaterial.length-1],txtMaterial[txtMaterial.length-1]]);
textmesh.position.set(position.x, position.y, position.z);
scene.add( textmesh );
textTitle.push(textmesh);
return textmesh;
}
Top comments (0)