Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ef8e946

Browse files
ctranctran
ctran
authored and
ctran
committed
postprocessing works
1 parent fb8c2ff commit ef8e946

34 files changed

+310
-224
lines changed

apps/kitchen-sink-new/src/app/app.routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ export const appRoutes: Route[] = [
1010
loadComponent: () => import('./cannon/cannon'),
1111
loadChildren: () => import('./cannon/cannon.routes'),
1212
},
13+
{
14+
path: 'postprocessing',
15+
loadComponent: () => import('./postprocessing/postprocessing'),
16+
loadChildren: () => import('./postprocessing/postprocessing.routes'),
17+
},
1318
{
1419
path: '',
1520
// redirectTo: 'cannon',
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { NgtCanvas } from 'angular-three-core-new';
3+
import { Experience } from './experience';
4+
5+
@Component({
6+
standalone: true,
7+
template: `
8+
<ngt-canvas [sceneGraph]="scene" [options]="{ camera: { position: [0, 0, 10] } }" />
9+
`,
10+
changeDetection: ChangeDetectionStrategy.OnPush,
11+
imports: [NgtCanvas],
12+
host: { class: 'basic-postprocessing' },
13+
})
14+
export default class Basic {
15+
scene = Experience;
16+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {
2+
CUSTOM_ELEMENTS_SCHEMA,
3+
ChangeDetectionStrategy,
4+
Component,
5+
ElementRef,
6+
input,
7+
viewChild,
8+
} from '@angular/core';
9+
import { NgtArgs, extend, injectBeforeRender } from 'angular-three-core-new';
10+
import { NgtpEffectComposer, NgtpGodRays } from 'angular-three-postprocessing';
11+
import * as THREE from 'three';
12+
import { Group, Mesh } from 'three';
13+
14+
extend(THREE);
15+
16+
// NOTE: this is to be used with GodRaysEffect as the effect needs a sun source
17+
@Component({
18+
selector: 'app-sun',
19+
standalone: true,
20+
template: `
21+
<ngt-mesh #sun [position]="position()">
22+
<ngt-sphere-geometry *args="[4, 36, 36]" />
23+
<ngt-mesh-basic-material [color]="color()" />
24+
</ngt-mesh>
25+
`,
26+
imports: [NgtArgs],
27+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
28+
changeDetection: ChangeDetectionStrategy.OnPush,
29+
})
30+
export class Sun {
31+
color = input('#00FF00');
32+
position = input([0, 0, -15]);
33+
sunRef = viewChild.required<ElementRef<Mesh>>('sun');
34+
}
35+
36+
@Component({
37+
standalone: true,
38+
template: `
39+
<ngt-color *args="['#171717']" attach="background" />
40+
41+
<app-sun #sun color="yellow" />
42+
43+
<ngt-group #group>
44+
<ngt-mesh>
45+
<ngt-torus-knot-geometry />
46+
<ngt-mesh-basic-material color="pink" />
47+
</ngt-mesh>
48+
49+
<ngt-mesh [position]="[2, 2, 2]">
50+
<ngt-sphere-geometry />
51+
<ngt-mesh-basic-material color="aquamarine" />
52+
</ngt-mesh>
53+
54+
<ngt-mesh [position]="[-2, -2, -2]">
55+
<ngt-box-geometry />
56+
<ngt-mesh-basic-material color="goldenrod" />
57+
</ngt-mesh>
58+
</ngt-group>
59+
60+
<ngtp-effect-composer>
61+
@if (sun.sunRef().nativeElement; as sun) {
62+
<ngtp-god-rays [options]="{ sun }" />
63+
}
64+
</ngtp-effect-composer>
65+
`,
66+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
67+
imports: [NgtpEffectComposer, NgtArgs, NgtpGodRays, Sun],
68+
changeDetection: ChangeDetectionStrategy.OnPush,
69+
host: { class: 'experience-basic-postprocessing' },
70+
})
71+
export class Experience {
72+
group = viewChild.required<ElementRef<Group>>('group');
73+
74+
constructor() {
75+
injectBeforeRender(() => {
76+
const { nativeElement } = this.group();
77+
nativeElement.rotation.x += 0.005;
78+
nativeElement.rotation.y += 0.005;
79+
});
80+
}
81+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Routes } from '@angular/router';
2+
3+
const routes: Routes = [
4+
{
5+
path: 'basic',
6+
loadComponent: () => import('./basic/basic'),
7+
},
8+
{
9+
path: '',
10+
redirectTo: 'basic',
11+
pathMatch: 'full',
12+
},
13+
];
14+
15+
export default routes;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ChangeDetectionStrategy, Component } from '@angular/core';
2+
import { RouterOutlet } from '@angular/router';
3+
import { UiNavigations } from '../shared/ui-navigations';
4+
5+
@Component({
6+
standalone: true,
7+
template: `
8+
<app-ui-navigations [examples]="examples" root="postprocessing">
9+
<router-outlet />
10+
</app-ui-navigations>
11+
`,
12+
imports: [RouterOutlet, UiNavigations],
13+
changeDetection: ChangeDetectionStrategy.OnPush,
14+
host: { class: 'postprocessing' },
15+
})
16+
export default class Postprocessing {
17+
examples = ['basic'];
18+
}

libs/core-new/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
export * from './lib/args';
22
export * from './lib/canvas';
33
export { NgtThreeEvent } from './lib/events';
4+
export { getLocalState } from './lib/instance';
45
export * from './lib/portal';
56
export * from './lib/renderer';
7+
export { injectStore } from './lib/store';
68
export * from './lib/utils/before-render';
79
export * from './lib/utils/is';
810
export * from './lib/utils/make';
911
export * from './lib/utils/resolve-ref';
1012
export * from './lib/utils/signal-store';
13+
export * from './lib/utils/signals';
1114
export * from './lib/utils/token';
1215

13-
export { injectStore } from './lib/store';
1416
export type * from './lib/three-types';

libs/postprocessing/src/lib/effect-composer.ts

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@ import {
22
CUSTOM_ELEMENTS_SCHEMA,
33
ChangeDetectionStrategy,
44
Component,
5-
Directive,
65
ElementRef,
76
Injector,
8-
TemplateRef,
9-
ViewContainerRef,
107
afterNextRender,
118
computed,
12-
contentChild,
9+
effect,
1310
inject,
1411
input,
15-
untracked,
1612
viewChild,
1713
} from '@angular/core';
18-
import { createApiToken, extend, getLocalState, injectBeforeRender, injectNgtStore, pick } from 'angular-three';
14+
import {
15+
createApiToken,
16+
extend,
17+
getLocalState,
18+
injectBeforeRender,
19+
injectStore,
20+
pick,
21+
signalStore,
22+
} from 'angular-three-core-new';
1923
import { injectAutoEffect } from 'ngxtension/auto-effect';
2024
import { mergeInputs } from 'ngxtension/inject-inputs';
2125
import {
@@ -42,7 +46,19 @@ export interface NgtpEffectComposerApi {
4246
resolutionScale?: number;
4347
}
4448

45-
export const [injectEffectComposerApi, provideEffectComposerApi] = createApiToken(() => NgtpEffectComposer);
49+
export const [injectEffectComposerApi, provideEffectComposerApi] = createApiToken(
50+
'NGTP_EFFECT_COMPOSER_API',
51+
() => NgtpEffectComposer,
52+
(composer) => {
53+
const store = signalStore<NgtpEffectComposerApi>({});
54+
55+
effect(() => {
56+
store.update(composer.api());
57+
});
58+
59+
return store;
60+
},
61+
);
4662

4763
interface NgtpEffectComposerOptions {
4864
enabled: boolean;
@@ -71,14 +87,13 @@ function isConvolution(effect: Effect) {
7187
return (effect.getAttributes() & EffectAttribute.CONVOLUTION) === EffectAttribute.CONVOLUTION;
7288
}
7389

74-
@Directive({ selector: 'ng-template[effects]', standalone: true })
75-
export class NgtpEffects {}
76-
7790
@Component({
7891
selector: 'ngtp-effect-composer',
7992
standalone: true,
8093
template: `
81-
<ngt-group #group ngtCompound />
94+
<ngt-group #group>
95+
<ng-content />
96+
</ngt-group>
8297
`,
8398
providers: [provideEffectComposerApi()],
8499
schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -87,28 +102,26 @@ export class NgtpEffects {}
87102
export class NgtpEffectComposer {
88103
options = input(defaultOptions, { transform: mergeInputs(defaultOptions) });
89104

90-
injector = inject(Injector);
91-
autoEffect = injectAutoEffect();
92-
store = injectNgtStore();
93-
size = this.store.select('size');
94-
gl = this.store.select('gl');
95-
defaultScene = this.store.select('scene');
96-
defaultCamera = this.store.select('camera');
97-
98-
depthBuffer = pick(this.options, 'depthBuffer');
99-
stencilBuffer = pick(this.options, 'stencilBuffer');
100-
multisampling = pick(this.options, 'multisampling');
101-
frameBufferType = pick(this.options, 'frameBufferType');
102-
scene = computed(() => this.options().scene ?? this.defaultScene());
103-
camera = computed(() => this.options().camera ?? this.defaultCamera());
104-
enableNormalPass = pick(this.options, 'enableNormalPass');
105-
resolutionScale = pick(this.options, 'resolutionScale');
106-
107105
group = viewChild.required<ElementRef<Group>>('group');
108-
groupAnchor = viewChild.required('group', { read: ViewContainerRef });
109-
content = contentChild.required(NgtpEffects, { read: TemplateRef });
110106

111-
composerData = computed(() => {
107+
private injector = inject(Injector);
108+
private autoEffect = injectAutoEffect();
109+
private store = injectStore();
110+
private size = this.store.select('size');
111+
private gl = this.store.select('gl');
112+
private defaultScene = this.store.select('scene');
113+
private defaultCamera = this.store.select('camera');
114+
115+
private depthBuffer = pick(this.options, 'depthBuffer');
116+
private stencilBuffer = pick(this.options, 'stencilBuffer');
117+
private multisampling = pick(this.options, 'multisampling');
118+
private frameBufferType = pick(this.options, 'frameBufferType');
119+
private scene = computed(() => this.options().scene ?? this.defaultScene());
120+
private camera = computed(() => this.options().camera ?? this.defaultCamera());
121+
private enableNormalPass = pick(this.options, 'enableNormalPass');
122+
private resolutionScale = pick(this.options, 'resolutionScale');
123+
124+
private composerData = computed(() => {
112125
const webGL2Available = isWebGL2Available();
113126
const [
114127
gl,
@@ -174,7 +187,6 @@ export class NgtpEffectComposer {
174187
afterNextRender(() => {
175188
this.disableToneMapping();
176189
this.setComposerSize();
177-
this.render();
178190
this.updatePasses();
179191

180192
injectBeforeRender(
@@ -219,19 +231,6 @@ export class NgtpEffectComposer {
219231
});
220232
}
221233

222-
private render() {
223-
this.autoEffect(
224-
(injector) => {
225-
return untracked(() => {
226-
const ref = this.groupAnchor().createEmbeddedView(this.content(), {}, { injector });
227-
ref.detectChanges();
228-
return () => ref.destroy();
229-
});
230-
},
231-
{ allowSignalWrites: true },
232-
);
233-
}
234-
235234
private updatePasses() {
236235
this.autoEffect(() => {
237236
const [group, { composer, normalPass, downSamplingPass }, camera] = [

libs/postprocessing/src/lib/effect.ts

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, Directive, inject, input } from '@angular/core';
2-
import { injectNgtRef, injectNgtStore } from 'angular-three';
3-
import { injectAutoEffect } from 'ngxtension/auto-effect';
4-
import { createNoopInjectionToken } from 'ngxtension/create-injection-token';
5-
import { BlendFunction, Effect } from 'postprocessing';
1+
import {
2+
CUSTOM_ELEMENTS_SCHEMA,
3+
ChangeDetectionStrategy,
4+
Component,
5+
Directive,
6+
InjectionToken,
7+
inject,
8+
input,
9+
} from '@angular/core';
10+
import { injectStore } from 'angular-three-core-new';
11+
import { BlendFunction } from 'postprocessing';
612

7-
export const [injectDefaultEffectOptions, provideDefaultEffectOptions] = createNoopInjectionToken<{
8-
blendFunction?: BlendFunction;
9-
opacity?: number;
10-
}>('Default Effect options');
13+
export const NGTP_DEFAULT_EFFECT_OPTIONS = new InjectionToken<{ blendFunction?: BlendFunction; opacity?: number }>(
14+
'NGTP_DEFAULT_EFFECT_OPTIONS',
15+
);
16+
export function provideDefaultEffectOptions(options: { blendFunction?: BlendFunction; opacity?: number }) {
17+
return { provide: NGTP_DEFAULT_EFFECT_OPTIONS, useFactory: () => options };
18+
}
1119

1220
@Component({
1321
selector: 'ngtp-effect-blend-mode',
@@ -27,44 +35,14 @@ export class NgtpEffectBlendMode {
2735

2836
@Directive({ standalone: true })
2937
export class NgtpEffect {
30-
defaultEffectOptions = injectDefaultEffectOptions({ optional: true });
38+
defaultEffectOptions = inject(NGTP_DEFAULT_EFFECT_OPTIONS, { optional: true });
3139

32-
effectRef = input(injectNgtRef<Effect>());
3340
blendFunction = input(this.defaultEffectOptions?.blendFunction);
3441
opacity = input(this.defaultEffectOptions?.opacity);
3542

36-
autoEffect = injectAutoEffect();
37-
store = injectNgtStore();
43+
store = injectStore();
3844
camera = this.store.select('camera');
3945
invalidate = this.store.select('invalidate');
40-
41-
// constructor() {
42-
// afterNextRender(() => {
43-
// this.setBlendMode();
44-
// });
45-
// }
46-
//
47-
// private setBlendMode() {
48-
// this.autoEffect(() => {
49-
// const [effect, blendFunction, opacity, invalidate] = [
50-
// this.effectRef().nativeElement,
51-
// this.blendFunction(),
52-
// this.opacity(),
53-
// this.invalidate(),
54-
// ];
55-
// if (!effect) return;
56-
//
57-
// if (blendFunction !== undefined) {
58-
// effect.blendMode.blendFunction = blendFunction;
59-
// }
60-
//
61-
// if (opacity !== undefined) {
62-
// effect.blendMode.opacity.value = opacity;
63-
// }
64-
//
65-
// invalidate();
66-
// });
67-
// }
6846
}
6947

70-
export const NgtpEffectHostDirective = { directive: NgtpEffect, inputs: ['blendFunction', 'opacity', 'effectRef'] };
48+
export const NgtpEffectHostDirective = { directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] };

0 commit comments

Comments
 (0)