diff --git a/src/components/gltf-model-plus.js b/src/components/gltf-model-plus.js index 912490b97e552d7c4aff1b6b69c519c29a66869d..b4d25bb3989aea9619a3ebc2d4f6b3bc8e5de9cf 100644 --- a/src/components/gltf-model-plus.js +++ b/src/components/gltf-model-plus.js @@ -1,5 +1,6 @@ import nextTick from "../utils/next-tick"; import SketchfabZipWorker from "../workers/sketchfab-zip.worker.js"; +import MobileStandardMaterial from "../materials/MobileStandardMaterial"; import cubeMapPosX from "../assets/images/cubemap/posx.jpg"; import cubeMapNegX from "../assets/images/cubemap/negx.jpg"; import cubeMapPosY from "../assets/images/cubemap/posy.jpg"; @@ -255,8 +256,12 @@ async function loadGLTF(src, contentType, preferredTechnique, onProgress) { gltf.scene.traverse(object => { if (object.material && object.material.type === "MeshStandardMaterial") { - object.material.envMap = envMap; - object.material.needsUpdate = true; + if (preferredTechnique === "KHR_materials_unlit") { + object.material = MobileStandardMaterial.fromStandardMaterial(object.material); + } else { + object.material.envMap = envMap; + object.material.needsUpdate = true; + } } }); diff --git a/src/materials/MobileStandardMaterial.js b/src/materials/MobileStandardMaterial.js new file mode 100644 index 0000000000000000000000000000000000000000..aa9e10de101be73807c0259e1eb75f222e4d974d --- /dev/null +++ b/src/materials/MobileStandardMaterial.js @@ -0,0 +1,110 @@ +const VERTEX_SHADER = ` +#include <common> +#include <uv_pars_vertex> +#include <uv2_pars_vertex> +#include <color_pars_vertex> +#include <fog_pars_vertex> +#include <morphtarget_pars_vertex> +#include <skinning_pars_vertex> +#include <logdepthbuf_pars_vertex> +#include <clipping_planes_pars_vertex> + +void main() { + #include <uv_vertex> + #include <uv2_vertex> + #include <color_vertex> + #include <skinbase_vertex> + + #include <begin_vertex> + #include <morphtarget_vertex> + #include <skinning_vertex> + #include <project_vertex> + #include <logdepthbuf_vertex> + + #include <worldpos_vertex> + #include <clipping_planes_vertex> + #include <fog_vertex> +} +`; + +const FRAGMENT_SHADER = ` +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; + +#include <common> +#include <color_pars_fragment> +#include <uv_pars_fragment> +#include <uv2_pars_fragment> +#include <map_pars_fragment> +#include <aomap_pars_fragment> +#include <emissivemap_pars_fragment> +#include <fog_pars_fragment> +#include <logdepthbuf_pars_fragment> +#include <clipping_planes_pars_fragment> + +void main() { + #include <clipping_planes_fragment> + + vec4 diffuseColor = vec4(diffuse, opacity); + ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + vec3 totalEmissiveRadiance = emissive; + + #include <logdepthbuf_fragment> + #include <map_fragment> + #include <color_fragment> + #include <alphatest_fragment> + #include <emissivemap_fragment> + + reflectedLight.indirectDiffuse += vec3(1.0); + + #include <aomap_fragment> + + reflectedLight.indirectDiffuse *= diffuseColor.rgb; + + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + + gl_FragColor = vec4(outgoingLight, diffuseColor.a); + + #include <premultiplied_alpha_fragment> + #include <tonemapping_fragment> + #include <encodings_fragment> + #include <fog_fragment> +} +`; + +export default class MobileStandardMaterial extends THREE.ShaderMaterial { + static fromStandardMaterial(material) { + const parameters = { + vertexShader: VERTEX_SHADER, + fragmentShader: FRAGMENT_SHADER, + uniforms: { + uvTransform: { value: new THREE.Matrix3() }, + diffuse: { value: material.color }, + opacity: { value: material.opacity }, + map: { value: material.map }, + aoMapIntensity: { value: material.aoMapIntensity }, + aoMap: { value: material.aoMap }, + emissive: { value: material.emissive }, + emissiveMap: { value: material.emissiveMap } + }, + fog: true, + lights: false, + opacity: material.opacity, + transparent: material.transparent, + skinning: material.skinning, + morphTargets: material.morphTargets + }; + + const mobileMaterial = new MobileStandardMaterial(parameters); + + mobileMaterial.color = material.color; + mobileMaterial.map = material.map; + mobileMaterial.aoMap = material.aoMap; + mobileMaterial.aoMapIntensity = material.aoMapIntensity; + mobileMaterial.emissive = material.emissive; + mobileMaterial.emissiveMap = material.emissiveMap; + + return mobileMaterial; + } +}