-
-
Notifications
You must be signed in to change notification settings - Fork 212
/
TextureEffect.ts
141 lines (90 loc) · 2.74 KB
/
TextureEffect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import { Texture, Uniform, UnsignedByteType } from "three";
import { ColorChannel } from "../enums/ColorChannel.js";
import { Effect } from "./Effect.js";
import fragmentShader from "./shaders/texture.frag";
import vertexShader from "./shaders/texture.vert";
/**
* TextureEffect options.
*
* @category Effects
*/
export interface TextureEffectOptions {
/**
* A texture.
*/
texture?: Texture | null;
}
/**
* A texture effect.
*
* @category Effects
*/
export class TextureEffect extends Effect {
/**
* Constructs a new texture effect.
*
* @param options - The options.
*/
constructor({ texture = null }: TextureEffectOptions = {}) {
super("TextureEffect");
this.fragmentShader = fragmentShader;
const defines = this.input.defines;
defines.set("TEXEL", "texel");
const uniforms = this.input.uniforms;
uniforms.set("map", new Uniform(null));
uniforms.set("uvTransform", new Uniform(null));
this.texture = texture;
}
/**
* The current texture.
*/
get texture(): Texture | null {
return this.input.uniforms.get("map")!.value as Texture;
}
set texture(value: Texture | null) {
const prevTexture = this.texture;
const uniforms = this.input.uniforms;
const defines = this.input.defines;
if(prevTexture !== value) {
uniforms.get("map")!.value = value;
defines.delete("TEXTURE_PRECISION_HIGH");
if(value !== null) {
if(value.matrixAutoUpdate) {
defines.set("UV_TRANSFORM", true);
uniforms.get("uvTransform")!.value = value.matrix;
this.vertexShader = vertexShader;
} else {
defines.delete("UV_TRANSFORM");
uniforms.get("uvTransform")!.value = null;
this.vertexShader = null;
}
if(value.type !== UnsignedByteType) {
defines.set("TEXTURE_PRECISION_HIGH", true);
}
}
this.setChanged();
}
}
/**
* Sets the swizzles that will be applied to the components of a texel before it is written to the output color.
*
* @param r - The swizzle for the `r` component.
* @param g - The swizzle for the `g` component. Defaults to the same value used for `r`.
* @param b - The swizzle for the `b` component. Defaults to the same value used for `r`.
* @param a - The swizzle for the `a` component. Defaults to the same value used for `r`.
*/
setTextureSwizzleRGBA(r: ColorChannel, g = r, b = r, a = r) {
const rgba = "rgba";
let swizzle = "";
if(r !== ColorChannel.RED || g !== ColorChannel.GREEN || b !== ColorChannel.BLUE || a !== ColorChannel.ALPHA) {
swizzle = [".", rgba[r], rgba[g], rgba[b], rgba[a]].join("");
}
this.input.defines.set("TEXEL", "texel" + swizzle);
this.setChanged();
}
override render(): void {
if(this.texture !== null && this.texture.matrixAutoUpdate) {
this.texture.updateMatrix();
}
}
}