diff --git a/src/components/gltf-model-plus.js b/src/components/gltf-model-plus.js index 912490b97..b4d25bb39 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 000000000..aa9e10de1 --- /dev/null +++ b/src/materials/MobileStandardMaterial.js @@ -0,0 +1,110 @@ +const VERTEX_SHADER = ` +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void main() { + #include + #include + #include + #include + + #include + #include + #include + #include + #include + + #include + #include + #include +} +`; + +const FRAGMENT_SHADER = ` +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void main() { + #include + + vec4 diffuseColor = vec4(diffuse, opacity); + ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + vec3 totalEmissiveRadiance = emissive; + + #include + #include + #include + #include + #include + + reflectedLight.indirectDiffuse += vec3(1.0); + + #include + + reflectedLight.indirectDiffuse *= diffuseColor.rgb; + + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + + gl_FragColor = vec4(outgoingLight, diffuseColor.a); + + #include + #include + #include + #include +} +`; + +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; + } +}