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

add effects

This commit is contained in:
Kevin Levron 2020-10-06 20:57:00 +02:00
parent b800071f93
commit cfdbdd76c1
8 changed files with 220 additions and 0 deletions

View File

@ -0,0 +1,53 @@
import { Vector2 } from 'three';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { watch } from 'vue';
import EffectPass from './EffectPass.js';
import TiltShift from '../shaders/TiltShift.js';
import useBindPropValue from '../use/useBindPropValue.js';
export default {
extends: EffectPass,
props: {
blurRadius: { type: Number, default: 10 },
gradientRadius: { type: Number, default: 100 },
start: { type: Object, default: { x: 0, y: 100 } },
end: { type: Object, default: { x: 10, y: 100 } },
},
mounted() {
this.pass = new ShaderPass(TiltShift);
this.passes.push(this.pass);
this.pass1 = new ShaderPass(TiltShift);
this.passes.push(this.pass1);
const uniforms = this.uniforms = this.pass.uniforms;
const uniforms1 = this.uniforms1 = this.pass1.uniforms;
uniforms1.blurRadius = uniforms.blurRadius;
uniforms1.gradientRadius = uniforms.gradientRadius;
uniforms1.start = uniforms.start;
uniforms1.end = uniforms.end;
uniforms1.texSize = uniforms.texSize;
useBindPropValue(this, 'blurRadius', uniforms.blurRadius);
useBindPropValue(this, 'gradientRadius', uniforms.gradientRadius);
this.updateFocusLine();
['start', 'end'].forEach(p => {
watch(() => this[p], this.updateFocusLine);
});
this.pass.setSize = (width, height) => {
uniforms.texSize.value.set(width, height);
};
},
methods: {
updateFocusLine() {
this.uniforms.start.value.copy(this.start);
this.uniforms.end.value.copy(this.end);
const dv = new Vector2().copy(this.end).sub(this.start).normalize();
this.uniforms.delta.value.copy(dv);
this.uniforms1.delta.value.set(-dv.y, dv.x);
},
},
__hmrId: 'TiltShiftPass',
};

View File

@ -0,0 +1,26 @@
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import EffectPass from './EffectPass.js';
import ZoomBlur from '../shaders/ZoomBlur.js';
import useBindProp from '../use/useBindProp.js';
import useBindPropValue from '../use/useBindPropValue.js';
export default {
extends: EffectPass,
props: {
center: { type: Object, default: { x: 0, y: 0 } },
strength: { type: Number, default: 0.5 },
},
mounted() {
this.pass = new ShaderPass(ZoomBlur);
this.passes.push(this.pass);
const uniforms = this.uniforms = this.pass.uniforms;
useBindProp(this, 'center', uniforms.center.value);
useBindPropValue(this, 'strength', uniforms.strength);
this.pass.setSize = (width, height) => {
uniforms.texSize.value.set(width, height);
};
},
__hmrId: 'ZoomBlurPass',
};

View File

@ -7,4 +7,6 @@ export { default as FXAAPass } from './FXAAPass.js';
export { default as HalftonePass } from './HalftonePass.js'; export { default as HalftonePass } from './HalftonePass.js';
export { default as SAOPass } from './SAOPass.js'; export { default as SAOPass } from './SAOPass.js';
export { default as SMAAPass } from './SMAAPass.js'; export { default as SMAAPass } from './SMAAPass.js';
export { default as TiltShiftPass } from './TiltShiftPass.js';
export { default as UnrealBloomPass } from './UnrealBloomPass.js'; export { default as UnrealBloomPass } from './UnrealBloomPass.js';
export { default as ZoomBlurPass } from './ZoomBlurPass.js';

View File

@ -76,7 +76,9 @@ export const TroisJSVuePlugin = {
'RenderPass', 'RenderPass',
'SAOPass', 'SAOPass',
'SMAAPass', 'SMAAPass',
'TiltShiftPass',
'UnrealBloomPass', 'UnrealBloomPass',
'ZoomBlurPass',
'GLTFViewer', 'GLTFViewer',
]; ];

60
src/shaders/TiltShift.js Normal file
View File

@ -0,0 +1,60 @@
// From https://github.com/evanw/glfx.js
import { Vector2 } from 'three';
import DefaultShader from './default';
export default {
uniforms: {
tDiffuse: { value: null },
blurRadius: { value: 0 },
gradientRadius: { value: 0 },
start: { value: new Vector2() },
end: { value: new Vector2() },
delta: { value: new Vector2() },
texSize: { value: new Vector2() },
},
vertexShader: DefaultShader.vertexShader,
fragmentShader: `
uniform sampler2D tDiffuse;
uniform float blurRadius;
uniform float gradientRadius;
uniform vec2 start;
uniform vec2 end;
uniform vec2 delta;
uniform vec2 texSize;
varying vec2 vUv;
float random(vec3 scale, float seed) {
/* use the fragment position for a different seed per-pixel */
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
vec4 color = vec4(0.0);
float total = 0.0;
/* randomize the lookup values to hide the fixed number of samples */
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
vec2 normal = normalize(vec2(start.y - end.y, end.x - start.x));
float radius = smoothstep(0.0, 1.0, abs(dot(vUv * texSize - start, normal)) / gradientRadius) * blurRadius;
for (float t = -30.0; t <= 30.0; t++) {
float percent = (t + offset - 0.5) / 30.0;
float weight = 1.0 - abs(percent);
vec4 texel = texture2D(tDiffuse, vUv + delta / texSize * percent * radius);
// vec4 texel2 = texture2D(tDiffuse, vUv + vec2(-delta.y, delta.x) / texSize * percent * radius);
/* switch to pre-multiplied alpha to correctly blur transparent images */
texel.rgb *= texel.a;
// texel2.rgb *= texel2.a;
color += texel * weight;
total += 2.0 * weight;
}
gl_FragColor = color / total;
/* switch back from pre-multiplied alpha */
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}
`,
};

51
src/shaders/ZoomBlur.js Normal file
View File

@ -0,0 +1,51 @@
// From https://github.com/evanw/glfx.js
import { Vector2 } from 'three';
import DefaultShader from './default';
export default {
uniforms: {
tDiffuse: { value: null },
center: { value: new Vector2() },
strength: { value: 0 },
texSize: { value: new Vector2() },
},
vertexShader: DefaultShader.vertexShader,
fragmentShader: `
uniform sampler2D tDiffuse;
uniform vec2 center;
uniform float strength;
uniform vec2 texSize;
varying vec2 vUv;
float random(vec3 scale, float seed) {
/* use the fragment position for a different seed per-pixel */
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
vec4 color = vec4(0.0);
float total = 0.0;
vec2 toCenter = center - vUv * texSize;
/* randomize the lookup values to hide the fixed number of samples */
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
for (float t = 0.0; t <= 40.0; t++) {
float percent = (t + offset) / 40.0;
float weight = 4.0 * (percent - percent * percent);
vec4 texel = texture2D(tDiffuse, vUv + toCenter * percent * strength / texSize);
/* switch to pre-multiplied alpha to correctly blur transparent images */
texel.rgb *= texel.a;
color += texel * weight;
total += weight;
}
gl_FragColor = color / total;
/* switch back from pre-multiplied alpha */
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}
`,
};

16
src/shaders/default.js Normal file
View File

@ -0,0 +1,16 @@
export default {
uniforms: {},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`,
};

View File

@ -0,0 +1,10 @@
import { watch } from 'vue';
export default function useBindPropValue(src, srcProp, dst, dstProp = 'value') {
if (src[srcProp]) {
dst[dstProp] = src[srcProp];
watch(() => src[srcProp], (value) => {
dst[dstProp] = value;
});
}
};