mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
add effects
This commit is contained in:
parent
b800071f93
commit
cfdbdd76c1
53
src/effects/TiltShiftPass.js
Normal file
53
src/effects/TiltShiftPass.js
Normal 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',
|
||||||
|
};
|
26
src/effects/ZoomBlurPass.js
Normal file
26
src/effects/ZoomBlurPass.js
Normal 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',
|
||||||
|
};
|
@ -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';
|
||||||
|
@ -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
60
src/shaders/TiltShift.js
Normal 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
51
src/shaders/ZoomBlur.js
Normal 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
16
src/shaders/default.js
Normal 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);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
10
src/use/useBindPropValue.js
Normal file
10
src/use/useBindPropValue.js
Normal 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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user