mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
wip: materials
This commit is contained in:
parent
b37c1b465f
commit
457d871269
@ -1,20 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { MeshBasicMaterial } from 'three';
|
||||
import { bindProps, propsValues } from '../tools';
|
||||
import Material, { wireframeProps } from './Material';
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshBasicMaterial(propsValues(this.$props));
|
||||
},
|
||||
addWatchers() {
|
||||
bindProps(this, Object.keys(wireframeProps), this.material);
|
||||
},
|
||||
},
|
||||
__hmrId: 'BasicMaterial',
|
||||
});
|
19
src/materials/BasicMaterial.ts
Normal file
19
src/materials/BasicMaterial.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { MeshBasicMaterial } from 'three'
|
||||
import { bindProps, propsValues } from '../tools'
|
||||
import Material, { wireframeProps } from './Material'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const material = new MeshBasicMaterial(propsValues(this.$props))
|
||||
bindProps(this, Object.keys(wireframeProps), material)
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'BasicMaterial',
|
||||
})
|
@ -1,20 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { MeshLambertMaterial } from 'three';
|
||||
import { bindProps, propsValues } from '../tools';
|
||||
import Material, { wireframeProps } from './Material';
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshLambertMaterial(propsValues(this.$props));
|
||||
},
|
||||
addWatchers() {
|
||||
bindProps(this, Object.keys(wireframeProps), this.material);
|
||||
},
|
||||
},
|
||||
__hmrId: 'LambertMaterial',
|
||||
});
|
19
src/materials/LambertMaterial.ts
Normal file
19
src/materials/LambertMaterial.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { MeshLambertMaterial } from 'three'
|
||||
import { bindProps, propsValues } from '../tools'
|
||||
import Material, { wireframeProps } from './Material'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const material = new MeshLambertMaterial(propsValues(this.$props))
|
||||
bindProps(this, Object.keys(wireframeProps), material)
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'LambertMaterial',
|
||||
})
|
@ -1,25 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { MeshMatcapMaterial, TextureLoader } from 'three';
|
||||
import { propsValues, getMatcapUrl } from '../tools';
|
||||
import Material from './Material';
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
src: String,
|
||||
name: String,
|
||||
flatShading: Boolean,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const src = this.name ? getMatcapUrl(this.name) : this.src;
|
||||
const opts = propsValues(this.$props, ['src', 'name']);
|
||||
opts.matcap = new TextureLoader().load(src);
|
||||
this.material = new MeshMatcapMaterial(opts);
|
||||
},
|
||||
addWatchers() {
|
||||
// TODO
|
||||
},
|
||||
},
|
||||
__hmrId: 'MatcapMaterial',
|
||||
});
|
22
src/materials/MatcapMaterial.ts
Normal file
22
src/materials/MatcapMaterial.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { MeshMatcapMaterial, TextureLoader } from 'three'
|
||||
import { propsValues, getMatcapUrl } from '../tools'
|
||||
import Material from './Material'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
src: String,
|
||||
name: { type: String, default: '0404E8_0404B5_0404CB_3333FC' },
|
||||
flatShading: Boolean,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const src = this.src ? this.src : getMatcapUrl(this.name)
|
||||
const opts = propsValues(this.$props, ['src', 'name'])
|
||||
opts.matcap = new TextureLoader().load(src)
|
||||
return new MeshMatcapMaterial(opts)
|
||||
},
|
||||
},
|
||||
__hmrId: 'MatcapMaterial',
|
||||
})
|
@ -1,63 +0,0 @@
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { FrontSide } from 'three';
|
||||
|
||||
export default defineComponent({
|
||||
inject: ['three', 'mesh'],
|
||||
props: {
|
||||
color: { type: [String, Number], default: '#ffffff' },
|
||||
depthTest: { type: Boolean, default: true },
|
||||
depthWrite: { type: Boolean, default: true },
|
||||
fog: { type: Boolean, default: true },
|
||||
opacity: { type: Number, default: 1 },
|
||||
side: { type: Number, default: FrontSide },
|
||||
transparent: Boolean,
|
||||
vertexColors: Boolean,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
material: this,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.createMaterial();
|
||||
this.mesh.setMaterial(this.material);
|
||||
|
||||
this._addWatchers();
|
||||
if (this.addWatchers) this.addWatchers();
|
||||
},
|
||||
unmounted() {
|
||||
this.material.dispose();
|
||||
},
|
||||
methods: {
|
||||
setProp(key, value, needsUpdate = false) {
|
||||
this.material[key] = value;
|
||||
this.material.needsUpdate = needsUpdate;
|
||||
},
|
||||
setTexture(texture, key = 'map') {
|
||||
this.setProp(key, texture, true);
|
||||
},
|
||||
_addWatchers() {
|
||||
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
|
||||
watch(() => this[p], () => {
|
||||
if (p === 'color') {
|
||||
this.material.color.set(this.color);
|
||||
} else {
|
||||
this.material[p] = this[p];
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return this.$slots.default ? this.$slots.default() : [];
|
||||
},
|
||||
__hmrId: 'Material',
|
||||
});
|
||||
|
||||
export const wireframeProps = {
|
||||
wireframe: { type: Boolean, default: false },
|
||||
// not needed for WebGL
|
||||
// wireframeLinecap: { type: String, default: 'round' },
|
||||
// wireframeLinejoin: { type: String, default: 'round' },
|
||||
wireframeLinewidth: { type: Number, default: 1 }, // not really useful
|
||||
};
|
85
src/materials/Material.ts
Normal file
85
src/materials/Material.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { FrontSide, Material, Texture } from 'three'
|
||||
|
||||
interface MeshInterface {
|
||||
setMaterial(material: Material): void
|
||||
}
|
||||
|
||||
interface MaterialInterface {
|
||||
mesh?: MeshInterface
|
||||
material?: Material
|
||||
createMaterial?(): Material
|
||||
addWatchers?(m: Material): void
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
inject: ['three', 'mesh'],
|
||||
props: {
|
||||
color: { type: [String, Number], default: '#ffffff' },
|
||||
depthTest: { type: Boolean, default: true },
|
||||
depthWrite: { type: Boolean, default: true },
|
||||
fog: { type: Boolean, default: true },
|
||||
opacity: { type: Number, default: 1 },
|
||||
side: { type: Number, default: FrontSide },
|
||||
transparent: Boolean,
|
||||
vertexColors: Boolean,
|
||||
},
|
||||
setup(): MaterialInterface {
|
||||
return {}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
material: this,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!this.mesh) {
|
||||
console.error('Missing parent Mesh')
|
||||
return
|
||||
}
|
||||
|
||||
if (this.createMaterial) {
|
||||
this.material = this.createMaterial()
|
||||
this.mesh.setMaterial(this.material)
|
||||
this._addWatchers()
|
||||
this.addWatchers?.(this.material)
|
||||
}
|
||||
},
|
||||
unmounted() {
|
||||
this.material?.dispose()
|
||||
},
|
||||
methods: {
|
||||
setProp(key: string, value: any, needsUpdate = false) {
|
||||
if (this.material) {
|
||||
this.material[key] = value
|
||||
this.material.needsUpdate = needsUpdate
|
||||
}
|
||||
},
|
||||
setTexture(texture: Texture, key = 'map') {
|
||||
this.setProp(key, texture, true)
|
||||
},
|
||||
_addWatchers() {
|
||||
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
|
||||
watch(() => this[p], (value) => {
|
||||
if (p === 'color') {
|
||||
this.material.color.set(value)
|
||||
} else {
|
||||
this.material[p] = value
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return this.$slots.default ? this.$slots.default() : []
|
||||
},
|
||||
__hmrId: 'Material',
|
||||
})
|
||||
|
||||
export const wireframeProps = {
|
||||
wireframe: { type: Boolean, default: false },
|
||||
// not needed for WebGL
|
||||
// wireframeLinecap: { type: String, default: 'round' },
|
||||
// wireframeLinejoin: { type: String, default: 'round' },
|
||||
wireframeLinewidth: { type: Number, default: 1 }, // not really useful
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { MeshPhongMaterial } from 'three';
|
||||
import { bindProps, propsValues } from '../tools';
|
||||
import Material, { wireframeProps } from './Material';
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { MeshPhongMaterial } from 'three'
|
||||
import { bindProps, propsValues } from '../tools'
|
||||
import Material, { wireframeProps } from './Material'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
@ -16,21 +16,23 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshPhongMaterial(propsValues(this.$props));
|
||||
},
|
||||
addWatchers() {
|
||||
const material = new MeshPhongMaterial(propsValues(this.$props))
|
||||
|
||||
// TODO : handle flatShading ?
|
||||
['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular'].forEach(p => {
|
||||
const watchProps = ['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular']
|
||||
watchProps.forEach(p => {
|
||||
watch(() => this[p], (value) => {
|
||||
if (p === 'emissive' || p === 'specular') {
|
||||
this.material[p].set(value);
|
||||
material[p].set(value)
|
||||
} else {
|
||||
this.material[p] = value;
|
||||
material[p] = value
|
||||
}
|
||||
});
|
||||
});
|
||||
bindProps(this, Object.keys(wireframeProps), this.material);
|
||||
})
|
||||
})
|
||||
bindProps(this, Object.keys(wireframeProps), material)
|
||||
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'PhongMaterial',
|
||||
});
|
||||
})
|
@ -1,20 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { MeshPhysicalMaterial } from 'three';
|
||||
import { propsValues } from '../tools';
|
||||
import StandardMaterial from './StandardMaterial';
|
||||
|
||||
export default defineComponent({
|
||||
extends: StandardMaterial,
|
||||
props: {
|
||||
flatShading: Boolean,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshPhysicalMaterial(propsValues(this.$props));
|
||||
},
|
||||
addWatchers() {
|
||||
// TODO
|
||||
},
|
||||
},
|
||||
__hmrId: 'PhysicalMaterial',
|
||||
});
|
17
src/materials/PhysicalMaterial.ts
Normal file
17
src/materials/PhysicalMaterial.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { MeshPhysicalMaterial } from 'three'
|
||||
import { propsValues } from '../tools'
|
||||
import StandardMaterial from './StandardMaterial'
|
||||
|
||||
export default defineComponent({
|
||||
extends: StandardMaterial,
|
||||
props: {
|
||||
flatShading: Boolean,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
return new MeshPhysicalMaterial(propsValues(this.$props))
|
||||
},
|
||||
},
|
||||
__hmrId: 'PhysicalMaterial',
|
||||
})
|
@ -1,7 +1,7 @@
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { MeshStandardMaterial } from 'three';
|
||||
import { bindProp, bindProps, propsValues } from '../tools';
|
||||
import Material, { wireframeProps } from './Material';
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { MeshStandardMaterial } from 'three'
|
||||
import { bindProp, bindProps, propsValues } from '../tools'
|
||||
import Material, { wireframeProps } from './Material'
|
||||
|
||||
const props = {
|
||||
aoMapIntensity: { type: Number, default: 1 },
|
||||
@ -13,11 +13,11 @@ const props = {
|
||||
envMapIntensity: { type: Number, default: 1 },
|
||||
lightMapIntensity: { type: Number, default: 1 },
|
||||
metalness: { type: Number, default: 0 },
|
||||
normalScale: { type: Object, default: { x: 1, y: 1 } },
|
||||
normalScale: { type: Object, default: () => ({ x: 1, y: 1 }) },
|
||||
roughness: { type: Number, default: 1 },
|
||||
refractionRatio: { type: Number, default: 0.98 },
|
||||
flatShading: Boolean,
|
||||
};
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
@ -27,23 +27,25 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshStandardMaterial(propsValues(this.$props, ['normalScale']));
|
||||
},
|
||||
addWatchers() {
|
||||
const material = new MeshStandardMaterial(propsValues(this.$props, ['normalScale']))
|
||||
|
||||
// TODO : use setProp, handle flatShading ?
|
||||
Object.keys(props).forEach(p => {
|
||||
if (p === 'normalScale') return;
|
||||
if (p === 'normalScale') return
|
||||
watch(() => this[p], (value) => {
|
||||
if (p === 'emissive') {
|
||||
this.material[p].set(value);
|
||||
material[p].set(value)
|
||||
} else {
|
||||
this.material[p] = value;
|
||||
material[p] = value
|
||||
}
|
||||
});
|
||||
});
|
||||
bindProp(this, 'normalScale', this.material);
|
||||
bindProps(this, Object.keys(wireframeProps), this.material);
|
||||
})
|
||||
})
|
||||
|
||||
bindProp(this, 'normalScale', material)
|
||||
bindProps(this, Object.keys(wireframeProps), material)
|
||||
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'StandardMaterial',
|
||||
});
|
||||
})
|
@ -11,14 +11,14 @@ import {
|
||||
ShaderChunk,
|
||||
ShaderLib,
|
||||
UniformsUtils,
|
||||
} from 'three';
|
||||
} from 'three'
|
||||
|
||||
function replaceAll(string, find, replace) {
|
||||
return string.split(find).join(replace);
|
||||
function replaceAll(string: string, find: string, replace: string) {
|
||||
return string.split(find).join(replace)
|
||||
}
|
||||
|
||||
const meshphongFragHead = ShaderChunk.meshphong_frag.slice(0, ShaderChunk.meshphong_frag.indexOf('void main() {'));
|
||||
const meshphongFragBody = ShaderChunk.meshphong_frag.slice(ShaderChunk.meshphong_frag.indexOf('void main() {'));
|
||||
const meshphongFragHead = ShaderChunk.meshphong_frag.slice(0, ShaderChunk.meshphong_frag.indexOf('void main() {'))
|
||||
const meshphongFragBody = ShaderChunk.meshphong_frag.slice(ShaderChunk.meshphong_frag.indexOf('void main() {'))
|
||||
|
||||
const SubsurfaceScatteringShader = {
|
||||
|
||||
@ -45,23 +45,23 @@ const SubsurfaceScatteringShader = {
|
||||
|
||||
${meshphongFragHead}
|
||||
|
||||
uniform float thicknessPower;
|
||||
uniform float thicknessScale;
|
||||
uniform float thicknessDistortion;
|
||||
uniform float thicknessAmbient;
|
||||
uniform float thicknessAttenuation;
|
||||
uniform vec3 thicknessColor;
|
||||
uniform float thicknessPower
|
||||
uniform float thicknessScale
|
||||
uniform float thicknessDistortion
|
||||
uniform float thicknessAmbient
|
||||
uniform float thicknessAttenuation
|
||||
uniform vec3 thicknessColor
|
||||
|
||||
void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {
|
||||
#ifdef USE_COLOR
|
||||
vec3 thickness = vColor * thicknessColor;
|
||||
vec3 thickness = vColor * thicknessColor
|
||||
#else
|
||||
vec3 thickness = thicknessColor;
|
||||
vec3 thickness = thicknessColor
|
||||
#endif
|
||||
vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));
|
||||
float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;
|
||||
vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;
|
||||
reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;
|
||||
vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion))
|
||||
float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale
|
||||
vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness
|
||||
reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color
|
||||
}
|
||||
` + meshphongFragBody.replace(
|
||||
'#include <lights_fragment_begin>',
|
||||
@ -69,13 +69,13 @@ const SubsurfaceScatteringShader = {
|
||||
ShaderChunk.lights_fragment_begin,
|
||||
'RE_Direct( directLight, geometry, material, reflectedLight );',
|
||||
`
|
||||
RE_Direct( directLight, geometry, material, reflectedLight );
|
||||
RE_Direct( directLight, geometry, material, reflectedLight )
|
||||
#if defined( SUBSURFACE ) && defined( USE_UV )
|
||||
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);
|
||||
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight)
|
||||
#endif
|
||||
`
|
||||
)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export default SubsurfaceScatteringShader;
|
||||
export default SubsurfaceScatteringShader
|
@ -1,20 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { MeshToonMaterial } from 'three';
|
||||
import { bindProps, propsValues } from '../tools';
|
||||
import Material, { wireframeProps } from './Material';
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new MeshToonMaterial(propsValues(this.$props));
|
||||
},
|
||||
addWatchers() {
|
||||
bindProps(this, Object.keys(wireframeProps), this.material);
|
||||
},
|
||||
},
|
||||
__hmrId: 'ToonMaterial',
|
||||
});
|
19
src/materials/ToonMaterial.ts
Normal file
19
src/materials/ToonMaterial.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { MeshToonMaterial } from 'three'
|
||||
import { bindProps, propsValues } from '../tools'
|
||||
import Material, { wireframeProps } from './Material'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
...wireframeProps,
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const material = new MeshToonMaterial(propsValues(this.$props))
|
||||
bindProps(this, Object.keys(wireframeProps), material)
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'ToonMaterial',
|
||||
})
|
@ -1,12 +0,0 @@
|
||||
export { default as BasicMaterial } from './BasicMaterial.js';
|
||||
export { default as LambertMaterial } from './LambertMaterial.js';
|
||||
export { default as MatcapMaterial } from './MatcapMaterial.js';
|
||||
export { default as PhongMaterial } from './PhongMaterial.js';
|
||||
export { default as PhysicalMaterial } from './PhysicalMaterial.js';
|
||||
export { default as ShaderMaterial } from './ShaderMaterial.js';
|
||||
export { default as StandardMaterial } from './StandardMaterial.js';
|
||||
export { default as SubSurfaceMaterial } from './SubSurfaceMaterial.js';
|
||||
export { default as ToonMaterial } from './ToonMaterial.js';
|
||||
|
||||
export { default as Texture } from './Texture.js';
|
||||
export { default as CubeTexture } from './CubeTexture.js';
|
12
src/materials/index.ts
Normal file
12
src/materials/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export { default as BasicMaterial } from './BasicMaterial'
|
||||
export { default as LambertMaterial } from './LambertMaterial'
|
||||
export { default as MatcapMaterial } from './MatcapMaterial'
|
||||
export { default as PhongMaterial } from './PhongMaterial'
|
||||
export { default as PhysicalMaterial } from './PhysicalMaterial'
|
||||
export { default as ShaderMaterial } from './ShaderMaterial'
|
||||
export { default as StandardMaterial } from './StandardMaterial'
|
||||
export { default as SubSurfaceMaterial } from './SubSurfaceMaterial'
|
||||
export { default as ToonMaterial } from './ToonMaterial'
|
||||
|
||||
export { default as Texture } from './Texture'
|
||||
export { default as CubeTexture } from './CubeTexture'
|
Loading…
Reference in New Issue
Block a user