Add lens effect and step easing functions
- 단계별(Step) 이징 함수 추가 (steps2 ~ steps10) - 영역별 렌즈 왜곡 효과(볼록/오목) 기능 및 셰이더 로직 추가 - 에디터 파라미터 패널에 렌즈 효과 슬라이더 및 스텝 이징 옵션 추가 - 관련 상수, 타입 정의 및 유니폼 변수 업데이트 - 패키지 버전 업데이트 (1.2.7)
This commit is contained in:
parent
031230bc36
commit
6d9dd082c1
1
.npmrc
Normal file
1
.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
//git.bnovalab.com/api/packages/baekryang/npm/:_authToken=a2ed709f39e95662493a92305555a4bf70f6fe10
|
||||||
10
dist/distortion.frag.glsl
vendored
10
dist/distortion.frag.glsl
vendored
@ -4,6 +4,7 @@ uniform vec2 u_points[32]; // 최대 8영역 × 4포인트 (정규화된
|
|||||||
uniform int u_numAreas;
|
uniform int u_numAreas;
|
||||||
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
||||||
uniform float u_distortionStrengths[8];
|
uniform float u_distortionStrengths[8];
|
||||||
|
uniform float u_lensEffects[8];
|
||||||
|
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
|
|
||||||
@ -74,6 +75,15 @@ void main() {
|
|||||||
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
||||||
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
||||||
texCoord += distortion;
|
texCoord += distortion;
|
||||||
|
|
||||||
|
// 렌즈 왜곡 효과 (방사형 UV 왜곡)
|
||||||
|
if (abs(u_lensEffects[i]) > 0.001) {
|
||||||
|
vec2 centered = uv_local - vec2(0.5);
|
||||||
|
float dist2 = dot(centered, centered);
|
||||||
|
float lensK = u_lensEffects[i] * 2.0; // 강도 스케일링
|
||||||
|
vec2 lensDistortion = centered * lensK * dist2;
|
||||||
|
texCoord += lensDistortion * u_distortionStrengths[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
dist/index.d.mts
vendored
13
dist/index.d.mts
vendored
@ -11,7 +11,7 @@ interface Point {
|
|||||||
/**
|
/**
|
||||||
* 애니메이션 이징 함수 타입
|
* 애니메이션 이징 함수 타입
|
||||||
*/
|
*/
|
||||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
|
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'steps2' | 'steps3' | 'steps4' | 'steps5' | 'steps6' | 'steps8' | 'steps10';
|
||||||
/**
|
/**
|
||||||
* 내장 모션 프리셋 타입
|
* 내장 모션 프리셋 타입
|
||||||
*/
|
*/
|
||||||
@ -68,6 +68,11 @@ interface DistortionArea {
|
|||||||
influenceRadius: number;
|
influenceRadius: number;
|
||||||
maxStrength: number;
|
maxStrength: number;
|
||||||
};
|
};
|
||||||
|
/** 렌즈 효과 설정 (선택사항) */
|
||||||
|
lensEffect?: {
|
||||||
|
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||||
|
strength: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 영역 충돌 감지를 위한 경계 상자
|
* 영역 충돌 감지를 위한 경계 상자
|
||||||
@ -96,6 +101,8 @@ interface ShaderUniforms {
|
|||||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||||
/** 각 영역의 왜곡 강도 배열 */
|
/** 각 영역의 왜곡 강도 배열 */
|
||||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||||
|
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||||
|
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 셰이더 설정
|
* 셰이더 설정
|
||||||
@ -388,6 +395,8 @@ declare const SHADER_CONFIG: {
|
|||||||
readonly MAX_DRAG_VECTORS: 8;
|
readonly MAX_DRAG_VECTORS: 8;
|
||||||
/** 최대 강도 배열 크기 */
|
/** 최대 강도 배열 크기 */
|
||||||
readonly MAX_STRENGTHS: 8;
|
readonly MAX_STRENGTHS: 8;
|
||||||
|
/** 최대 렌즈 효과 배열 크기 */
|
||||||
|
readonly MAX_LENS_EFFECTS: 8;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 애니메이션 관련 설정
|
* 애니메이션 관련 설정
|
||||||
@ -418,6 +427,8 @@ declare const DEFAULT_AREA: {
|
|||||||
readonly x: -0.1;
|
readonly x: -0.1;
|
||||||
readonly y: -0.1;
|
readonly y: -0.1;
|
||||||
};
|
};
|
||||||
|
/** 기본 렌즈 효과 강도 */
|
||||||
|
readonly LENS_STRENGTH: 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
13
dist/index.d.ts
vendored
13
dist/index.d.ts
vendored
@ -11,7 +11,7 @@ interface Point {
|
|||||||
/**
|
/**
|
||||||
* 애니메이션 이징 함수 타입
|
* 애니메이션 이징 함수 타입
|
||||||
*/
|
*/
|
||||||
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
|
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'steps2' | 'steps3' | 'steps4' | 'steps5' | 'steps6' | 'steps8' | 'steps10';
|
||||||
/**
|
/**
|
||||||
* 내장 모션 프리셋 타입
|
* 내장 모션 프리셋 타입
|
||||||
*/
|
*/
|
||||||
@ -68,6 +68,11 @@ interface DistortionArea {
|
|||||||
influenceRadius: number;
|
influenceRadius: number;
|
||||||
maxStrength: number;
|
maxStrength: number;
|
||||||
};
|
};
|
||||||
|
/** 렌즈 효과 설정 (선택사항) */
|
||||||
|
lensEffect?: {
|
||||||
|
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||||
|
strength: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 영역 충돌 감지를 위한 경계 상자
|
* 영역 충돌 감지를 위한 경계 상자
|
||||||
@ -96,6 +101,8 @@ interface ShaderUniforms {
|
|||||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||||
/** 각 영역의 왜곡 강도 배열 */
|
/** 각 영역의 왜곡 강도 배열 */
|
||||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||||
|
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||||
|
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 셰이더 설정
|
* 셰이더 설정
|
||||||
@ -388,6 +395,8 @@ declare const SHADER_CONFIG: {
|
|||||||
readonly MAX_DRAG_VECTORS: 8;
|
readonly MAX_DRAG_VECTORS: 8;
|
||||||
/** 최대 강도 배열 크기 */
|
/** 최대 강도 배열 크기 */
|
||||||
readonly MAX_STRENGTHS: 8;
|
readonly MAX_STRENGTHS: 8;
|
||||||
|
/** 최대 렌즈 효과 배열 크기 */
|
||||||
|
readonly MAX_LENS_EFFECTS: 8;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 애니메이션 관련 설정
|
* 애니메이션 관련 설정
|
||||||
@ -418,6 +427,8 @@ declare const DEFAULT_AREA: {
|
|||||||
readonly x: -0.1;
|
readonly x: -0.1;
|
||||||
readonly y: -0.1;
|
readonly y: -0.1;
|
||||||
};
|
};
|
||||||
|
/** 기본 렌즈 효과 강도 */
|
||||||
|
readonly LENS_STRENGTH: 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
57
dist/index.js
vendored
57
dist/index.js
vendored
@ -96,7 +96,8 @@ var ThreeScene = class {
|
|||||||
u_numAreas: { value: 0 },
|
u_numAreas: { value: 0 },
|
||||||
u_dragVectors: { value: new Float32Array(16) },
|
u_dragVectors: { value: new Float32Array(16) },
|
||||||
// 8벡터 × 2(x,y)
|
// 8벡터 × 2(x,y)
|
||||||
u_distortionStrengths: { value: new Float32Array(8) }
|
u_distortionStrengths: { value: new Float32Array(8) },
|
||||||
|
u_lensEffects: { value: new Float32Array(8) }
|
||||||
};
|
};
|
||||||
this.handleResize();
|
this.handleResize();
|
||||||
window.addEventListener("resize", this.handleResize);
|
window.addEventListener("resize", this.handleResize);
|
||||||
@ -242,6 +243,7 @@ var ShaderManager = class {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// src/utils/easing.ts
|
// src/utils/easing.ts
|
||||||
|
var createStepEasing = (steps) => (t) => Math.floor(t * steps) / steps;
|
||||||
var easingFunctions = {
|
var easingFunctions = {
|
||||||
linear: (t) => t,
|
linear: (t) => t,
|
||||||
easeIn: (t) => t * t,
|
easeIn: (t) => t * t,
|
||||||
@ -250,7 +252,14 @@ var easingFunctions = {
|
|||||||
easeInQuad: (t) => t * t,
|
easeInQuad: (t) => t * t,
|
||||||
easeOutQuad: (t) => t * (2 - t),
|
easeOutQuad: (t) => t * (2 - t),
|
||||||
easeInCubic: (t) => t * t * t,
|
easeInCubic: (t) => t * t * t,
|
||||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
|
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||||
|
steps2: createStepEasing(2),
|
||||||
|
steps3: createStepEasing(3),
|
||||||
|
steps4: createStepEasing(4),
|
||||||
|
steps5: createStepEasing(5),
|
||||||
|
steps6: createStepEasing(6),
|
||||||
|
steps8: createStepEasing(8),
|
||||||
|
steps10: createStepEasing(10)
|
||||||
};
|
};
|
||||||
var applyEasing = (progress, easingType) => {
|
var applyEasing = (progress, easingType) => {
|
||||||
const clampedProgress = Math.max(0, Math.min(1, progress));
|
const clampedProgress = Math.max(0, Math.min(1, progress));
|
||||||
@ -808,7 +817,9 @@ var SHADER_CONFIG = {
|
|||||||
/** 최대 드래그 벡터 개수 */
|
/** 최대 드래그 벡터 개수 */
|
||||||
MAX_DRAG_VECTORS: 8,
|
MAX_DRAG_VECTORS: 8,
|
||||||
/** 최대 강도 배열 크기 */
|
/** 최대 강도 배열 크기 */
|
||||||
MAX_STRENGTHS: 8
|
MAX_STRENGTHS: 8,
|
||||||
|
/** 최대 렌즈 효과 배열 크기 */
|
||||||
|
MAX_LENS_EFFECTS: 8
|
||||||
};
|
};
|
||||||
var ANIMATION_CONFIG = {
|
var ANIMATION_CONFIG = {
|
||||||
/** 목표 FPS */
|
/** 목표 FPS */
|
||||||
@ -826,7 +837,9 @@ var DEFAULT_AREA = {
|
|||||||
/** 기본 벡터 A */
|
/** 기본 벡터 A */
|
||||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||||
/** 기본 벡터 B */
|
/** 기본 벡터 B */
|
||||||
VECTOR_B: { x: -0.1, y: -0.1 }
|
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||||
|
/** 기본 렌즈 효과 강도 */
|
||||||
|
LENS_STRENGTH: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/components/ImageDistortion.tsx
|
// src/components/ImageDistortion.tsx
|
||||||
@ -958,11 +971,16 @@ var ImageDistortion = ({
|
|||||||
currentAreas.forEach((area, index) => {
|
currentAreas.forEach((area, index) => {
|
||||||
strengths[index] = area.distortionStrength;
|
strengths[index] = area.distortionStrength;
|
||||||
});
|
});
|
||||||
|
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||||
|
currentAreas.forEach((area, index) => {
|
||||||
|
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||||
|
});
|
||||||
sceneRef.current.updateUniforms({
|
sceneRef.current.updateUniforms({
|
||||||
u_numAreas: { value: currentAreas.length },
|
u_numAreas: { value: currentAreas.length },
|
||||||
u_points: { value: points },
|
u_points: { value: points },
|
||||||
u_dragVectors: { value: dragVectors },
|
u_dragVectors: { value: dragVectors },
|
||||||
u_distortionStrengths: { value: strengths }
|
u_distortionStrengths: { value: strengths },
|
||||||
|
u_lensEffects: { value: lensEffects }
|
||||||
});
|
});
|
||||||
sceneRef.current.render();
|
sceneRef.current.render();
|
||||||
}, [currentAreas, isReady]);
|
}, [currentAreas, isReady]);
|
||||||
@ -1092,7 +1110,14 @@ var EASING_OPTIONS = [
|
|||||||
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
||||||
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
||||||
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
||||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" }
|
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" },
|
||||||
|
{ value: "steps2", label: "2\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps3", label: "3\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps4", label: "4\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps5", label: "5\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps6", label: "6\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps8", label: "8\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps10", label: "10\uB2E8\uACC4 \uC2A4\uD15D" }
|
||||||
];
|
];
|
||||||
var ParameterPanel = ({ area, onUpdateArea }) => {
|
var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||||
if (!area) {
|
if (!area) {
|
||||||
@ -1154,6 +1179,26 @@ var ParameterPanel = ({ area, onUpdateArea }) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
] }),
|
] }),
|
||||||
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "parameter-group", children: [
|
||||||
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { children: [
|
||||||
|
"\uB80C\uC988 \uD6A8\uACFC: ",
|
||||||
|
(area.lensEffect?.strength ?? 0) > 0 ? "\uBCFC\uB85D " : (area.lensEffect?.strength ?? 0) < 0 ? "\uC624\uBAA9 " : "",
|
||||||
|
((area.lensEffect?.strength ?? 0) * 100).toFixed(0),
|
||||||
|
"%"
|
||||||
|
] }),
|
||||||
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
||||||
|
"input",
|
||||||
|
{
|
||||||
|
type: "range",
|
||||||
|
min: "-1",
|
||||||
|
max: "1",
|
||||||
|
step: "0.01",
|
||||||
|
value: area.lensEffect?.strength ?? 0,
|
||||||
|
onChange: (e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } }),
|
||||||
|
className: "slider"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "parameter-group", children: [
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "parameter-group", children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "point-coord", children: [
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "point-coord", children: [
|
||||||
|
|||||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
57
dist/index.mjs
vendored
57
dist/index.mjs
vendored
@ -36,7 +36,8 @@ var ThreeScene = class {
|
|||||||
u_numAreas: { value: 0 },
|
u_numAreas: { value: 0 },
|
||||||
u_dragVectors: { value: new Float32Array(16) },
|
u_dragVectors: { value: new Float32Array(16) },
|
||||||
// 8벡터 × 2(x,y)
|
// 8벡터 × 2(x,y)
|
||||||
u_distortionStrengths: { value: new Float32Array(8) }
|
u_distortionStrengths: { value: new Float32Array(8) },
|
||||||
|
u_lensEffects: { value: new Float32Array(8) }
|
||||||
};
|
};
|
||||||
this.handleResize();
|
this.handleResize();
|
||||||
window.addEventListener("resize", this.handleResize);
|
window.addEventListener("resize", this.handleResize);
|
||||||
@ -182,6 +183,7 @@ var ShaderManager = class {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// src/utils/easing.ts
|
// src/utils/easing.ts
|
||||||
|
var createStepEasing = (steps) => (t) => Math.floor(t * steps) / steps;
|
||||||
var easingFunctions = {
|
var easingFunctions = {
|
||||||
linear: (t) => t,
|
linear: (t) => t,
|
||||||
easeIn: (t) => t * t,
|
easeIn: (t) => t * t,
|
||||||
@ -190,7 +192,14 @@ var easingFunctions = {
|
|||||||
easeInQuad: (t) => t * t,
|
easeInQuad: (t) => t * t,
|
||||||
easeOutQuad: (t) => t * (2 - t),
|
easeOutQuad: (t) => t * (2 - t),
|
||||||
easeInCubic: (t) => t * t * t,
|
easeInCubic: (t) => t * t * t,
|
||||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
|
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||||
|
steps2: createStepEasing(2),
|
||||||
|
steps3: createStepEasing(3),
|
||||||
|
steps4: createStepEasing(4),
|
||||||
|
steps5: createStepEasing(5),
|
||||||
|
steps6: createStepEasing(6),
|
||||||
|
steps8: createStepEasing(8),
|
||||||
|
steps10: createStepEasing(10)
|
||||||
};
|
};
|
||||||
var applyEasing = (progress, easingType) => {
|
var applyEasing = (progress, easingType) => {
|
||||||
const clampedProgress = Math.max(0, Math.min(1, progress));
|
const clampedProgress = Math.max(0, Math.min(1, progress));
|
||||||
@ -748,7 +757,9 @@ var SHADER_CONFIG = {
|
|||||||
/** 최대 드래그 벡터 개수 */
|
/** 최대 드래그 벡터 개수 */
|
||||||
MAX_DRAG_VECTORS: 8,
|
MAX_DRAG_VECTORS: 8,
|
||||||
/** 최대 강도 배열 크기 */
|
/** 최대 강도 배열 크기 */
|
||||||
MAX_STRENGTHS: 8
|
MAX_STRENGTHS: 8,
|
||||||
|
/** 최대 렌즈 효과 배열 크기 */
|
||||||
|
MAX_LENS_EFFECTS: 8
|
||||||
};
|
};
|
||||||
var ANIMATION_CONFIG = {
|
var ANIMATION_CONFIG = {
|
||||||
/** 목표 FPS */
|
/** 목표 FPS */
|
||||||
@ -766,7 +777,9 @@ var DEFAULT_AREA = {
|
|||||||
/** 기본 벡터 A */
|
/** 기본 벡터 A */
|
||||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||||
/** 기본 벡터 B */
|
/** 기본 벡터 B */
|
||||||
VECTOR_B: { x: -0.1, y: -0.1 }
|
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||||
|
/** 기본 렌즈 효과 강도 */
|
||||||
|
LENS_STRENGTH: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/components/ImageDistortion.tsx
|
// src/components/ImageDistortion.tsx
|
||||||
@ -898,11 +911,16 @@ var ImageDistortion = ({
|
|||||||
currentAreas.forEach((area, index) => {
|
currentAreas.forEach((area, index) => {
|
||||||
strengths[index] = area.distortionStrength;
|
strengths[index] = area.distortionStrength;
|
||||||
});
|
});
|
||||||
|
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||||
|
currentAreas.forEach((area, index) => {
|
||||||
|
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||||
|
});
|
||||||
sceneRef.current.updateUniforms({
|
sceneRef.current.updateUniforms({
|
||||||
u_numAreas: { value: currentAreas.length },
|
u_numAreas: { value: currentAreas.length },
|
||||||
u_points: { value: points },
|
u_points: { value: points },
|
||||||
u_dragVectors: { value: dragVectors },
|
u_dragVectors: { value: dragVectors },
|
||||||
u_distortionStrengths: { value: strengths }
|
u_distortionStrengths: { value: strengths },
|
||||||
|
u_lensEffects: { value: lensEffects }
|
||||||
});
|
});
|
||||||
sceneRef.current.render();
|
sceneRef.current.render();
|
||||||
}, [currentAreas, isReady]);
|
}, [currentAreas, isReady]);
|
||||||
@ -1032,7 +1050,14 @@ var EASING_OPTIONS = [
|
|||||||
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
{ value: "easeOut", label: "\uAC10\uC18D (Ease Out)" },
|
||||||
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
{ value: "easeInOut", label: "\uAC00\uAC10\uC18D (Ease In Out)" },
|
||||||
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
{ value: "easeInQuad", label: "\uAC00\uC18D\xB2 (Ease In Quad)" },
|
||||||
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" }
|
{ value: "easeOutQuad", label: "\uAC10\uC18D\xB2 (Ease Out Quad)" },
|
||||||
|
{ value: "steps2", label: "2\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps3", label: "3\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps4", label: "4\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps5", label: "5\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps6", label: "6\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps8", label: "8\uB2E8\uACC4 \uC2A4\uD15D" },
|
||||||
|
{ value: "steps10", label: "10\uB2E8\uACC4 \uC2A4\uD15D" }
|
||||||
];
|
];
|
||||||
var ParameterPanel = ({ area, onUpdateArea }) => {
|
var ParameterPanel = ({ area, onUpdateArea }) => {
|
||||||
if (!area) {
|
if (!area) {
|
||||||
@ -1094,6 +1119,26 @@ var ParameterPanel = ({ area, onUpdateArea }) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
] }),
|
] }),
|
||||||
|
/* @__PURE__ */ jsxs2("div", { className: "parameter-group", children: [
|
||||||
|
/* @__PURE__ */ jsxs2("label", { children: [
|
||||||
|
"\uB80C\uC988 \uD6A8\uACFC: ",
|
||||||
|
(area.lensEffect?.strength ?? 0) > 0 ? "\uBCFC\uB85D " : (area.lensEffect?.strength ?? 0) < 0 ? "\uC624\uBAA9 " : "",
|
||||||
|
((area.lensEffect?.strength ?? 0) * 100).toFixed(0),
|
||||||
|
"%"
|
||||||
|
] }),
|
||||||
|
/* @__PURE__ */ jsx3(
|
||||||
|
"input",
|
||||||
|
{
|
||||||
|
type: "range",
|
||||||
|
min: "-1",
|
||||||
|
max: "1",
|
||||||
|
step: "0.01",
|
||||||
|
value: area.lensEffect?.strength ?? 0,
|
||||||
|
onChange: (e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } }),
|
||||||
|
className: "slider"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
] }),
|
||||||
/* @__PURE__ */ jsxs2("div", { className: "parameter-group", children: [
|
/* @__PURE__ */ jsxs2("div", { className: "parameter-group", children: [
|
||||||
/* @__PURE__ */ jsx3("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
/* @__PURE__ */ jsx3("label", { children: "\uD3EC\uC778\uD2B8 \uC88C\uD45C (\uCE94\uBC84\uC2A4\uC5D0\uC11C \uB4DC\uB798\uADF8)" }),
|
||||||
/* @__PURE__ */ jsx3("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ jsxs2("div", { className: "point-coord", children: [
|
/* @__PURE__ */ jsx3("div", { className: "points-display", children: area.basePoints.map((point, idx) => /* @__PURE__ */ jsxs2("div", { className: "point-coord", children: [
|
||||||
|
|||||||
2
dist/index.mjs.map
vendored
2
dist/index.mjs.map
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@baekryang/responsive-image-canvas",
|
"name": "@baekryang/responsive-image-canvas",
|
||||||
"version": "1.2.6",
|
"version": "1.2.7",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
|
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -196,11 +196,18 @@ export const ImageDistortion: React.FC<ImageDistortionProps> = ({
|
|||||||
strengths[index] = area.distortionStrength;
|
strengths[index] = area.distortionStrength;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 렌즈 효과 배열 생성
|
||||||
|
const lensEffects = new Float32Array(SHADER_CONFIG.MAX_LENS_EFFECTS);
|
||||||
|
currentAreas.forEach((area, index) => {
|
||||||
|
lensEffects[index] = area.lensEffect?.strength ?? 0;
|
||||||
|
});
|
||||||
|
|
||||||
sceneRef.current.updateUniforms({
|
sceneRef.current.updateUniforms({
|
||||||
u_numAreas: { value: currentAreas.length },
|
u_numAreas: { value: currentAreas.length },
|
||||||
u_points: { value: points },
|
u_points: { value: points },
|
||||||
u_dragVectors: { value: dragVectors },
|
u_dragVectors: { value: dragVectors },
|
||||||
u_distortionStrengths: { value: strengths },
|
u_distortionStrengths: { value: strengths },
|
||||||
|
u_lensEffects: { value: lensEffects },
|
||||||
});
|
});
|
||||||
|
|
||||||
sceneRef.current.render();
|
sceneRef.current.render();
|
||||||
|
|||||||
@ -13,6 +13,13 @@ const EASING_OPTIONS: { value: EasingFunction; label: string }[] = [
|
|||||||
{ value: 'easeInOut', label: '가감속 (Ease In Out)' },
|
{ value: 'easeInOut', label: '가감속 (Ease In Out)' },
|
||||||
{ value: 'easeInQuad', label: '가속² (Ease In Quad)' },
|
{ value: 'easeInQuad', label: '가속² (Ease In Quad)' },
|
||||||
{ value: 'easeOutQuad', label: '감속² (Ease Out Quad)' },
|
{ value: 'easeOutQuad', label: '감속² (Ease Out Quad)' },
|
||||||
|
{ value: 'steps2', label: '2단계 스텝' },
|
||||||
|
{ value: 'steps3', label: '3단계 스텝' },
|
||||||
|
{ value: 'steps4', label: '4단계 스텝' },
|
||||||
|
{ value: 'steps5', label: '5단계 스텝' },
|
||||||
|
{ value: 'steps6', label: '6단계 스텝' },
|
||||||
|
{ value: 'steps8', label: '8단계 스텝' },
|
||||||
|
{ value: 'steps10', label: '10단계 스텝' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ParameterPanel: React.FC<ParameterPanelProps> = ({ area, onUpdateArea }) => {
|
export const ParameterPanel: React.FC<ParameterPanelProps> = ({ area, onUpdateArea }) => {
|
||||||
@ -84,6 +91,22 @@ export const ParameterPanel: React.FC<ParameterPanelProps> = ({ area, onUpdateAr
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 렌즈 효과 */}
|
||||||
|
<div className="parameter-group">
|
||||||
|
<label>
|
||||||
|
렌즈 효과: {((area.lensEffect?.strength ?? 0) > 0 ? '볼록 ' : (area.lensEffect?.strength ?? 0) < 0 ? '오목 ' : '')}{((area.lensEffect?.strength ?? 0) * 100).toFixed(0)}%
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="-1"
|
||||||
|
max="1"
|
||||||
|
step="0.01"
|
||||||
|
value={area.lensEffect?.strength ?? 0}
|
||||||
|
onChange={(e) => onUpdateArea({ lensEffect: { strength: parseFloat(e.target.value) } })}
|
||||||
|
className="slider"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 포인트 좌표 (읽기 전용 표시) */}
|
{/* 포인트 좌표 (읽기 전용 표시) */}
|
||||||
<div className="parameter-group">
|
<div className="parameter-group">
|
||||||
<label>포인트 좌표 (캔버스에서 드래그)</label>
|
<label>포인트 좌표 (캔버스에서 드래그)</label>
|
||||||
|
|||||||
@ -34,6 +34,7 @@ export class ThreeScene {
|
|||||||
u_numAreas: { value: 0 },
|
u_numAreas: { value: 0 },
|
||||||
u_dragVectors: { value: new Float32Array(16) }, // 8벡터 × 2(x,y)
|
u_dragVectors: { value: new Float32Array(16) }, // 8벡터 × 2(x,y)
|
||||||
u_distortionStrengths: { value: new Float32Array(8) },
|
u_distortionStrengths: { value: new Float32Array(8) },
|
||||||
|
u_lensEffects: { value: new Float32Array(8) },
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleResize();
|
this.handleResize();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ uniform vec2 u_points[32]; // 최대 8영역 × 4포인트 (정규화된
|
|||||||
uniform int u_numAreas;
|
uniform int u_numAreas;
|
||||||
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
uniform vec2 u_dragVectors[8]; // 드래그 벡터 (정규화된 좌표 0-1)
|
||||||
uniform float u_distortionStrengths[8];
|
uniform float u_distortionStrengths[8];
|
||||||
|
uniform float u_lensEffects[8];
|
||||||
|
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
|
|
||||||
@ -74,6 +75,15 @@ void main() {
|
|||||||
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
// dragVector는 정규화된 좌표(0-1)이므로 바로 사용
|
||||||
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
vec2 distortion = u_dragVectors[i] * influence * u_distortionStrengths[i];
|
||||||
texCoord += distortion;
|
texCoord += distortion;
|
||||||
|
|
||||||
|
// 렌즈 왜곡 효과 (방사형 UV 왜곡)
|
||||||
|
if (abs(u_lensEffects[i]) > 0.001) {
|
||||||
|
vec2 centered = uv_local - vec2(0.5);
|
||||||
|
float dist2 = dot(centered, centered);
|
||||||
|
float lensK = u_lensEffects[i] * 2.0; // 강도 스케일링
|
||||||
|
vec2 lensDistortion = centered * lensK * dist2;
|
||||||
|
texCoord += lensDistortion * u_distortionStrengths[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,14 @@ export type EasingFunction =
|
|||||||
| 'easeInQuad'
|
| 'easeInQuad'
|
||||||
| 'easeOutQuad'
|
| 'easeOutQuad'
|
||||||
| 'easeInCubic'
|
| 'easeInCubic'
|
||||||
| 'easeOutCubic';
|
| 'easeOutCubic'
|
||||||
|
| 'steps2'
|
||||||
|
| 'steps3'
|
||||||
|
| 'steps4'
|
||||||
|
| 'steps5'
|
||||||
|
| 'steps6'
|
||||||
|
| 'steps8'
|
||||||
|
| 'steps10';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 내장 모션 프리셋 타입
|
* 내장 모션 프리셋 타입
|
||||||
@ -92,6 +99,11 @@ export interface DistortionArea {
|
|||||||
influenceRadius: number;
|
influenceRadius: number;
|
||||||
maxStrength: number;
|
maxStrength: number;
|
||||||
};
|
};
|
||||||
|
/** 렌즈 효과 설정 (선택사항) */
|
||||||
|
lensEffect?: {
|
||||||
|
/** 렌즈 강도 (양수: 볼록, 음수: 오목, 0: 없음, 범위: -1.0 ~ 1.0) */
|
||||||
|
strength: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -17,6 +17,8 @@ export interface ShaderUniforms {
|
|||||||
u_dragVectors: THREE.IUniform<Float32Array>;
|
u_dragVectors: THREE.IUniform<Float32Array>;
|
||||||
/** 각 영역의 왜곡 강도 배열 */
|
/** 각 영역의 왜곡 강도 배열 */
|
||||||
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
u_distortionStrengths: THREE.IUniform<Float32Array>;
|
||||||
|
/** 각 영역의 렌즈 효과 강도 배열 */
|
||||||
|
u_lensEffects: THREE.IUniform<Float32Array>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -10,6 +10,8 @@ export const SHADER_CONFIG = {
|
|||||||
MAX_DRAG_VECTORS: 8,
|
MAX_DRAG_VECTORS: 8,
|
||||||
/** 최대 강도 배열 크기 */
|
/** 최대 강도 배열 크기 */
|
||||||
MAX_STRENGTHS: 8,
|
MAX_STRENGTHS: 8,
|
||||||
|
/** 최대 렌즈 효과 배열 크기 */
|
||||||
|
MAX_LENS_EFFECTS: 8,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,4 +38,6 @@ export const DEFAULT_AREA = {
|
|||||||
VECTOR_A: { x: 0.1, y: 0.1 },
|
VECTOR_A: { x: 0.1, y: 0.1 },
|
||||||
/** 기본 벡터 B */
|
/** 기본 벡터 B */
|
||||||
VECTOR_B: { x: -0.1, y: -0.1 },
|
VECTOR_B: { x: -0.1, y: -0.1 },
|
||||||
|
/** 기본 렌즈 효과 강도 */
|
||||||
|
LENS_STRENGTH: 0,
|
||||||
} as const;
|
} as const;
|
||||||
@ -2,6 +2,10 @@ import { type EasingFunction } from '../types';
|
|||||||
|
|
||||||
type EasingFunc = (t: number) => number;
|
type EasingFunc = (t: number) => number;
|
||||||
|
|
||||||
|
/** 스텝 이징 헬퍼: floor(t * n) / n → n단계로 양자화 */
|
||||||
|
const createStepEasing = (steps: number): EasingFunc =>
|
||||||
|
(t) => Math.floor(t * steps) / steps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 이징 함수 구현 맵
|
* 이징 함수 구현 맵
|
||||||
*/
|
*/
|
||||||
@ -17,6 +21,14 @@ const easingFunctions: Record<EasingFunction, EasingFunc> = {
|
|||||||
|
|
||||||
easeInCubic: (t) => t * t * t,
|
easeInCubic: (t) => t * t * t,
|
||||||
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
||||||
|
|
||||||
|
steps2: createStepEasing(2),
|
||||||
|
steps3: createStepEasing(3),
|
||||||
|
steps4: createStepEasing(4),
|
||||||
|
steps5: createStepEasing(5),
|
||||||
|
steps6: createStepEasing(6),
|
||||||
|
steps8: createStepEasing(8),
|
||||||
|
steps10: createStepEasing(10),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user