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
|
mesh?: MeshInterface
|
||||||
material?: Material
|
material?: Material
|
||||||
createMaterial?(): Material
|
createMaterial?(): Material
|
||||||
addWatchers?(m: Material): void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -41,8 +40,7 @@ export default defineComponent({
|
|||||||
if (this.createMaterial) {
|
if (this.createMaterial) {
|
||||||
this.material = this.createMaterial()
|
this.material = this.createMaterial()
|
||||||
this.mesh.setMaterial(this.material)
|
this.mesh.setMaterial(this.material)
|
||||||
this._addWatchers()
|
this.addWatchers()
|
||||||
this.addWatchers?.(this.material)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
@ -58,7 +56,7 @@ export default defineComponent({
|
|||||||
setTexture(texture: Texture, key = 'map') {
|
setTexture(texture: Texture, key = 'map') {
|
||||||
this.setProp(key, texture, true)
|
this.setProp(key, texture, true)
|
||||||
},
|
},
|
||||||
_addWatchers() {
|
addWatchers() {
|
||||||
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
|
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
|
||||||
watch(() => this[p], (value) => {
|
watch(() => this[p], (value) => {
|
||||||
if (p === 'color') {
|
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}
|
${meshphongFragHead}
|
||||||
|
|
||||||
uniform float thicknessPower
|
uniform float thicknessPower;
|
||||||
uniform float thicknessScale
|
uniform float thicknessScale;
|
||||||
uniform float thicknessDistortion
|
uniform float thicknessDistortion;
|
||||||
uniform float thicknessAmbient
|
uniform float thicknessAmbient;
|
||||||
uniform float thicknessAttenuation
|
uniform float thicknessAttenuation;
|
||||||
uniform vec3 thicknessColor
|
uniform vec3 thicknessColor;
|
||||||
|
|
||||||
void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {
|
void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {
|
||||||
#ifdef USE_COLOR
|
#ifdef USE_COLOR
|
||||||
vec3 thickness = vColor * thicknessColor
|
vec3 thickness = vColor * thicknessColor;
|
||||||
#else
|
#else
|
||||||
vec3 thickness = thicknessColor
|
vec3 thickness = thicknessColor;
|
||||||
#endif
|
#endif
|
||||||
vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion))
|
vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));
|
||||||
float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale
|
float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;
|
||||||
vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness
|
vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;
|
||||||
reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color
|
reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;
|
||||||
}
|
}
|
||||||
` + meshphongFragBody.replace(
|
` + meshphongFragBody.replace(
|
||||||
'#include <lights_fragment_begin>',
|
'#include <lights_fragment_begin>',
|
||||||
@ -69,9 +69,9 @@ const SubsurfaceScatteringShader = {
|
|||||||
ShaderChunk.lights_fragment_begin,
|
ShaderChunk.lights_fragment_begin,
|
||||||
'RE_Direct( directLight, geometry, material, reflectedLight );',
|
'RE_Direct( directLight, geometry, material, reflectedLight );',
|
||||||
`
|
`
|
||||||
RE_Direct( directLight, geometry, material, reflectedLight )
|
RE_Direct( directLight, geometry, material, reflectedLight );
|
||||||
#if defined( SUBSURFACE ) && defined( USE_UV )
|
#if defined( SUBSURFACE ) && defined( USE_UV )
|
||||||
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight)
|
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);
|
||||||
#endif
|
#endif
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user