three 基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.3 KiB

2 years ago
/**
* MMD Toon Shader
*
* This shader is extended from MeshPhongMaterial, and merged algorithms with
* MeshToonMaterial and MeshMetcapMaterial.
* Ideas came from https://github.com/mrdoob/three.js/issues/19609
*
* Combining steps:
* * Declare matcap uniform.
* * Add gradientmap_pars_fragment.
* * Use gradient irradiances instead of dotNL irradiance from MeshPhongMaterial.
* (Replace lights_phong_pars_fragment with lights_mmd_toon_pars_fragment)
* * Add mmd_toon_matcap_fragment.
*/
import { UniformsUtils, ShaderLib } from '../../../build/three.module.js';
const lights_mmd_toon_pars_fragment = `
varying vec3 vViewPosition;
#ifndef FLAT_SHADED
varying vec3 vNormal;
#endif
struct BlinnPhongMaterial {
vec3 diffuseColor;
vec3 specularColor;
float specularShininess;
float specularStrength;
};
void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;
#ifndef PHYSICALLY_CORRECT_LIGHTS
irradiance *= PI; // punctual light
#endif
reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
}
void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
}
#define RE_Direct RE_Direct_BlinnPhong
#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
#define Material_LightProbeLOD( material ) (0)
`;
const mmd_toon_matcap_fragment = `
#ifdef USE_MATCAP
vec3 viewDir = normalize( vViewPosition );
vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );
vec3 y = cross( viewDir, x );
vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks
vec4 matcapColor = texture2D( matcap, uv );
matcapColor = matcapTexelToLinear( matcapColor );
#ifdef MATCAP_BLENDING_MULTIPLY
outgoingLight *= matcapColor.rgb;
#elif defined( MATCAP_BLENDING_ADD )
outgoingLight += matcapColor.rgb;
#endif
#endif
`;
const MMDToonShader = {
defines: {
TOON: true,
MATCAP: true,
MATCAP_BLENDING_ADD: true,
},
uniforms: UniformsUtils.merge( [
ShaderLib.toon.uniforms,
ShaderLib.phong.uniforms,
ShaderLib.matcap.uniforms,
] ),
vertexShader: ShaderLib.phong.vertexShader,
fragmentShader:
ShaderLib.phong.fragmentShader
.replace(
'#include <common>',
`
#ifdef USE_MATCAP
uniform sampler2D matcap;
#endif
#include <common>
`
)
.replace(
'#include <envmap_common_pars_fragment>',
`
#include <gradientmap_pars_fragment>
#include <envmap_common_pars_fragment>
`
)
.replace(
'#include <lights_phong_pars_fragment>',
lights_mmd_toon_pars_fragment
)
.replace(
'#include <envmap_fragment>',
`
#include <envmap_fragment>
${mmd_toon_matcap_fragment}
`
),
};
export { MMDToonShader };