+ 요구한 역학·와류·블룸·셰이더를 구현 수준으로 제시했다.
- trailLength가 미사용이며 프레임 의존 감쇠값 설명이 부족하다.
마우스나 터치 상호작용 조건을 넣으면 생체발광 플랑크톤처럼 반응하는 입자 바다의 물리 파라미터와 GLSL 발광 셰이더를 요청합니다.
| 분류 | 개발 › 코딩 |
|---|---|
| 태그 | 초안작성분석개발자코드 |
I want you to act as a VFX Artist focused on bioluminescent fluid simulations and particle-based environmental effects. Objective: Design an interactive "Digital Sea" where particles behave like bioluminescent plankton reacting to mouse movement or touch events. Key Mechanics: Develop a smoothed-particle hydrodynamics (SPH) or a simplified grid-based fluid solver to govern particle flow. Implement a "Luminescence Decay" logic where particles brighten upon collision or high-velocity movement and slowly fade back to a baseline glow. Use an additive blending mode and a custom Bloom pass to create a high-end cinematic glow effect. Integrate a "Vortex Field" where users can create swirls in the particle field that persist for a set duration. Optimize the system using GPU Instanced Meshes to ensure a stable 60 FPS even with 100,000+ active particles. Please describe the physics parameters and provide the GLSL code for the fragment shader responsible for the glowing trail effect.
VFX Artist 역할로 인터랙티브 Digital Sea를 설계하게 하는 프롬프트다. SPH 또는 격자 유체, 발광 감쇠, vortex field, 100,000개 이상 입자 최적화를 포함한다.
ChatGPT가 가장 완결되고 구현 가능하다. Gemini는 연출은 풍부하지만 수치·셰이더 오류가 있으며 [C]는 누락됐다.
+ 요구한 역학·와류·블룸·셰이더를 구현 수준으로 제시했다.
- trailLength가 미사용이며 프레임 의존 감쇠값 설명이 부족하다.
+ GPU 파이프라인과 시각 연출을 구체적 수치로 잘 연결했다.
- 감쇠 시간 계산과 점성 단위가 부정확하고 실제 꼬리가 비대칭이 아니다.
| 기준 | ChatGPT | Gemini | 앞선 모델 |
|---|---|---|---|
| 지시 준수 | 10 | 8 | ChatGPT +25% |
| 정확성 | 8 | 6 | ChatGPT +33% |
| 구체성 | 9 | 9 | 동점 |
| 구성·가독성 | 9 | 9 | 동점 |
| 분량 적정성 | 8 | 7 | ChatGPT +14% |
gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-25). 측정값이 아니라 AI 심사 결과입니다.
같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.
100,000개 이상의 입자를 안정적으로 처리하려면 입자마다 SPH 이웃 탐색을 수행하기보다, 저해상도 Eulerian 속도 필드 + GPU 인스턴싱 입자 조합을 권장합니다.
구조는 다음과 같습니다.
const fluidParams = {
particleCount: 100000,
// 시뮬레이션 공간
gridWidth: 256,
gridHeight: 256,
worldWidth: 2.0,
worldHeight: 2.0,
// 유체
viscosity: 0.012,
velocityDamping: 0.985,
pressureStrength: 0.18,
curlStrength: 0.65,
advectionStrength: 1.0,
// 입력 반응
mouseForce: 2.8,
mouseRadius: 0.12,
inputSmoothing: 0.82,
// 입자
particleDrag: 0.985,
maxVelocity: 1.8,
particleSize: 0.006,
// 발광
baseLuminescence: 0.08,
collisionLuminescence: 1.4,
velocityLuminescence: 0.55,
luminescenceDecay: 0.92,
luminescenceResponse: 0.35,
// 와류
vortexStrength: 3.5,
vortexRadius: 0.22,
vortexLifetime: 2.8,
vortexDecay: 0.94,
// Bloom
bloomThreshold: 0.7,
bloomStrength: 1.25,
bloomRadius: 4.0
};
입자의 발광값은 다음과 같이 갱신할 수 있습니다.
luminescence =
max(
baseLuminescence,
luminescence * luminescenceDecay +
collisionAmount * collisionLuminescence +
velocityLength * velocityLuminescence
);
충돌은 화면 경계, 장애물 필드, 또는 주변 입자의 속도 차이를 기반으로 단순화할 수 있습니다.
float collisionAmount = clamp(
length(velocity - sampledFluidVelocity) * 0.5,
0.0,
1.0
);
사용자가 드래그하면 입력 위치에 다음 힘을 추가합니다.
vec2 offset = particlePosition - vortexPosition;
float distanceToVortex = length(offset);
float influence = 1.0 - smoothstep(0.0, vortexRadius, distanceToVortex);
vec2 tangent = vec2(-offset.y, offset.x);
velocity += normalize(tangent) *
vortexStrength *
influence *
deltaTime;
와류는 위치, 반경, 강도, 남은 시간을 가진 이벤트로 저장합니다.
{
position: vec2,
radius: 0.22,
strength: 3.5,
remaining: 2.8
}
매 프레임 다음과 같이 약화시킵니다.
vortex.strength *= 0.94;
vortex.remaining -= deltaTime;
아래 셰이더는 인스턴스화된 쿼드 하나를 입자 하나로 사용하는 방식입니다. vUv는 쿼드 좌표이며, vVelocity, vLuminescence, vLife는 인스턴스 버텍스 셰이더에서 전달됩니다.
#version 300 es
precision highp float;
in vec2 vUv;
in vec2 vVelocity;
in float vLuminescence;
in float vLife;
uniform vec3 uColor;
uniform float uTime;
uniform float uBloomThreshold;
layout(location = 0) out vec4 outColor;
float gaussian(float x, float sigma) {
return exp(-(x * x) / (2.0 * sigma * sigma));
}
void main() {
// 중심을 기준으로 한 쿼드 좌표
vec2 p = vUv * 2.0 - 1.0;
float speed = length(vVelocity);
vec2 direction = speed > 0.001
? normalize(vVelocity)
: vec2(1.0, 0.0);
vec2 normal = vec2(-direction.y, direction.x);
// 속도가 빠를수록 잔상이 길어짐
float trailLength = mix(0.35, 1.8, smoothstep(0.0, 1.5, speed));
float along = dot(p, direction);
float across = dot(p, normal);
// 진행 방향 뒤쪽으로 늘어진 꼬리
float trailStart = -0.95;
float trailEnd = 0.75;
float trailMask = smoothstep(trailStart - 0.15, trailStart, along) *
(1.0 - smoothstep(trailEnd, trailEnd + 0.15, along));
// 중앙은 밝고 외곽은 부드럽게 감쇠
float width = mix(0.34, 0.12, smoothstep(0.0, 1.5, speed));
float radialGlow = gaussian(across, width);
// 입자 머리 부분의 강한 핵
float head = exp(-length(p * vec2(1.0, 1.8)) * 5.0);
// 뒤로 갈수록 밝기가 약해지는 잔상
float tailFade = 1.0 - smoothstep(-0.95, 0.55, along);
float glow = trailMask *
radialGlow *
mix(0.45, 1.0, tailFade);
glow += head * 1.4;
// 생명주기와 발광량 반영
float intensity = glow *
max(vLuminescence, 0.05) *
mix(0.65, 1.0, vLife);
// 약간의 유기적 깜빡임
float flicker = 0.94 +
0.06 * sin(uTime * 8.0 + vLife * 23.0);
intensity *= flicker;
// HDR 값으로 출력해야 Bloom이 충분히 발생함
vec3 emissive = uColor * intensity * 3.5;
// 아주 약한 투명도 가장자리
float alpha = clamp(glow * vLuminescence * 1.5, 0.0, 1.0);
if (alpha < 0.01) {
discard;
}
outColor = vec4(emissive, alpha);
}
렌더 상태는 다음과 같이 설정합니다.
material.blending = THREE.AdditiveBlending;
material.transparent = true;
material.depthWrite = false;
material.toneMapped = false;
Bloom은 한 번에 강하게 블러하기보다 다음 단계가 안정적입니다.
HDR Scene
↓
Brightness Threshold
↓
Half Resolution Blur
↓
Quarter Resolution Blur
↓
Additive Composite
↓
Tone Mapping
Threshold fragment shader의 핵심은 다음과 같습니다.
vec3 color = texture(uScene, vUv).rgb;
float brightness = max(max(color.r, color.g), color.b);
float mask = smoothstep(
uThreshold,
uThreshold + 0.2,
brightness
);
outColor = vec4(color * mask, 1.0);
최종 합성:
vec3 scene = texture(uScene, vUv).rgb;
vec3 bloom = texture(uBloom, vUv).rgb;
vec3 finalColor = scene + bloom * uBloomStrength;
outColor = vec4(finalColor, 1.0);
RGBA32F 또는 적절한 정밀도의 텍스처에 저장InstancedMesh 또는 raw instanced buffer 사용depthWrite = false로 투명 입자 깊이 쓰기 비용 제거이 구성은 실제 SPH보다 근사도가 낮지만, 100,000~500,000개 입자 규모에서 인터랙티브한 생물발광 바다와 안정적인 성능을 얻기에 적합합니다.
| 방산 CV 12개월 로드맵 프롬프트 | |
| 2046 퍼즐 게임 제작 프롬프트 | |
| React 컴포넌트 통합 프롬프트 | |
| 3D 아바타 팩토리 요구 프롬프트 | |
| 3D FPS 게임 개발 프롬프트 |