1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00

wip: materials

This commit is contained in:
Kevin Levron 2021-04-19 00:40:22 +02:00
parent 457d871269
commit b3f21b3ec6
6 changed files with 162 additions and 126 deletions

View File

@ -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') {

View File

@ -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',
});

View 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',
})

View File

@ -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',
});

View 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',
// })

View File

@ -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
`
)