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
457d871269
commit
b3f21b3ec6
@ -9,7 +9,6 @@ interface MaterialInterface {
|
||||
mesh?: MeshInterface
|
||||
material?: Material
|
||||
createMaterial?(): Material
|
||||
addWatchers?(m: Material): void
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
@ -41,8 +40,7 @@ export default defineComponent({
|
||||
if (this.createMaterial) {
|
||||
this.material = this.createMaterial()
|
||||
this.mesh.setMaterial(this.material)
|
||||
this._addWatchers()
|
||||
this.addWatchers?.(this.material)
|
||||
this.addWatchers()
|
||||
}
|
||||
},
|
||||
unmounted() {
|
||||
@ -58,7 +56,7 @@ export default defineComponent({
|
||||
setTexture(texture: Texture, key = 'map') {
|
||||
this.setProp(key, texture, true)
|
||||
},
|
||||
_addWatchers() {
|
||||
addWatchers() {
|
||||
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
|
||||
watch(() => this[p], (value) => {
|
||||
if (p === 'color') {
|
||||
|
@ -1,53 +0,0 @@
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { ShaderMaterial } from 'three';
|
||||
import { propsValues } from '../tools';
|
||||
|
||||
const defaultVertexShader = `
|
||||
varying vec2 vUv;
|
||||
void main(){
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
|
||||
}`;
|
||||
|
||||
const defaultFragmentShader = `
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
gl_FragColor = vec4(vUv.x, vUv.y, 0., 1.0);
|
||||
}`;
|
||||
|
||||
export default defineComponent({
|
||||
inject: ['three', 'mesh'],
|
||||
props: {
|
||||
uniforms: { type: Object, default: () => { return {}; } },
|
||||
vertexShader: { type: String, default: defaultVertexShader },
|
||||
fragmentShader: { type: String, default: defaultFragmentShader },
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
material: this,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.createMaterial();
|
||||
['vertexShader', 'fragmentShader'].forEach(p => {
|
||||
watch(() => this[p], () => {
|
||||
// recreate material if we change either shader
|
||||
this.material.dispose();
|
||||
this.createMaterial();
|
||||
});
|
||||
});
|
||||
},
|
||||
unmounted() {
|
||||
this.material.dispose();
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
this.material = new ShaderMaterial(propsValues(this.$props));
|
||||
this.mesh.setMaterial(this.material);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return this.$slots.default ? this.$slots.default() : [];
|
||||
},
|
||||
__hmrId: 'ShaderMaterial',
|
||||
});
|
47
src/materials/ShaderMaterial.ts
Normal file
47
src/materials/ShaderMaterial.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { ShaderMaterial } from 'three'
|
||||
import Material from './Material'
|
||||
|
||||
const defaultVertexShader = `
|
||||
varying vec2 vUv;
|
||||
void main(){
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
|
||||
}
|
||||
`
|
||||
|
||||
const defaultFragmentShader = `
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
gl_FragColor = vec4(vUv.x, vUv.y, 0., 1.0);
|
||||
}
|
||||
`
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
uniforms: { type: Object, default: () => ({}) },
|
||||
vertexShader: { type: String, default: defaultVertexShader },
|
||||
fragmentShader: { type: String, default: defaultFragmentShader },
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const material = new ShaderMaterial({
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: this.vertexShader,
|
||||
fragmentShader: this.fragmentShader,
|
||||
})
|
||||
|
||||
const watchProps = ['vertexShader', 'fragmentShader']
|
||||
watchProps.forEach(p => {
|
||||
watch(() => this[p], (value) => {
|
||||
this.setProp(p, value, true)
|
||||
})
|
||||
})
|
||||
|
||||
return material
|
||||
},
|
||||
addWatchers() {},
|
||||
},
|
||||
__hmrId: 'ShaderMaterial',
|
||||
})
|
@ -1,55 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { Color, ShaderMaterial as TShaderMaterial, UniformsUtils } from 'three';
|
||||
import SubsurfaceScatteringShader from './SubsurfaceScatteringShader.js';
|
||||
|
||||
export default defineComponent({
|
||||
inject: ['three', 'mesh'],
|
||||
props: {
|
||||
color: { type: String, default: '#ffffff' },
|
||||
thicknessColor: { type: String, default: '#ffffff' },
|
||||
thicknessDistortion: { type: Number, default: 0.4 },
|
||||
thicknessAmbient: { type: Number, default: 0.01 },
|
||||
thicknessAttenuation: { type: Number, default: 0.7 },
|
||||
thicknessPower: { type: Number, default: 2 },
|
||||
thicknessScale: { type: Number, default: 4 },
|
||||
transparent: { type: Boolean, default: false },
|
||||
opacity: { type: Number, default: 1 },
|
||||
vertexColors: { type: Boolean, default: false },
|
||||
},
|
||||
created() {
|
||||
this.createMaterial();
|
||||
this.mesh.setMaterial(this.material);
|
||||
},
|
||||
unmounted() {
|
||||
this.material.dispose();
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const params = SubsurfaceScatteringShader;
|
||||
const uniforms = UniformsUtils.clone(params.uniforms);
|
||||
|
||||
Object.entries(this.$props).forEach(([key, value]) => {
|
||||
let _key = key, _value = value;
|
||||
if (['color', 'thicknessColor'].includes(key)) {
|
||||
if (key === 'color') _key = 'diffuse';
|
||||
_value = new Color(value);
|
||||
}
|
||||
if (!['transparent', 'vertexColors'].includes(key)) {
|
||||
uniforms[_key].value = _value;
|
||||
}
|
||||
});
|
||||
|
||||
this.material = new TShaderMaterial({
|
||||
...params,
|
||||
uniforms,
|
||||
lights: true,
|
||||
transparent: this.transparent,
|
||||
vertexColors: this.vertexColors,
|
||||
});
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return [];
|
||||
},
|
||||
__hmrId: 'SubSurfaceMaterial',
|
||||
});
|
99
src/materials/SubSurfaceMaterial.ts
Normal file
99
src/materials/SubSurfaceMaterial.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { Color, ShaderMaterial, UniformsUtils } from 'three'
|
||||
import SubsurfaceScatteringShader from './SubsurfaceScatteringShader'
|
||||
import Material from './Material'
|
||||
// import { bindProps, propsValues } from '../tools'
|
||||
|
||||
export default defineComponent({
|
||||
extends: Material,
|
||||
props: {
|
||||
thicknessColor: { type: String, default: '#ffffff' },
|
||||
thicknessDistortion: { type: Number, default: 0.4 },
|
||||
thicknessAmbient: { type: Number, default: 0.01 },
|
||||
thicknessAttenuation: { type: Number, default: 0.7 },
|
||||
thicknessPower: { type: Number, default: 2 },
|
||||
thicknessScale: { type: Number, default: 4 },
|
||||
},
|
||||
methods: {
|
||||
createMaterial() {
|
||||
const params = SubsurfaceScatteringShader
|
||||
const uniforms = UniformsUtils.clone(params.uniforms)
|
||||
|
||||
// Object.entries(this.$props).forEach(([key, value]) => {
|
||||
// let _key = key, _value = value
|
||||
// if (['color', 'thicknessColor'].includes(key)) {
|
||||
// if (key === 'color') _key = 'diffuse'
|
||||
// _value = new Color(value)
|
||||
// }
|
||||
// if (!['transparent', 'vertexColors'].includes(key)) {
|
||||
// console.log(_key)
|
||||
// uniforms[_key].value = _value
|
||||
// }
|
||||
// })
|
||||
|
||||
const material = new ShaderMaterial({
|
||||
...params,
|
||||
uniforms,
|
||||
lights: true,
|
||||
transparent: this.transparent,
|
||||
vertexColors: this.vertexColors,
|
||||
})
|
||||
|
||||
return material
|
||||
},
|
||||
},
|
||||
__hmrId: 'SubSurfaceMaterial',
|
||||
})
|
||||
|
||||
|
||||
// export default defineComponent({
|
||||
// inject: ['three', 'mesh'],
|
||||
// props: {
|
||||
// color: { type: String, default: '#ffffff' },
|
||||
// thicknessColor: { type: String, default: '#ffffff' },
|
||||
// thicknessDistortion: { type: Number, default: 0.4 },
|
||||
// thicknessAmbient: { type: Number, default: 0.01 },
|
||||
// thicknessAttenuation: { type: Number, default: 0.7 },
|
||||
// thicknessPower: { type: Number, default: 2 },
|
||||
// thicknessScale: { type: Number, default: 4 },
|
||||
// transparent: { type: Boolean, default: false },
|
||||
// opacity: { type: Number, default: 1 },
|
||||
// vertexColors: { type: Boolean, default: false },
|
||||
// },
|
||||
// created() {
|
||||
// this.createMaterial()
|
||||
// this.mesh.setMaterial(this.material)
|
||||
// },
|
||||
// unmounted() {
|
||||
// this.material.dispose()
|
||||
// },
|
||||
// methods: {
|
||||
// createMaterial() {
|
||||
// const params = SubsurfaceScatteringShader
|
||||
// const uniforms = UniformsUtils.clone(params.uniforms)
|
||||
|
||||
// Object.entries(this.$props).forEach(([key, value]) => {
|
||||
// let _key = key, _value = value
|
||||
// if (['color', 'thicknessColor'].includes(key)) {
|
||||
// if (key === 'color') _key = 'diffuse'
|
||||
// _value = new Color(value)
|
||||
// }
|
||||
// if (!['transparent', 'vertexColors'].includes(key)) {
|
||||
// uniforms[_key].value = _value
|
||||
// }
|
||||
// })
|
||||
|
||||
// this.material = new TShaderMaterial({
|
||||
// ...params,
|
||||
// uniforms,
|
||||
// lights: true,
|
||||
// transparent: this.transparent,
|
||||
// vertexColors: this.vertexColors,
|
||||
// })
|
||||
// },
|
||||
// },
|
||||
// render() {
|
||||
// return []
|
||||
// },
|
||||
// __hmrId: 'SubSurfaceMaterial',
|
||||
// })
|
@ -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,9 +69,9 @@ 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
|
||||
`
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user