@webeach/gl-circular-progress 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +118 -0
- package/README.ru.md +120 -0
- package/docs/en/CircularProgressFire.md +105 -0
- package/docs/en/CircularProgressLiquid.md +106 -0
- package/lib/cjs/classes/BaseCircularProgress/BaseCircularProgress.js +151 -0
- package/lib/cjs/classes/BaseCircularProgress/BaseCircularProgress.js.map +1 -0
- package/lib/cjs/classes/BaseCircularProgress/constants.js +27 -0
- package/lib/cjs/classes/BaseCircularProgress/constants.js.map +1 -0
- package/lib/cjs/classes/BaseCircularProgress/index.js +8 -0
- package/lib/cjs/classes/BaseCircularProgress/index.js.map +1 -0
- package/lib/cjs/classes/CircularProgressFire/CircularProgressFire.js +299 -0
- package/lib/cjs/classes/CircularProgressFire/CircularProgressFire.js.map +1 -0
- package/lib/cjs/classes/CircularProgressFire/index.js +8 -0
- package/lib/cjs/classes/CircularProgressFire/index.js.map +1 -0
- package/lib/cjs/classes/CircularProgressFire/shaders/fragment.frag.js +6 -0
- package/lib/cjs/classes/CircularProgressFire/shaders/fragment.frag.js.map +1 -0
- package/lib/cjs/classes/CircularProgressFire/shaders/vertex.vert.js +6 -0
- package/lib/cjs/classes/CircularProgressFire/shaders/vertex.vert.js.map +1 -0
- package/lib/cjs/classes/CircularProgressLiquid/CircularProgressLiquid.js +306 -0
- package/lib/cjs/classes/CircularProgressLiquid/CircularProgressLiquid.js.map +1 -0
- package/lib/cjs/classes/CircularProgressLiquid/index.js +8 -0
- package/lib/cjs/classes/CircularProgressLiquid/index.js.map +1 -0
- package/lib/cjs/classes/CircularProgressLiquid/shaders/fragment.frag.js +6 -0
- package/lib/cjs/classes/CircularProgressLiquid/shaders/fragment.frag.js.map +1 -0
- package/lib/cjs/classes/CircularProgressLiquid/shaders/vertex.vert.js +6 -0
- package/lib/cjs/classes/CircularProgressLiquid/shaders/vertex.vert.js.map +1 -0
- package/lib/cjs/index.js +10 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/utils/hexToCss/hexToCss.js +22 -0
- package/lib/cjs/utils/hexToCss/hexToCss.js.map +1 -0
- package/lib/esm/classes/BaseCircularProgress/BaseCircularProgress.js +149 -0
- package/lib/esm/classes/BaseCircularProgress/BaseCircularProgress.js.map +1 -0
- package/lib/esm/classes/BaseCircularProgress/constants.js +22 -0
- package/lib/esm/classes/BaseCircularProgress/constants.js.map +1 -0
- package/lib/esm/classes/BaseCircularProgress/index.js +2 -0
- package/lib/esm/classes/BaseCircularProgress/index.js.map +1 -0
- package/lib/esm/classes/CircularProgressFire/CircularProgressFire.js +297 -0
- package/lib/esm/classes/CircularProgressFire/CircularProgressFire.js.map +1 -0
- package/lib/esm/classes/CircularProgressFire/index.js +2 -0
- package/lib/esm/classes/CircularProgressFire/index.js.map +1 -0
- package/lib/esm/classes/CircularProgressFire/shaders/fragment.frag.js +4 -0
- package/lib/esm/classes/CircularProgressFire/shaders/fragment.frag.js.map +1 -0
- package/lib/esm/classes/CircularProgressFire/shaders/vertex.vert.js +4 -0
- package/lib/esm/classes/CircularProgressFire/shaders/vertex.vert.js.map +1 -0
- package/lib/esm/classes/CircularProgressLiquid/CircularProgressLiquid.js +304 -0
- package/lib/esm/classes/CircularProgressLiquid/CircularProgressLiquid.js.map +1 -0
- package/lib/esm/classes/CircularProgressLiquid/index.js +2 -0
- package/lib/esm/classes/CircularProgressLiquid/index.js.map +1 -0
- package/lib/esm/classes/CircularProgressLiquid/shaders/fragment.frag.js +4 -0
- package/lib/esm/classes/CircularProgressLiquid/shaders/fragment.frag.js.map +1 -0
- package/lib/esm/classes/CircularProgressLiquid/shaders/vertex.vert.js +4 -0
- package/lib/esm/classes/CircularProgressLiquid/shaders/vertex.vert.js.map +1 -0
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/utils/hexToCss/hexToCss.js +20 -0
- package/lib/esm/utils/hexToCss/hexToCss.js.map +1 -0
- package/lib/types/classes/BaseCircularProgress/BaseCircularProgress.d.ts +113 -0
- package/lib/types/classes/BaseCircularProgress/BaseCircularProgress.d.ts.map +1 -0
- package/lib/types/classes/BaseCircularProgress/constants.d.ts +21 -0
- package/lib/types/classes/BaseCircularProgress/constants.d.ts.map +1 -0
- package/lib/types/classes/BaseCircularProgress/index.d.ts +3 -0
- package/lib/types/classes/BaseCircularProgress/index.d.ts.map +1 -0
- package/lib/types/classes/BaseCircularProgress/types.d.ts +40 -0
- package/lib/types/classes/BaseCircularProgress/types.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressFire/CircularProgressFire.d.ts +98 -0
- package/lib/types/classes/CircularProgressFire/CircularProgressFire.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressFire/index.d.ts +3 -0
- package/lib/types/classes/CircularProgressFire/index.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressFire/types.d.ts +12 -0
- package/lib/types/classes/CircularProgressFire/types.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressLiquid/CircularProgressLiquid.d.ts +99 -0
- package/lib/types/classes/CircularProgressLiquid/CircularProgressLiquid.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressLiquid/index.d.ts +3 -0
- package/lib/types/classes/CircularProgressLiquid/index.d.ts.map +1 -0
- package/lib/types/classes/CircularProgressLiquid/types.d.ts +13 -0
- package/lib/types/classes/CircularProgressLiquid/types.d.ts.map +1 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/types/core.d.ts +4 -0
- package/lib/types/types/core.d.ts.map +1 -0
- package/lib/types/utils/hexToCss/hexToCss.d.ts +16 -0
- package/lib/types/utils/hexToCss/hexToCss.d.ts.map +1 -0
- package/lib/types/utils/hexToCss/index.d.ts +2 -0
- package/lib/types/utils/hexToCss/index.d.ts.map +1 -0
- package/package.json +121 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var hexToCss = require('../../utils/hexToCss/hexToCss.js');
|
|
4
|
+
var BaseCircularProgress = require('../BaseCircularProgress/BaseCircularProgress.js');
|
|
5
|
+
var fragment = require('./shaders/fragment.frag.js');
|
|
6
|
+
var vertex = require('./shaders/vertex.vert.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A circular progress indicator with a fire effect.
|
|
10
|
+
* Uses WebGL 2.0 for rendering.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const instance = new CircularProgressFire(canvas, {
|
|
14
|
+
* colors: [0xff5a00, 0xff9a00],
|
|
15
|
+
* intensity: 1.0,
|
|
16
|
+
* progress: 0.5,
|
|
17
|
+
* speed: 1.5,
|
|
18
|
+
* thickness: 20,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* @see https://webeach.github.io/gl-circular-progress/CircularProgressFire.html - Live Demo
|
|
22
|
+
* @see https://github.com/webeach/gl-circular-progress/blob/main/docs/en/CircularProgressFire.md - Documentation
|
|
23
|
+
*/
|
|
24
|
+
class CircularProgressFire extends BaseCircularProgress.BaseCircularProgress {
|
|
25
|
+
extraState;
|
|
26
|
+
animationFrameId = null;
|
|
27
|
+
gl = null;
|
|
28
|
+
gradientTexture = null;
|
|
29
|
+
lastFrameTime = 0;
|
|
30
|
+
locations = null;
|
|
31
|
+
program = null;
|
|
32
|
+
targetProgress = 0.0;
|
|
33
|
+
time = 0.0;
|
|
34
|
+
visualProgress = 0.0;
|
|
35
|
+
/**
|
|
36
|
+
* Creates an instance of CircularProgressFire.
|
|
37
|
+
*
|
|
38
|
+
* @param canvas - The HTMLCanvasElement to render on.
|
|
39
|
+
* @param options - Configuration options.
|
|
40
|
+
*/
|
|
41
|
+
constructor(canvas, options) {
|
|
42
|
+
super(canvas, options);
|
|
43
|
+
this.extraState = {
|
|
44
|
+
intensity: options.intensity ?? 1.0,
|
|
45
|
+
};
|
|
46
|
+
this.targetProgress = this.state.progress;
|
|
47
|
+
this.visualProgress = this.state.progress;
|
|
48
|
+
this.animate = this.animate.bind(this);
|
|
49
|
+
this.initWebGL();
|
|
50
|
+
this.createGradientTexture();
|
|
51
|
+
this.resize();
|
|
52
|
+
this.startAnimation();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Cleans up WebGL resources and stops animation.
|
|
56
|
+
*/
|
|
57
|
+
destroy() {
|
|
58
|
+
super.destroy();
|
|
59
|
+
if (this.animationFrameId !== null) {
|
|
60
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
61
|
+
}
|
|
62
|
+
if (this.gl) {
|
|
63
|
+
if (this.program) {
|
|
64
|
+
this.gl.deleteProgram(this.program);
|
|
65
|
+
}
|
|
66
|
+
if (this.gradientTexture) {
|
|
67
|
+
this.gl.deleteTexture(this.gradientTexture);
|
|
68
|
+
}
|
|
69
|
+
// Note: We don't lose the context, but we clean up our resources
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Gets the current intensity.
|
|
74
|
+
*/
|
|
75
|
+
get intensity() {
|
|
76
|
+
return this.extraState.intensity;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sets the intensity and updates rendering.
|
|
80
|
+
*/
|
|
81
|
+
set intensity(value) {
|
|
82
|
+
this.extraState.intensity = Math.max(0, value);
|
|
83
|
+
this.updateIntensity();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Handles resizing of the canvas and updates WebGL viewport.
|
|
87
|
+
*/
|
|
88
|
+
resize() {
|
|
89
|
+
if (!this.gl || !this.locations) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.gl.viewport(0, 0, this.canvasWidth, this.canvasHeight);
|
|
93
|
+
this.gl.uniform2f(this.locations.uResolution, this.canvasWidth, this.canvasHeight);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Updates WebGL uniforms when colors change.
|
|
97
|
+
*/
|
|
98
|
+
updateColors() {
|
|
99
|
+
this.createGradientTexture();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates the gradient texture from the colors option.
|
|
103
|
+
*/
|
|
104
|
+
createGradientTexture() {
|
|
105
|
+
if (!this.gl) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (this.gradientTexture) {
|
|
109
|
+
this.gl.deleteTexture(this.gradientTexture);
|
|
110
|
+
}
|
|
111
|
+
this.gradientTexture = this.gl.createTexture();
|
|
112
|
+
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
113
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.gradientTexture);
|
|
114
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
115
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
116
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
117
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
118
|
+
// Create gradient on a temporary 2D canvas
|
|
119
|
+
const gradientCanvas = document.createElement('canvas');
|
|
120
|
+
gradientCanvas.width = 256;
|
|
121
|
+
gradientCanvas.height = 1;
|
|
122
|
+
const ctx = gradientCanvas.getContext('2d');
|
|
123
|
+
if (ctx) {
|
|
124
|
+
const grad = ctx.createLinearGradient(0, 0, 256, 0);
|
|
125
|
+
const { colors } = this.state;
|
|
126
|
+
if (colors.length === 1) {
|
|
127
|
+
const color = hexToCss.hexToCss(colors[0]);
|
|
128
|
+
grad.addColorStop(0, color);
|
|
129
|
+
grad.addColorStop(1, color);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
colors.forEach((hex, index) => {
|
|
133
|
+
const stop = index / (colors.length - 1);
|
|
134
|
+
grad.addColorStop(stop, hexToCss.hexToCss(hex));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
ctx.fillStyle = grad;
|
|
138
|
+
ctx.fillRect(0, 0, 256, 1);
|
|
139
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, gradientCanvas);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
updateIntensity() {
|
|
143
|
+
if (!this.gl || !this.locations) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.gl.uniform1f(this.locations.uIntensity, this.extraState.intensity);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Updates the progress value.
|
|
150
|
+
*
|
|
151
|
+
* @param value - The new progress value (0.0 to 1.0).
|
|
152
|
+
*/
|
|
153
|
+
updateProgress(value) {
|
|
154
|
+
this.targetProgress = value;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Updates WebGL uniforms when direction changes.
|
|
158
|
+
*/
|
|
159
|
+
updateReversed() {
|
|
160
|
+
if (!this.gl || !this.locations) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.gl.uniform1f(this.locations.uReversed, this.state.reversed ? 1.0 : 0.0);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Updates WebGL uniforms when speed changes.
|
|
167
|
+
*/
|
|
168
|
+
updateSpeed() {
|
|
169
|
+
// Speed is used in animate loop
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Updates WebGL uniforms when start angle changes.
|
|
173
|
+
*/
|
|
174
|
+
updateStartAngle() {
|
|
175
|
+
if (!this.gl || !this.locations) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const startAngleRad = this.state.startAngle * (Math.PI / 180.0);
|
|
179
|
+
this.gl.uniform1f(this.locations.uStartAngle, startAngleRad);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Updates WebGL uniforms when thickness changes.
|
|
183
|
+
*/
|
|
184
|
+
updateThickness() {
|
|
185
|
+
// Thickness handled in animate loop
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The main animation loop.
|
|
189
|
+
*/
|
|
190
|
+
animate(time) {
|
|
191
|
+
if (this.isDestroyed || !this.gl || !this.locations) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (!this.lastFrameTime) {
|
|
195
|
+
this.lastFrameTime = time;
|
|
196
|
+
}
|
|
197
|
+
const deltaTime = (time - this.lastFrameTime) * 0.001;
|
|
198
|
+
this.lastFrameTime = time;
|
|
199
|
+
// Update State
|
|
200
|
+
this.time += deltaTime * this.state.speed;
|
|
201
|
+
const diff = this.targetProgress - this.visualProgress;
|
|
202
|
+
// Smooth interpolation
|
|
203
|
+
this.visualProgress += diff * 0.1;
|
|
204
|
+
// Render
|
|
205
|
+
this.gl.uniform1f(this.locations.uTime, this.time);
|
|
206
|
+
this.gl.uniform1f(this.locations.uProgress, this.visualProgress);
|
|
207
|
+
// Ensure these are set every frame or when changed
|
|
208
|
+
this.updateReversed();
|
|
209
|
+
this.updateStartAngle();
|
|
210
|
+
this.updateIntensity();
|
|
211
|
+
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
212
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.gradientTexture);
|
|
213
|
+
this.gl.uniform1i(this.locations.uGradientTexture, 0);
|
|
214
|
+
// Radius calculations
|
|
215
|
+
const radiusPx = Math.min(this.canvasWidth, this.canvasHeight) / 2;
|
|
216
|
+
const outerR = 0.95; // Margin for flame tips
|
|
217
|
+
const thicknessRatio = (this.state.thickness * this.dpr) / radiusPx;
|
|
218
|
+
const innerR = outerR - thicknessRatio;
|
|
219
|
+
this.gl.uniform1f(this.locations.uOuterRadius, outerR);
|
|
220
|
+
this.gl.uniform1f(this.locations.uInnerRadius, Math.max(0.0, innerR));
|
|
221
|
+
this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
|
|
222
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Creates and compiles a shader.
|
|
226
|
+
*/
|
|
227
|
+
createShader(type, source) {
|
|
228
|
+
if (!this.gl) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const shader = this.gl.createShader(type);
|
|
232
|
+
if (!shader) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
this.gl.shaderSource(shader, source);
|
|
236
|
+
this.gl.compileShader(shader);
|
|
237
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
238
|
+
console.error(this.gl.getShaderInfoLog(shader));
|
|
239
|
+
this.gl.deleteShader(shader);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
return shader;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Initializes WebGL context and shaders.
|
|
246
|
+
*/
|
|
247
|
+
initWebGL() {
|
|
248
|
+
this.gl = this.canvas.getContext('webgl2', {
|
|
249
|
+
alpha: true,
|
|
250
|
+
antialias: true,
|
|
251
|
+
});
|
|
252
|
+
if (!this.gl) {
|
|
253
|
+
console.error('WebGL 2.0 is not supported');
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertex);
|
|
257
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragment);
|
|
258
|
+
if (!vertexShader || !fragmentShader) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
this.program = this.gl.createProgram();
|
|
262
|
+
if (!this.program) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this.gl.attachShader(this.program, vertexShader);
|
|
266
|
+
this.gl.attachShader(this.program, fragmentShader);
|
|
267
|
+
this.gl.linkProgram(this.program);
|
|
268
|
+
if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
|
|
269
|
+
console.error(this.gl.getProgramInfoLog(this.program));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.gl.useProgram(this.program);
|
|
273
|
+
// Setup Geometry (Full Quad)
|
|
274
|
+
const positionBuffer = this.gl.createBuffer();
|
|
275
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);
|
|
276
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]), this.gl.STATIC_DRAW);
|
|
277
|
+
const posLoc = this.gl.getAttribLocation(this.program, 'a_position');
|
|
278
|
+
this.gl.enableVertexAttribArray(posLoc);
|
|
279
|
+
this.gl.vertexAttribPointer(posLoc, 2, this.gl.FLOAT, false, 0, 0);
|
|
280
|
+
// Get Uniform Locations
|
|
281
|
+
this.locations = {
|
|
282
|
+
uGradientTexture: this.gl.getUniformLocation(this.program, 'u_gradientTexture'),
|
|
283
|
+
uInnerRadius: this.gl.getUniformLocation(this.program, 'u_innerRadius'),
|
|
284
|
+
uIntensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
285
|
+
uOuterRadius: this.gl.getUniformLocation(this.program, 'u_outerRadius'),
|
|
286
|
+
uProgress: this.gl.getUniformLocation(this.program, 'u_progress'),
|
|
287
|
+
uResolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
288
|
+
uReversed: this.gl.getUniformLocation(this.program, 'u_reversed'),
|
|
289
|
+
uStartAngle: this.gl.getUniformLocation(this.program, 'u_startAngle'),
|
|
290
|
+
uTime: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
startAnimation() {
|
|
294
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
exports.CircularProgressFire = CircularProgressFire;
|
|
299
|
+
//# sourceMappingURL=CircularProgressFire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircularProgressFire.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fragmentShaderSource = "#version 300 es\nprecision mediump float;in vec2 v_uv;out vec4 fragColor;uniform float u_time;uniform float u_progress;uniform vec2 u_resolution;uniform float u_innerRadius;uniform float u_outerRadius;uniform float u_startAngle;uniform float u_reversed;uniform sampler2D u_gradientTexture;uniform float u_intensity;\n#define PI 3.14159265359\n#define TWO_PI 6.28318530718\nvec3 permute(vec3 x){return mod(((x*34.0)+1.0)*x,289.0);}float snoise(vec2 v){const vec4 C=vec4(0.211324865405187,0.366025403784439,-0.577350269189626,0.024390243902439);vec2 i=floor(v+dot(v,C.yy));vec2 x0=v-i+dot(i,C.xx);vec2 i1;i1=(x0.x>x0.y)? vec2(1.0,0.0): vec2(0.0,1.0);vec4 x12=x0.xyxy+C.xxzz;x12.xy-=i1;i=mod(i,289.0);vec3 p=permute(permute(i.y+vec3(0.0,i1.y,1.0))+i.x+vec3(0.0,i1.x,1.0));vec3 m=max(0.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy),dot(x12.zw,x12.zw)),0.0);m=m*m;m=m*m;vec3 x=2.0*fract(p*C.www)-1.0;vec3 h=abs(x)-0.5;vec3 ox=floor(x+0.5);vec3 a0=x-ox;m*=1.79284291400159-0.85373472095314*(a0*a0+h*h);vec3 g;g.x=a0.x*x0.x+h.x*x0.y;g.yz=a0.yz*x12.xz+h.yz*x12.yw;return 130.0*dot(m,g);}void main(){vec2 st=v_uv*2.0-1.0;st.x*=u_resolution.x/u_resolution.y;float radius=length(st);float absAngle=atan(st.x,st.y);if(absAngle<0.0)absAngle+=TWO_PI;float relAngle=absAngle-u_startAngle;relAngle=mod(relAngle,TWO_PI);if(relAngle<0.0)relAngle+=TWO_PI;if(u_reversed>0.5){relAngle=TWO_PI-relAngle;}float angle=mod(relAngle,TWO_PI);float progressAngle=u_progress*TWO_PI;float time=u_time*2.0;float noiseFreq=2.0;float radiusFreq=3.0;float trackWidth=u_outerRadius-u_innerRadius;float normRadius=(radius-u_innerRadius)/trackWidth;float nx=cos(angle)*noiseFreq;float ny=sin(angle)*noiseFreq;float flowAngle=angle-time*0.5;float n_x=cos(flowAngle)*noiseFreq;float n_y=sin(flowAngle)*noiseFreq;float n_z=normRadius*radiusFreq;vec2 polarUV=vec2(cos(angle),sin(angle))*(2.0+normRadius)-vec2(time,time*0.5);float n=snoise(polarUV*1.5);vec2 polarUV2=vec2(cos(angle+1.0),sin(angle+1.0))*(3.0+normRadius*2.0)-vec2(time*1.5,-time);float n2=snoise(polarUV2*2.0);float fireNoise=n*0.6+n2*0.4;float ringInner=smoothstep(u_innerRadius-0.01,u_innerRadius,radius);float trackCenter=(u_innerRadius+u_outerRadius)*0.5;float distFromCenter=abs(radius-trackCenter);float halfWidth=(u_outerRadius-u_innerRadius)*0.5;float arcLen=trackCenter*progressAngle;float capRadius=halfWidth;float roundingFactor=1.0;if(u_progress>0.9){roundingFactor=(1.0-u_progress)*10.0;}float effectiveCapRadius=capRadius*roundingFactor;float distToHeadArc=(progressAngle-angle)*trackCenter;float distToTailArc=angle*trackCenter;float headAlpha=1.0;if(distToHeadArc<effectiveCapRadius&&distToHeadArc>-effectiveCapRadius){float dX=(progressAngle-angle)*trackCenter;float dY=radius-trackCenter;float distToCapCenter=sqrt(dX*dX+dY*dY);}float dHeadX=(angle-progressAngle)*trackCenter;float dHeadY=abs(radius-trackCenter);float capCircleRadius=halfWidth*roundingFactor;float dX_head=(angle-progressAngle)*trackCenter;float dY_cap=radius-trackCenter;float distHeadSq=dX_head*dX_head+dY_cap*dY_cap;float dX_tail=(angle-0.0)*trackCenter;float distTailSq=dX_tail*dX_tail+dY_cap*dY_cap;float dEnd=(progressAngle-angle)*trackCenter;float dStart=angle*trackCenter;float dSide=halfWidth-abs(radius-trackCenter);float headRounding=1.0;if(dEnd<effectiveCapRadius&&dSide<effectiveCapRadius){float cx=effectiveCapRadius-dEnd;float cy=effectiveCapRadius-dSide;float cornerDist=sqrt(cx*cx+cy*cy);headRounding=1.0-smoothstep(effectiveCapRadius-0.005,effectiveCapRadius+0.005,cornerDist);}float tailRounding=1.0;if(dStart<effectiveCapRadius&&dSide<effectiveCapRadius){float cx=effectiveCapRadius-dStart;float cy=effectiveCapRadius-dSide;float cornerDist=sqrt(cx*cx+cy*cy);tailRounding=1.0-smoothstep(effectiveCapRadius-0.005,effectiveCapRadius+0.005,cornerDist);}float roundingAlpha=headRounding*tailRounding;float flameHeight=u_outerRadius+fireNoise*0.04*u_intensity;float ringOuter=smoothstep(flameHeight,flameHeight+0.02,radius);float ringAlpha=ringInner-ringOuter;ringAlpha=clamp(ringAlpha,0.0,1.0);ringAlpha*=roundingAlpha;float headNoise=snoise(vec2(time*5.0,radius*10.0))*0.05*u_intensity;float isVisible=0.0;if(u_progress>=0.995){isVisible=1.0;}else{float effectiveAngle=angle;float diff=progressAngle-angle;if(diff>0.0){isVisible=1.0;}}float headFade=smoothstep(0.0,0.02,progressAngle-angle);float tailFade=smoothstep(0.0,0.02,angle);if(u_progress>=0.99){tailFade=1.0;headFade=1.0;}float fillAlpha=isVisible*headFade*tailFade;if(u_progress<0.001)fillAlpha=0.0;float centerDist=abs(normRadius-0.5)*2.0;float heatMap=(fireNoise*0.5+0.5);heatMap*=(1.0-centerDist*0.5);heatMap*=(0.8+u_intensity*0.4);float relPos=angle/(progressAngle+0.001);float heatBoostHead=smoothstep(0.7,1.0,relPos)*0.4*u_intensity;float heatBoostTail=smoothstep(0.3,0.0,relPos)*0.4*u_intensity;heatMap+=heatBoostHead+heatBoostTail;float gradientPos=angle/TWO_PI;vec3 baseColor=texture(u_gradientTexture,vec2(gradientPos,0.5)).rgb;vec3 black=vec3(0.0);vec3 white=vec3(1.0);vec3 finalColor=black;if(heatMap<0.5){float t=heatMap/0.5;finalColor=mix(black,baseColor,t*t);}else{float t=(heatMap-0.5)/0.5;finalColor=mix(baseColor,white,t*t);}float finalAlpha=ringAlpha*fillAlpha;fragColor=vec4(finalColor,finalAlpha);}";
|
|
4
|
+
|
|
5
|
+
module.exports = fragmentShaderSource;
|
|
6
|
+
//# sourceMappingURL=fragment.frag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment.frag.js","sources":["../../../../../src/classes/CircularProgressFire/shaders/fragment.frag"],"sourcesContent":["#version 300 es\nprecision mediump float;\n\nin vec2 v_uv;\nout vec4 fragColor;\n\nuniform float u_time;\nuniform float u_progress;\nuniform vec2 u_resolution;\nuniform float u_innerRadius;\nuniform float u_outerRadius;\nuniform float u_startAngle;\nuniform float u_reversed;\nuniform sampler2D u_gradientTexture;\nuniform float u_intensity;\n\n#define PI 3.14159265359\n#define TWO_PI 6.28318530718\n\n// Simplex noise helper functions\nvec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }\n\nfloat snoise(vec2 v){\n const vec4 C = vec4(0.211324865405187, 0.366025403784439,\n -0.577350269189626, 0.024390243902439);\n vec2 i = floor(v + dot(v, C.yy) );\n vec2 x0 = v - i + dot(i, C.xx);\n vec2 i1;\n i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n i = mod(i, 289.0);\n vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))\n + i.x + vec3(0.0, i1.x, 1.0 ));\n vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);\n m = m*m ;\n m = m*m ;\n vec3 x = 2.0 * fract(p * C.www) - 1.0;\n vec3 h = abs(x) - 0.5;\n vec3 ox = floor(x + 0.5);\n vec3 a0 = x - ox;\n m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );\n vec3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\nvoid main() {\n vec2 st = v_uv * 2.0 - 1.0;\n st.x *= u_resolution.x / u_resolution.y;\n\n float radius = length(st);\n\n // --- ANGLE CALCULATION ---\n float absAngle = atan(st.x, st.y);\n if (absAngle < 0.0) absAngle += TWO_PI;\n\n float relAngle = absAngle - u_startAngle;\n relAngle = mod(relAngle, TWO_PI);\n if (relAngle < 0.0) relAngle += TWO_PI;\n\n if (u_reversed > 0.5) {\n relAngle = TWO_PI - relAngle;\n }\n \n float angle = mod(relAngle, TWO_PI);\n float progressAngle = u_progress * TWO_PI;\n\n // --- FIRE NOISE ---\n // Make noise flow ALONG the ring (using angle) instead of radiating out\n float time = u_time * 2.0;\n \n // Coordinate system for noise:\n // We map polar coordinates to 3D space to ensure seamless looping at 0/360 degrees.\n // x,y: circle in 2D plane (based on angle)\n // z: time + radius variations\n \n float noiseFreq = 2.0; // Frequency of noise around the ring\n float radiusFreq = 3.0; // Frequency across the track width\n \n // Normalize radius to 0..1 within the track for better noise mapping\n float trackWidth = u_outerRadius - u_innerRadius;\n float normRadius = (radius - u_innerRadius) / trackWidth;\n \n // 3D Noise inputs\n // To make it loop perfectly:\n // We trace a circle in the noise space.\n float nx = cos(angle) * noiseFreq;\n float ny = sin(angle) * noiseFreq;\n // We add 'time' to Z to animate flow.\n // We add normRadius to Z to vary noise across width.\n // To make flow look like it moves along the ring, we rotate the angle with time.\n \n float flowAngle = angle - time * 0.5; // Flow direction\n float n_x = cos(flowAngle) * noiseFreq;\n float n_y = sin(flowAngle) * noiseFreq;\n float n_z = normRadius * radiusFreq; \n \n // However, we don't have snoise3. Let's fake it with snoise2 by mixing or careful mapping.\n // Or we can just use snoise2 with a clever wrapping? \n // No, snoise(vec2) is hard to wrap perfectly without artifacts unless we use 4D noise projected to 2D loop.\n // BUT, we can use the standard trick: mix two noise samples? No.\n \n // Let's implement a simple psuedo-3D noise or just use the domain wrapping trick with 2D noise:\n // Noise(x, y) where x is cos(a), y is sin(a) -> this loops!\n // But we need animation (time).\n // We can animate the domain offset? No.\n // We can animate the Z? We don't have Z.\n \n // Workaround with 2D noise for looping 1D domain + time:\n // We need 3 dimensions: Angle(loop), Radius(non-loop), Time(linear).\n // We can use 2D noise for (AngleLoop, Time).\n // AngleLoop needs 2 coords (cos, sin). So we need 3D noise.\n \n // Since we only have snoise(vec2) included, let's just use the coordinate mapping that minimizes the seam\n // OR accept that we need a better noise function.\n // Let's stick to snoise(vec2) but map it carefully.\n // Actually, let's just use the polar mapping:\n // noise(cos(a)*R + time, sin(a)*R) -> this distorts.\n \n // Better approach with what we have:\n // Let's use the polar coordinates directly but \"blend\" the seam at 0/2PI.\n // We sample noise at 'angle' and 'angle - 2PI' and mix them? \n \n // Let's try a simple Polar projection into 2D plane which rotates.\n // This is seamless by definition.\n vec2 polarUV = vec2(cos(angle), sin(angle)) * (2.0 + normRadius) - vec2(time, time * 0.5);\n // This rotates the noise field. It is seamless.\n \n // Main flame shape noise\n float n = snoise(polarUV * 1.5);\n \n // Detail noise (rotate faster/different direction)\n vec2 polarUV2 = vec2(cos(angle + 1.0), sin(angle + 1.0)) * (3.0 + normRadius * 2.0) - vec2(time * 1.5, -time);\n float n2 = snoise(polarUV2 * 2.0);\n \n float fireNoise = n * 0.6 + n2 * 0.4; // Range approx -1 to 1\n \n // --- RING SHAPE & MASK ---\n // Hard clamp at inner radius, soft fade at outer\n float ringInner = smoothstep(u_innerRadius - 0.01, u_innerRadius, radius);\n \n // Border radius effect\n // We want the \"head\" and \"tail\" to be rounded.\n // Distance from the center line of the track\n float trackCenter = (u_innerRadius + u_outerRadius) * 0.5;\n float distFromCenter = abs(radius - trackCenter);\n float halfWidth = (u_outerRadius - u_innerRadius) * 0.5;\n \n // Cap radius (rounding)\n // We want full rounding when progress is small, and diminishing rounding as it approaches 100%\n // Actually, simple rounded caps are just distance checks from the end points in Cartesian space.\n // But in polar, we can approximate.\n \n // Arc length at center radius\n float arcLen = trackCenter * progressAngle;\n float capRadius = halfWidth; // Full rounding radius\n \n // Reduce rounding radius as we near completion to make it seamless\n // Start reducing at 90% progress?\n float roundingFactor = 1.0;\n if (u_progress > 0.9) {\n roundingFactor = (1.0 - u_progress) * 10.0; // 1.0 at 0.9, 0.0 at 1.0\n }\n \n float effectiveCapRadius = capRadius * roundingFactor;\n \n // To implement caps in shader without expensive cartesian distance:\n // We use the angle distance converted to arc length.\n \n float distToHeadArc = (progressAngle - angle) * trackCenter;\n float distToTailArc = angle * trackCenter;\n \n // Check if we are in the \"cap zone\"\n // Head Cap\n float headAlpha = 1.0;\n if (distToHeadArc < effectiveCapRadius && distToHeadArc > -effectiveCapRadius) {\n // We are near the head.\n // Distance from the \"cap center\" point\n // Cap center is at angle = progressAngle - (capRadius/R) ? No, cap center is at the end of the bar.\n // Actually, a round cap usually extends OUT or is cut IN.\n // Let's assume \"inset\" caps or just rounding the corners?\n // Standard \"round\" lineCap extends beyond the endpoint by radius.\n // Here, let's round the CORNERS of the cut.\n \n // Let's model a circle at the end point.\n // End point in polar: (progressAngle, trackCenter)\n // Current point: (angle, radius)\n \n // Approximate distance in 2D (valid for small angles)\n float dX = (progressAngle - angle) * trackCenter;\n float dY = radius - trackCenter;\n float distToCapCenter = sqrt(dX*dX + dY*dY);\n \n // If we are \"ahead\" of the cut line, we mask? No, we want to round the cut.\n // Let's mask anything beyond the line, BUT add the circle.\n \n // Simplified: \n // 1. Mask everything beyond progressAngle (handled by headFade logic mostly)\n // 2. Except if inside the cap circle at the end.\n \n // But user wants \"border-radius like\", maybe just rounding the corners of the flat cut?\n // Let's assume we want a full semi-circle cap.\n \n // It's easier to mask everything > progressAngle, and add a circle at progressAngle.\n // BUT, we need to fade out this effect.\n \n // Let's use the \"Alpha\" we already computed (fillAlpha) which defines the cut.\n // And modify it.\n }\n \n // Simpler approach for \"Border Radius\" style effect on the cut:\n // We modify the opacity based on distance from the corner.\n \n // But wait, we are doing Fire. The edge is already soft.\n // User wants a \"rounded\" shape at the ends.\n \n // Let's use a Signed Distance Field (SDF) approach for the bar tips.\n \n // Tip 1: Head\n float dHeadX = (angle - progressAngle) * trackCenter; // Positive ahead, negative behind\n float dHeadY = abs(radius - trackCenter); // Distance from center line\n \n // SDF for a box with one rounded end? Or just a circle at the end?\n // Let's define the shape as: (Bar) U (Circle at Head) U (Circle at Tail)\n // Bar is defined by angles 0..progressAngle.\n // Circle Head at (progressAngle). Circle Tail at (0).\n \n // But we want the circle radius to shrink.\n \n float capCircleRadius = halfWidth * roundingFactor;\n \n // Check head circle\n float dX_head = (angle - progressAngle) * trackCenter;\n float dY_cap = radius - trackCenter;\n float distHeadSq = dX_head*dX_head + dY_cap*dY_cap;\n \n // Check tail circle\n float dX_tail = (angle - 0.0) * trackCenter;\n float distTailSq = dX_tail*dX_tail + dY_cap*dY_cap;\n \n // Modify visibility\n // Standard bar is angle <= progressAngle && angle >= 0\n // We want to ERODE the corners? Or EXTEND?\n // Usually border-radius on a progress bar means the ends are rounded.\n // So the effective bar is shorter, and we have caps.\n \n // Let's treat the bar as:\n // Rect from [capRadius/L] to [progress - capRadius/L]\n // + Circle at start + Circle at end.\n \n // This effectively \"shrinks\" the visual bar if we keep angles same.\n \n // Let's just apply a mask that rounds the corners of the existing sector.\n // Distance from the \"Corner\" (intersection of radial cut and outer/inner rings).\n \n // It's getting complicated for a shader without proper SDF.\n // Let's try a visual trick.\n // Smoothstep the alpha based on distance to the \"end line\" combined with distance to edge.\n \n // Distance to Head Line: (progressAngle - angle) * trackCenter\n // Distance to Edge (side): halfWidth - abs(radius - trackCenter)\n \n float dEnd = (progressAngle - angle) * trackCenter;\n float dStart = angle * trackCenter;\n float dSide = halfWidth - abs(radius - trackCenter);\n \n // We want the alpha to be 0 if sqrt(dEnd^2 + dSide^2) < radius (inverted corner)?\n // No, standard rounded rect logic: \n // Alpha = smoothstep(radius, radius-1, distance_from_inner_rect)\n \n // Let's model the tip as a rounded box shape SDF in 2D local space of the tip.\n // Tip space: x = distance from end, y = distance from center.\n // We want to round the corners where x -> 0 and y -> halfWidth.\n \n // Head Rounding\n float headRounding = 1.0;\n if (dEnd < effectiveCapRadius && dSide < effectiveCapRadius) {\n // Inside the corner zone\n float cx = effectiveCapRadius - dEnd;\n float cy = effectiveCapRadius - dSide;\n float cornerDist = sqrt(cx*cx + cy*cy);\n headRounding = 1.0 - smoothstep(effectiveCapRadius - 0.005, effectiveCapRadius + 0.005, cornerDist);\n }\n \n // Tail Rounding\n float tailRounding = 1.0;\n if (dStart < effectiveCapRadius && dSide < effectiveCapRadius) {\n float cx = effectiveCapRadius - dStart;\n float cy = effectiveCapRadius - dSide;\n float cornerDist = sqrt(cx*cx + cy*cy);\n tailRounding = 1.0 - smoothstep(effectiveCapRadius - 0.005, effectiveCapRadius + 0.005, cornerDist);\n }\n \n float roundingAlpha = headRounding * tailRounding;\n\n // The \"flame\" height varies.\n // We modify the effective outer radius with noise.\n // Base outer limit is u_outerRadius.\n // Flames can lick slightly outside, but we want to contain them mostly.\n \n // To prevent clipping, we should ensure u_outerRadius passed from JS leaves room.\n // But if we want strict bounds, we fade out before the edge.\n \n float flameHeight = u_outerRadius + fireNoise * 0.04 * u_intensity;\n float ringOuter = smoothstep(flameHeight, flameHeight + 0.02, radius);\n \n float ringAlpha = ringInner - ringOuter;\n ringAlpha = clamp(ringAlpha, 0.0, 1.0);\n \n // Apply rounding\n ringAlpha *= roundingAlpha;\n\n // --- PROGRESS FILL LOGIC ---\n // The \"head\" is the leading edge of the fire.\n \n float headNoise = snoise(vec2(time * 5.0, radius * 10.0)) * 0.05 * u_intensity;\n \n // Determine if a pixel is within the active arc\n // We need to handle the \"tail\" (start) and \"head\" (end) of the progress.\n // 0 to progressAngle.\n \n float isVisible = 0.0;\n \n // Handle the wrap-around case for looping 100%\n // If progress is ~1.0, we want full circle without a seam at 0/360\n if (u_progress >= 0.995) {\n isVisible = 1.0;\n } else {\n // Basic check: angle < progressAngle?\n // But we also want the head to have noise.\n \n float effectiveAngle = angle;\n // If we are very close to 0, and progress is near 1, we might have issues, but standard angle logic works 0..2PI\n \n float diff = progressAngle - angle;\n // Add noise to the boundary\n if (diff > 0.0) {\n isVisible = 1.0;\n }\n \n // Hard cut at exactly 0 if we want? \n // Or let the tail fade in?\n // Let's fade the tail (near angle 0).\n }\n\n // Soft head edge\n // Use sharper transition if we have rounding, but user asked for rounding.\n // The fade logic conflicts slightly with solid rounding.\n // Let's reduce the fade width to make the rounding visible.\n float headFade = smoothstep(0.0, 0.02, progressAngle - angle);\n \n // Soft tail edge (fade in from 0)\n // We want the start of the fire (at angle 0) to not be a hard cut line, but a soft rise.\n \n // Calculate tailFade similarly to headFade but reversed\n // angle > 0.0 essentially.\n // We want to mask out where angle < 0 (which doesn't happen in 0..2PI space directly, but close to 0 it matters)\n \n float tailFade = smoothstep(0.0, 0.02, angle);\n \n // If looping (progress ~ 1), we don't want tailFade to cut the loop at 0.\n if (u_progress >= 0.99) {\n tailFade = 1.0;\n headFade = 1.0;\n }\n\n // Combine transparency\n float fillAlpha = isVisible * headFade * tailFade;\n \n // Ensure 0 progress is empty\n if (u_progress < 0.001) fillAlpha = 0.0;\n\n // --- COLORING ---\n // Fire color palette\n // Deep Red -> Orange -> Yellow -> White (Hot)\n \n // Map noise and radius to color heat\n // Heat is higher in the center of the track and lower at edges\n float centerDist = abs(normRadius - 0.5) * 2.0; // 0 at center, 1 at edges\n float heatMap = (fireNoise * 0.5 + 0.5); // 0..1\n \n // Modulate heat by track position (hottest in middle)\n heatMap *= (1.0 - centerDist * 0.5);\n \n // Modulate by intensity\n heatMap *= (0.8 + u_intensity * 0.4);\n \n // Make the head AND tail hotter\n // Normalize angle to 0..1 relative to progress\n float relPos = angle / (progressAngle + 0.001);\n \n // Boost heat at the head (relPos near 1)\n float heatBoostHead = smoothstep(0.7, 1.0, relPos) * 0.4 * u_intensity;\n \n // Boost heat at the tail (relPos near 0)\n float heatBoostTail = smoothstep(0.3, 0.0, relPos) * 0.4 * u_intensity;\n \n // Apply boosts\n heatMap += heatBoostHead + heatBoostTail;\n \n \n // Color interpolation from gradient texture\n // Map angle (0..2PI) to UV (0..1)\n float gradientPos = angle / TWO_PI;\n vec3 baseColor = texture(u_gradientTexture, vec2(gradientPos, 0.5)).rgb;\n\n vec3 black = vec3(0.0);\n vec3 white = vec3(1.0);\n \n vec3 finalColor = black;\n \n // Heat map coloring strategy:\n // 0.0 - 0.3: Black -> Dark Base\n // 0.3 - 0.6: Dark Base -> Base\n // 0.6 - 0.8: Base -> Bright Base\n // 0.8 - 1.0: Bright Base -> White\n\n // Simplified 3-stage:\n // Low heat: Black -> Base\n // High heat: Base -> White\n\n if (heatMap < 0.5) {\n // Darker phase\n // Power function to keep it dark longer\n float t = heatMap / 0.5;\n finalColor = mix(black, baseColor, t * t); \n } else {\n // Brighter phase\n float t = (heatMap - 0.5) / 0.5;\n // Mix to white\n finalColor = mix(baseColor, white, t * t);\n }\n \n // Alpha composition\n float finalAlpha = ringAlpha * fillAlpha;\n \n // Fade out the tail end of the color intensity slightly?\n // Optional: make the \"start\" of the bar colder and \"head\" hotter\n \n fragColor = vec4(finalColor, finalAlpha);\n}\n\n"],"names":[],"mappings":";;AAAA,2BAAe,6kKAA6kK;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertex.vert.js","sources":["../../../../../src/classes/CircularProgressFire/shaders/vertex.vert"],"sourcesContent":["#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n\n"],"names":[],"mappings":";;AAAA,yBAAe,8HAA8H;;;;"}
|