MMDToonShader.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**
  2. * MMD Toon Shader
  3. *
  4. * This shader is extended from MeshPhongMaterial, and merged algorithms with
  5. * MeshToonMaterial and MeshMetcapMaterial.
  6. * Ideas came from https://github.com/mrdoob/three.js/issues/19609
  7. *
  8. * Combining steps:
  9. * * Declare matcap uniform.
  10. * * Add gradientmap_pars_fragment.
  11. * * Use gradient irradiances instead of dotNL irradiance from MeshPhongMaterial.
  12. * (Replace lights_phong_pars_fragment with lights_mmd_toon_pars_fragment)
  13. * * Add mmd_toon_matcap_fragment.
  14. */
  15. import { UniformsUtils, ShaderLib } from '../../../build/three.module.js';
  16. const lights_mmd_toon_pars_fragment = `
  17. varying vec3 vViewPosition;
  18. #ifndef FLAT_SHADED
  19. varying vec3 vNormal;
  20. #endif
  21. struct BlinnPhongMaterial {
  22. vec3 diffuseColor;
  23. vec3 specularColor;
  24. float specularShininess;
  25. float specularStrength;
  26. };
  27. void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
  28. vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;
  29. #ifndef PHYSICALLY_CORRECT_LIGHTS
  30. irradiance *= PI; // punctual light
  31. #endif
  32. reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
  33. reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
  34. }
  35. void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
  36. reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
  37. }
  38. #define RE_Direct RE_Direct_BlinnPhong
  39. #define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong
  40. #define Material_LightProbeLOD( material ) (0)
  41. `;
  42. const mmd_toon_matcap_fragment = `
  43. #ifdef USE_MATCAP
  44. vec3 viewDir = normalize( vViewPosition );
  45. vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );
  46. vec3 y = cross( viewDir, x );
  47. vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks
  48. vec4 matcapColor = texture2D( matcap, uv );
  49. matcapColor = matcapTexelToLinear( matcapColor );
  50. #ifdef MATCAP_BLENDING_MULTIPLY
  51. outgoingLight *= matcapColor.rgb;
  52. #elif defined( MATCAP_BLENDING_ADD )
  53. outgoingLight += matcapColor.rgb;
  54. #endif
  55. #endif
  56. `;
  57. const MMDToonShader = {
  58. defines: {
  59. TOON: true,
  60. MATCAP: true,
  61. MATCAP_BLENDING_ADD: true,
  62. },
  63. uniforms: UniformsUtils.merge( [
  64. ShaderLib.toon.uniforms,
  65. ShaderLib.phong.uniforms,
  66. ShaderLib.matcap.uniforms,
  67. ] ),
  68. vertexShader: ShaderLib.phong.vertexShader,
  69. fragmentShader:
  70. ShaderLib.phong.fragmentShader
  71. .replace(
  72. '#include <common>',
  73. `
  74. #ifdef USE_MATCAP
  75. uniform sampler2D matcap;
  76. #endif
  77. #include <common>
  78. `
  79. )
  80. .replace(
  81. '#include <envmap_common_pars_fragment>',
  82. `
  83. #include <gradientmap_pars_fragment>
  84. #include <envmap_common_pars_fragment>
  85. `
  86. )
  87. .replace(
  88. '#include <lights_phong_pars_fragment>',
  89. lights_mmd_toon_pars_fragment
  90. )
  91. .replace(
  92. '#include <envmap_fragment>',
  93. `
  94. #include <envmap_fragment>
  95. ${mmd_toon_matcap_fragment}
  96. `
  97. ),
  98. };
  99. export { MMDToonShader };