기준 build: TouchDesigner 2025.31550 목적: TouchDesigner POP에서 익힌 개념이 OpenGL/Vulkan, Unity, Houdini, WebGPU/WGSL에서 어떤 이름으로 다시 등장하는지의 1:1 사전. 읽는 법: 각 행은 한 CG 개념. 셀이 비어 있으면
(없음)으로 표시하고 그 이유를 한 줄로 적었다. 본문(17장)과 일부 중복되지만 본 부록은 reference table 전용판이다.
본 부록은 핸드북 본문 18 챕터의 보조 자료이며, 학습자가 한 환경에서 다른 환경으로 옮길 때 가장 먼저 펼쳐 보는 페이지로 설계되었다. 본문 17장 "다른 환경으로 가져가기"가 같은 매핑을 산문 형태로 다룬다면, 본 부록은 reference table 형태로 압축한 판이다. 한 환경에서 익숙한 단어를 다른 환경의 동의어로 즉시 치환하는 것이 본 부록의 단일 목적이다.
본 부록은 세 부분으로 구성한다.
- 33개 핵심 개념의 5-환경 매핑 표. attribute·buffer·dispatch·workgroup·instancing 등 GPU 그래픽스 파이프라인의 추상화 33개를 다섯 환경의 이름으로 동시에 적는다.
- Terminology Collisions. 같은 단어가 환경마다 다른 것을 가리키는 경우. POP, vertex, attribute, buffer, particle system 등이 대표 사례다.
- TouchDesigner GLSL POP / GLSL Advanced POP / GLSL MAT 헬퍼 함수 cheat-sheet.
TDIndex(),TDNumElements(),TDIn_AttribName(),oTDPoint_AttribName[]등 TD 고유 함수의 verbatim 시그니처 목록.
본문에서 환경 약칭을 다음과 같이 쓴다.
- TD POP — TouchDesigner POP family (Point Operator). 본 핸드북의 학습 환경이며 GPU SSBO 위의 attribute 모델을 노드 그래프로 노출한다.
- GL/VK — OpenGL 4.x core profile + Vulkan 1.x. Khronos canonical 이름. 셰이더 단의 어휘는 GLSL 4.60 기준.
- Unity — Unity Compute Shader (HLSL) / DOTS (C# Burst-compiled). 같은 데이터 모델의 CPU 변형이 DOTS다. 본 부록은 두 경로를 같은 셀에 함께 적는다.
- Houdini — VEX (Attribute Wrangle SOP) + Houdini Geometry attribute model. VEX는 CPU/SIMD 또는 OpenCL 컴파일 경로 — GPU 컴퓨트 셰이더가 아니라는 점에 주의. GPU-native 개념의 셀은 자주 비어 있다.
- WebGPU — WebGPU API + WGSL 셰이딩 언어. 셰이더 단은 WGSL 스펙 (https://gpuweb.github.io/gpuweb/wgsl/) 기준.
본 부록의 사용법은 다음과 같다. 첫째, 매핑 표 (§1)를 한 번 통독해 환경별 어휘의 전체 형상을 파악한다. 둘째, Terminology Collisions (§2)를 통해 자주 발생하는 검색 함정을 피한다. 셋째, GLSL POP 셰이더를 직접 작성할 때 §3 cheat-sheet를 옆에 두고 함수 시그니처를 verbatim으로 복사해 사용한다. 모든 GLSL 코드 블록은 본 cheat-sheet의 함수만으로 구성되어 TouchDesigner에 그대로 붙여넣어 실행 가능하다.
1. 5-환경 핵심 개념 매핑
| # | 개념 | TD POP | OpenGL / Vulkan | Unity (Compute / DOTS / HLSL) | Houdini (VEX / SOP) | WebGPU / WGSL |
|---|---|---|---|---|---|---|
| 1 | Point attribute | Point class attribute (e.g. P, N, Cd). Attribute POP의 Point. GLSL POP attrclass = point. |
Per-vertex in 입력 (OpenGL의 "vertex"가 POP의 "point"에 해당). VBO + glVertexAttribPointer. |
ComputeBuffer<T> 한 요소. DOTS에서는 IComponentData 한 필드. HLSL StructuredBuffer<T>. |
point attribute. VEX @P, @N. attribpromote SOP의 point class. |
array<T> in var<storage> buffer. @builtin(vertex_index) 로 인덱스. |
| 2 | Vertex attribute (per-corner) | Vertex class attribute. Normal POP Type=Vertex가 만드는 per-corner normal이 대표. GLSL POP attrclass = vertex. |
Per-vertex 입력의 corner-별 사본. 별도 buffer는 드물고 EBO + 동일 VBO를 공유하는 게 일반적. | 명시적 표준 없음. Mesh.SetVertexBufferData로 per-corner 채널을 흉내. |
vertex attribute. VEX i@vtxnum, vertex() 함수. |
per-corner attribute는 보통 별도 storage buffer로 packed. @location(n)은 vertex stage in만 정의. |
| 3 | Primitive attribute | Primitive class attribute. Attribute POP Class=Primitive. GLSL POP attrclass = primitive. |
공식 표준 없음. flat qualifier로 첫 provoking vertex 값을 per-prim처럼 쓰거나 SSBO를 primitive id로 인덱스. |
별도 ComputeBuffer 또는 MaterialPropertyBlock 활용 (per-instance). |
primitive attribute (prim class). VEX prim(), primintrinsic(). |
Storage buffer를 primitive id로 인덱스. WGSL에는 per-prim 표준 입력 없음. |
| 4 | Detail / global attribute | (없음) — TD POP wiki에는 detail/global class 개념이 명시되지 않는다. Houdini의 detail attribute를 흉내내려면 1-element Point POP 또는 Temp Buffer를 uniform처럼 사용. | UBO (uniform) 또는 push constant. |
C# 스크립트의 변수 / cs.SetFloat(...). |
detail attribute (Houdini 고유). VEX f@_detailattr (단일 element). |
uniform buffer (var<uniform>). |
| 5 | Custom per-element attribute (user-defined) | Attribute POP New Attribute 블록 / GLSL POP Create Attribs 페이지에서 이름·타입·기본값 선언. |
layout(location=N) in T name (vertex stage) 또는 SSBO struct field. |
ComputeBuffer.SetData<T>(...), HLSL RWStructuredBuffer<T>. |
VEX type prefix 자동 선언: f@speed, v@vel, i@id, p@orient. |
@group(0) @binding(N) var<storage, read_write> name: array<T>. |
| 6 | Buffer (vertex / index / SSBO 일반) | 내부적으로는 모든 attribute가 SSBO. 사용자에게는 attribute로 추상화. Wiki verbatim: "Each attribute is a Shader Storage Buffer Object (SSBO)." | VBO (vertex), EBO/IBO (index), SSBO (storage), UBO (uniform). Vulkan은 모두 VkBuffer 단일 타입. |
ComputeBuffer, GraphicsBuffer. Mesh 내부에 vertex/index buffer. |
(직접 노출되지 않음) attribute → 내부 buffer. OpenCL Wrangle에서는 __global buffer 직접 다룸. |
GPUBuffer (단일 타입), usage flag로 vertex/index/storage/uniform 구분. |
| 7 | Read-write storage buffer | GLSL POP Output Access = readwrite (atomic 연산에 필수). 출력 어트리뷰트가 read-write SSBO가 됨. |
layout(std430, binding=N) buffer (qualifier 없음 = read-write); readonly / writeonly 한정자. |
HLSL RWStructuredBuffer<T>. |
OpenCL Wrangle: __global float*. VEX 자체는 attribute write 추상화. |
var<storage, read_write> name: array<T> + GPUBufferBindingType.storage. |
| 8 | Uniform / constant | GLSL POP의 Colors / Vectors / Matrices 페이지에서 선언한 uniform. Constants 페이지의 entry는 specialization constant. | uniform T name; (UBO std140) 또는 push constant (Vulkan). |
HLSL cbuffer 또는 cs.SetFloat/SetVector/.... |
VEX 자체 chf(), chv()로 채널 참조 (CHOP 유사). |
var<uniform> name: T; (@binding으로 UBO 슬롯 지정). |
| 9 | Texture sampler (2D) | GLSL POP Samplers 페이지: sampler0name + 소스 TOP + Extend U/V/W + Filter. 셰이더 측은 uniform sampler2D 자동 선언. |
uniform sampler2D tex; texture(tex, uv). Vulkan: VkSampler + VkImageView 분리. |
HLSL Texture2D tex; SamplerState s; tex.Sample(s, uv). |
VEX texture("op:/path", u, v). |
var t: texture_2d<f32>; var s: sampler; textureSample(t, s, uv). |
| 10 | Texture buffer (samplerBuffer) |
GLSL POP Arrays 페이지에서 array0arraytype = texturebuffer 선택. CHOP 한 채널이 packed 1D texture로 노출. |
GLSL samplerBuffer / uniform samplerBuffer name; texelFetch(name, i). Vulkan: VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER. |
HLSL Buffer<T> (typed buffer view). |
(직접 없음) — VEX의 1D 채널 참조는 CHOP API로 우회. | WGSL texture_storage_1d 또는 typed array<T> storage buffer로 대체. |
| 11 | Compute shader program | GLSL POP / GLSL Advanced POP의 compute DAT (computedat). |
GLSL #version 460 \n layout(local_size_x=...) in; + glCreateProgram. |
.compute 파일 + #pragma kernel CSMain (HLSL). |
(없음) — VEX는 CPU/SIMD 컴파일러. GPU 컴퓨트는 OpenCL Wrangle SOP만 제한적으로 제공. | WGSL @compute entry function + device.createComputePipeline. |
| 12 | Compute dispatch (launch) | GLSL POP의 Dispatch Size 파라미터 + Number of Threads 모드. 자동으로 launch. |
glDispatchCompute(x,y,z) / vkCmdDispatch. |
ComputeShader.Dispatch(kernel, x, y, z). |
(없음) — VEX는 element loop가 자동. OpenCL Wrangle은 1D auto-dispatch. | passEncoder.dispatchWorkgroups(x, y, z). |
| 13 | Workgroup | GLSL POP의 1 workgroup = 1 thread group. Default 크기는 NVIDIA 32, AMD 64 (wiki verbatim). | layout(local_size_x=...) in; 가 정의하는 thread group. Vulkan에서도 동일. |
HLSL [numthreads(x,y,z)]. SV: SV_GroupID. |
(없음) — OpenCL Wrangle만 work-group 개념 노출. | WGSL @workgroup_size(x,y,z). |
| 14 | Workgroup size | GLSL POP Work Group Size (x,y,z) 파라미터. Manual 모드에서만 사용자 지정. |
layout(local_size_x=X, local_size_y=Y, local_size_z=Z). |
[numthreads(X,Y,Z)]. |
(없음) | @workgroup_size(X, Y, Z). |
| 15 | Local invocation index | wiki 미확정 — TD wiki는 gl_LocalInvocationID / gl_LocalInvocationIndex 노출 여부를 명시하지 않는다. TDIndex()만 표준 인터페이스. |
gl_LocalInvocationID.xyz / gl_LocalInvocationIndex (uint). |
HLSL SV_GroupThreadID, SV_GroupIndex. |
(없음) | WGSL @builtin(local_invocation_id), @builtin(local_invocation_index). |
| 16 | Global invocation index | TDIndex() (uint, 1D). manual dispatch 모드에서는 undefined → 사용자가 직접 계산해야 함. |
gl_GlobalInvocationID.xyz. |
HLSL SV_DispatchThreadID (uint3). |
VEX @elemnum / @ptnum / @primnum / @vtxnum. |
WGSL @builtin(global_invocation_id) (vec3 |
| 17 | Element index (1D thread index) | TDIndex(). TDNumElements()로 총 개수. workgroup-rounded 초과 인덱스는 사용자가 bounds-check. |
보통 gl_GlobalInvocationID.x. |
id.x (SV_DispatchThreadID의 첫 컴포넌트). |
VEX @elemnum (Run Over 모드에 따른 통합 인덱스). |
gid.x (global_invocation_id.x). |
| 18 | Atomic operation | GLSL POP Output Access = readwrite 필수. GLSL 표준 atomic 함수 (atomicAdd 등) 사용 가능. |
GLSL atomicAdd(buf[i], v), atomicMin, atomicCounterIncrement (atomic counter 별도). |
HLSL InterlockedAdd(buf[i], v), InterlockedMin/Max/Or/And/Xor/Exchange/CompareExchange. |
(없음) — VEX는 element-parallel 모델이라 atomic 미지원. OpenCL Wrangle만 atomic_add 등 가능. |
WGSL atomicAdd(&buf[i], v) 등. atomic 타입 변수만 가능 (atomic<u32>). |
| 19 | Shared / group-shared memory | wiki 미확정 — TD GLSL POP wiki에 shared qualifier 사용 가능 여부 명시 없음. GLSL 4.30+ 컴퓨트라면 원칙적으로 가능. 실험으로 확인 필요. |
GLSL shared T name[N]; + barrier(). Vulkan workgroup memory 동일. |
HLSL groupshared T name[N]; + GroupMemoryBarrierWithGroupSync(). |
(없음) — VEX는 element-isolated. | WGSL var<workgroup> name: array<T, N>; + workgroupBarrier(). |
| 20 | Specialization constant | GLSL POP Constants 페이지 (const0name, const0value). 셰이더 컴파일 시점에 baked. |
GLSL layout(constant_id=N) const T name = default; (Vulkan SPIR-V). |
(직접 등가물 없음) — cs.SetInt 등 uniform 또는 multi_compile keyword variants. |
(없음) | WGSL override name: T = default;. |
| 21 | Multi-pass (same shader N times) | GLSL POP Passes (npasses) 파라미터. Advanced POP도 노출 (wiki에 충돌; 새 파라미터 페이지 우선). |
C++ 측에서 glDispatchCompute를 N회 + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT). |
C# 측에서 cs.Dispatch를 N회. 사이에 GraphicsFence 가능. |
SOP Solver / For-loop SOP / Iterate Wrangle. | 같은 encoder에서 dispatchWorkgroups를 N회. pass 분리 또는 barrier(). |
| 22 | Ping-pong feedback | Feedback POP (이전 프레임 출력 참조) + Cache POP. GLSL POP Copy Previous Pass Output to Input (prevpassoutput) 토글. |
두 SSBO (또는 두 텍스처) 바인딩을 매 프레임 swap. | ComputeBuffer 두 개, A→B, 다음 프레임 B→A. |
Solver SOP — 이전 프레임 출력이 자동으로 다음 입력. | 두 storage buffer 핑퐁; 매 프레임 bind group swap. |
| 23 | Instancing (per-instance attribute) | Geometry COMP에 POP을 instance 소스로 공급. POP의 point attribute가 per-instance 값. (15장 참조) | glVertexAttribDivisor(loc, 1) + glDrawArraysInstanced(...). |
Graphics.RenderMeshInstanced / DrawMeshInstancedProcedural / MaterialPropertyBlock. |
Copy to Points SOP (per-point instance), i@instance attribute. |
passEncoder.draw(vertexCount, instanceCount) + @builtin(instance_index). |
| 24 | Instance ID | GLSL MAT 측 TDInstanceID() (wiki: Write_a_GLSL_Material). 셰이더에서 instance 색·매트릭스를 얻을 때 사용. |
gl_InstanceID (정수). Vulkan gl_InstanceIndex. |
HLSL SV_InstanceID. |
(per-point instancing이라 명시적 ID 없음; ptnum이 대신). | WGSL @builtin(instance_index) : u32. |
| 25 | Indirect dispatch | GLSL POP Number of Threads = Number of Elements from Attribute 모드에서 자동 활성화. Wiki verbatim: "an indirect command buffer is filled, and the compute shader is launched with an indirect dispatch." |
glDispatchComputeIndirect(GLintptr) / vkCmdDispatchIndirect. |
ComputeShader.DispatchIndirect(kernel, argsBuffer, argsOffset). |
(없음) — VEX 외부에서 처리. | WGSL/WebGPU passEncoder.dispatchWorkgroupsIndirect(buffer, offset). |
| 26 | Spatial neighborhood query | Neighbor POP (k-NN), Proximity POP (radius). 또는 GLSL POP에서 uniform grid SSBO 직접 구현. | (스펙 표준 아님) 사용자 SSBO 기반 grid / BVH. 하드웨어 ray-tracing API 활용 가능. | DOTS KDTree, Compute Shader 기반 grid. |
VEX nearpoints(), pcfind(), xyzdist(), PointCloud 함수 제공 — 가장 풍부. |
(스펙 표준 아님) 사용자 storage buffer 기반 grid. |
| 27 | Sort primitive | Sort POP (P 또는 임의 attribute 기준; vector / proximity / Geo-COMP-axis 모드). | (없음 — 사용자 구현) bitonic / radix sort on SSBO. | (없음 — 사용자 구현) compute shader 기반 sort. | Sort SOP. VEX sort() array 함수. |
(없음 — 사용자 구현). |
| 28 | Reduction (sum / min / max / scan) | Analyze POP (avg / min / max를 1-point 출력). prefix sum은 사용자 구현 (Advanced POP + atomic 또는 multi-pass). | 컴퓨트 셰이더 사용자 구현. GPU Gems 3 Ch.39 (Harris scan). | ComputeBuffer + 사용자 컴퓨트. Burst에는 IJobParallelForReduce 등. |
VEX attrib promote (detail로 promote = reduce). |
컴퓨트 사용자 구현. |
| 29 | Material / shader-graph | TD MAT family (Phong MAT / Constant MAT / GLSL MAT). GLSL MAT은 셰이더 직접 작성, 일반 MAT은 visual graph. | (없음 — API에 visual graph 개념 없음) | Unity Shader Graph (URP/HRP), HLSL .shader 파일. |
Material SOP (rendering 패스). | (없음 — API에 visual graph 개념 없음) |
| 30 | Vertex shader stage input | GLSL MAT vertex shader에서 TDPos(), TDNormal(), TDTexCoord(uint), TDPointColor(), custom은 TDAttrib_<name>(). |
layout(location=N) in T name;. |
HLSL vertex shader의 appdata struct semantic (POSITION, NORMAL, TEXCOORD0, …). |
(벡스는 rendering이 아님 — Karma/Mantra 측 별도) | WGSL @vertex fn main(@location(N) name: T) -> .... |
| 31 | Fragment shader stage input | GLSL MAT pixel shader의 in block — vertex shader out이 rasterizer 보간 후 들어옴. |
layout(location=N) in T name; + (선택) flat / noperspective qualifier. |
HLSL fragment shader v2f struct. |
(외부 렌더러) | WGSL @fragment fn main(@location(N) name: T) -> .... |
| 32 | Render target / framebuffer | Render TOP의 출력 텍스처. Render TOP 자체가 framebuffer 추상화. | FBO (glGenFramebuffers + glFramebufferTexture2D). Vulkan VkFramebuffer. |
RenderTexture, CommandBuffer.SetRenderTarget. |
(외부 렌더러) | GPURenderPassEncoder의 color attachments. |
| 33 | Render pass | Render TOP cook 1회 = 1 render pass. Multiple pass는 multiple Render TOP. | (OpenGL은 명시적 render pass 없음; Vulkan은 VkRenderPass로 명시). |
CommandBuffer + BeginRenderPass 패턴. |
(외부) | commandEncoder.beginRenderPass({...}) ~ pass.end(). |
매핑 표에 대한 일반 주석
표의 각 행은 1:1 동치를 주장하지 않는다. 같은 슬롯에 들어가는 가장 가까운 개념의 환경별 이름이라는 의미다. 본 주석은 표를 읽을 때 자주 발생하는 오해를 사전에 차단한다.
TD POP 셀의 함수 이름 출처. TD POP 열에 적힌 모든 함수 이름은 §3 cheat-sheet의 verbatim 시그니처를 기준으로 한다. 즉 TDIndex(), TDNumElements(), TDIn_AttribName(), oTDPoint_AttribName[] 등은 TD wiki의 Write_a_GLSL_POP 페이지 문구 그대로다. 일반 GLSL의 gl_GlobalInvocationID나 gl_LocalInvocationID는 TD wiki에 노출 여부가 명시되지 않았으므로 본 표에서 TD POP 셀에는 적지 않았다. 노출 여부가 궁금하다면 manual dispatch 모드에서 실험으로 확인해야 한다.
Houdini VEX 셀이 자주 "(없음)"인 이유. VEX는 GPU 컴퓨트 셰이더가 아니라 CPU/SIMD 컴파일러다. workgroup, dispatch, atomic, shared memory, indirect dispatch 같은 GPU-native 개념은 VEX 어휘에 존재하지 않는다. Houdini에서 같은 개념을 다루려면 OpenCL Wrangle SOP를 사용해야 하며, 그 안에서는 GL/Vulkan과 동일한 워크그룹·atomic 어휘가 다시 등장한다. 반대로 attribute 모델·neighborhood query·attribute promotion 등 데이터 모델 차원의 개념은 Houdini가 가장 풍부한 어휘를 제공하므로 그 행에서는 Houdini 셀이 가장 두껍다.
Unity 셀에 DOTS를 함께 적은 이유. Unity는 같은 attribute 모델을 두 경로로 노출한다. GPU 경로는 Compute Shader(HLSL RWStructuredBuffer<T>)이고, CPU 경로는 DOTS(IComponentData + Burst-compiled IJobEntity)다. 두 경로의 데이터 레이아웃은 거의 같다. 본 표에서 Unity 셀이 GPU 경로 위주로 쓰여 있지만, CPU 측 등가물은 DOTS에서 찾을 수 있음을 명시적으로 적어둔다. POP에서 익힌 dispatch 직관이 DOTS의 IJobParallelFor로 직접 옮겨간다.
WebGPU 셀이 "(없음)"인 항목들. WebGPU는 비교적 새 API이고, render pass·compute pipeline·storage buffer 같은 기본 추상화는 모두 명시적이지만, sort·reduce·neighborhood query 같은 상위 알고리즘은 표준 라이브러리가 아직 없다. 따라서 WebGPU 셀이 "(없음 — 사용자 구현)"인 행은 "이 환경에서는 직접 짜야 한다"는 의미다. WebGPU Fundamentals 같은 학습 사이트들이 그 빈자리를 메우고 있다.
"wiki 미확정" 표시. TouchDesigner wiki가 해당 기능의 노출 여부 또는 정확한 시그니처를 명시하지 않은 경우다. Local invocation index, shared memory, Advanced POP의 Collisions 페이지 등이 여기 해당한다. 본 부록의 §3 cheat-sheet에도 같은 표시가 일부 항목에 붙어 있다. 출판 직전 build 2025.31550 또는 이후 build에서 실험으로 재확인해야 한다.
OpenGL과 Vulkan을 한 셀에 합친 이유. 셰이더 단의 어휘는 GLSL 4.60 (OpenGL) 와 SPIR-V (Vulkan) 사이에서 거의 동일하다. API 단의 dispatch·buffer 바인딩·render pass 추상화에서만 차이가 크게 난다. 본 표는 셰이더 어휘 기준이므로 두 API를 한 셀에 합쳤다. API 단의 정밀한 차이는 Khronos 문서를 보아야 한다.
환경 간 "같은 개념, 다른 단어" 의 일반 규칙. 같은 컴퓨트 모델을 다섯 환경이 다섯 단어로 부른다는 사실이 본 부록의 출발점이다. 한 환경에서 익힌 직관을 다른 환경으로 옮길 때, 가장 먼저 해야 할 일은 "내가 익숙한 단어가 새 환경에서 어떤 단어로 바뀌는가"를 표에서 확인하는 것이다. 그 뒤에야 새 환경의 API quirk를 다룬다. 단어 매핑을 먼저 잡아 두지 않으면 같은 개념을 두 번 배우는 비효율이 생긴다.
2. Terminology Collisions — 같은 단어가 환경마다 다른 것
본 절은 research/03_theory_mapping.md의 Terminology Collisions 섹션을 verbatim 인용하고, 본 부록 분량에 맞춰 확장한다. 검색 시점에 가장 자주 헷갈리는 충돌만 다룬다.
용어 충돌은 단순히 학습자의 혼란이 아니라 검색 행동의 함정이다. 한 환경에서 익힌 단어를 다른 환경의 문서에 그대로 검색하면, 같은 글자가 가리키는 전혀 다른 시스템의 문서가 나온다. 이 절은 그런 검색 함정을 사전에 차단하는 용도로 쓴다. 본 핸드북의 각 챕터는 충돌이 처음 등장하는 자리에서 한 번 언급하지만, 본 부록은 reference 용도로 한자리에 모아둔다.
2.1 POP
- TouchDesigner POP: Point Operator. 2025.x에 도입된 GPU-resident operator family. 3D geometry + 임의 numeric data. 본 핸드북이 다루는 그것.
- Houdini POP (legacy): Particle Operators. Houdini 초기 입자 시스템. 현재 단종, DOP-network 입자로 대체 (https://www.sidefx.com/docs/houdini/dopparticles/index.html). 현행 Houdini 문서에서 "POP"을 검색하면 거의 항상 이쪽이 나온다.
- 둘은 전혀 무관하다. 약자 충돌이 가장 큰 검색 함정.
본 핸드북에서 "POP"은 항상 TouchDesigner Point Operator를 가리킨다. SideFX 문서를 참조할 일이 있다면 "POP"이라는 단어 자체가 다른 시스템을 가리킨다는 사실을 먼저 인지하고 들어가야 한다. 특히 Houdini의 입자 시스템 자료를 찾는다면 검색어는 "POP"이 아니라 "DOP particles" 또는 "Particle DOP"가 정답이다. 본 핸드북의 10장 (입자 시뮬레이션)이 다루는 POP-based 입자 시스템과 Houdini 입자 시스템은 데이터 모델 차원에서는 비슷하지만 (둘 다 point에 velocity·age·mass attribute를 두는 attribute-update 루프), 구현 환경과 노드 이름은 전혀 다르다.
2.2 Compute shader / kernel / shader graph node
- Compute shader: OpenGL / Vulkan / D3D11+ / Metal / WebGPU의 GPU 컴퓨트 프로그램. 같은 개념, 같은 이름.
- Kernel: CUDA, OpenCL이 같은 개념을 부르는 이름. Houdini OpenCL Wrangle SOP의 코드도 kernel.
- Shader graph node: Unity Shader Graph, Unreal Material Editor, TouchDesigner GLSL 노드. 셰이더 자체가 아니라 셰이더로 컴파일되는 visual graph. 다른 추상화 계층.
이 셋을 같은 평면에 두지 말 것. graph는 source, kernel/compute shader는 product. 즉 graph 노드를 편집하면 컴파일 결과로 셰이더가 만들어진다. 셰이더는 GPU에서 실행되는 코드 그 자체이지만, graph는 그 코드를 생성하는 도구다. 본 핸드북의 GLSL POP은 graph가 아니라 셰이더를 직접 작성하는 환경이며, TouchDesigner의 일반 MAT 노드들 (Phong MAT, Constant MAT) 은 그래프 측에 해당한다. 14장에서 다루듯, Phong MAT은 GLSL MAT을 TD가 자동 생성한 결과로 볼 수 있다.
2.3 Vertex
- TD POP vertex: primitive의 한 corner에 붙은 per-corner 레코드. Houdini의 vertex와 동일 의미. 예를 들어 한 점이 세 개의 삼각형에 공유되어 있다면 POP에서는 한 point + 세 vertex로 표현된다.
- OpenGL vertex: 보통 TD POP의 point에 해당. VBO의 한 entry가 한 vertex. corner-별 데이터가 필요하면 같은 point를 index buffer로 여러 번 참조하면서 attribute는 그대로 공유한다.
- Shader stage "vertex shader": 두 의미와 또 다름 — pipeline stage 이름. raster pipeline에서 가장 먼저 실행되는 셰이더로, 한 vertex (OpenGL 의미) 당 한 번 실행된다.
같은 단어가 세 가지 메모리 위치를 가리킨다. 본 핸드북은 vertex를 항상 TD POP 의미 (per-corner record) 로만 쓴다. Ch.2의 attribute model이 이 분리를 명시적으로 다루며, Normal POP의 Type = Vertex 옵션이 per-corner normal을 만드는 경로다. OpenGL/LearnOpenGL/RTR4 자료를 참조할 때는 "vertex"가 POP의 "point"를 의미한다는 점을 항상 머릿속에서 치환해 읽어야 한다.
2.4 Attribute
- GLSL
attribute/in(vertex stage): per-vertex 입력 변수. OpenGL 3.x에서attribute키워드는 deprecated,inqualifier로 대체. - POP attribute: Point / Vertex / Primitive / (Houdini의) Detail 어디에든 살 수 있는 named per-element value. GLSL POP wiki verbatim: "Each attribute is a Shader Storage Buffer Object (SSBO)."
- Houdini attribute: POP과 같은 의미 (Houdini가 원조 모델).
- Unity attribute: 보통 mesh data channel (Position, Normal, UV0, …)를 지칭. 또는 C# property attribute (다른 의미).
둘은 겹치지만 같지 않다. POP attribute는 셰이더 stage에 들어가기 직전까지 SSBO다. raster pipeline에 진입할 때 GLSL MAT의 vertex shader가 TDPos() / TDNormal() 등의 헬퍼를 통해 그 SSBO를 읽고 vertex stage in 변수로 옮긴다. 즉 두 의미는 "셰이더에 들어가기 전" 의 attribute와 "셰이더 안에서의 입력 변수" 의 attribute다. 같은 데이터가 두 위치를 차례로 거치므로 같은 단어가 쓰이지만, 추상화 계층은 다르다. Ch.14가 이 흐름을 다이어그램으로 보여준다.
2.5 Buffer
- GL/WebGPU buffer: VBO·EBO·IBO·SSBO·UBO·storage·uniform·vertex·index 등 typed memory의 통칭. Vulkan에서는 모두 단일
VkBuffer타입이고 usage flag로 구분한다. - TouchDesigner 일상 어휘 "buffer": 흔히 render target / framebuffer / TOP 텍스처를 의미. "이미지를 buffer에 그린다"는 표현이 그것.
- Unity buffer:
ComputeBuffer/GraphicsBuffer— GL/WebGPU 의미와 같음.
Ch.4의 "텍스처와 vertex buffer는 같은 GPU 메모리다"라는 명제는 이 구분을 분리하지 않으면 성립하지 않는다. TouchDesigner 일상 어휘의 "buffer"가 GL 어휘의 "framebuffer"와 같고, GL 어휘의 "buffer"는 TD에서 attribute SSBO·texture·constant buffer 모두에 해당한다. 본 핸드북은 "buffer"라는 단어가 등장할 때마다 어느 의미인지 문맥으로 표시한다 — GLSL POP 출력 SSBO를 "buffer"라 부르는 경우와 Render TOP 출력을 "buffer"라 부르는 경우가 같은 단락에서 등장한다면 명시적으로 풀어 쓴다.
2.6 Particle system
- Houdini particle system: 현재는 DOP-network 솔버. 과거는 legacy POPs.
- Unreal particle system: Niagara (modern) 또는 Cascade (legacy).
- TouchDesigner particle system:
- Particle SOP (CPU, legacy).
- Particle GPU TOP (GPU 텍스처 기반).
- POP-based particle simulation (본 핸드북 10장 — Particle POP + Feedback POP 또는 GLSL POP 직접 작성).
- 같은 표현이 네 가지 구현을 가리킨다. 본 핸드북에서 "particle"은 마지막 의미.
TouchDesigner 안에서도 "particle"이 세 구현 (Particle SOP / Particle GPU TOP / POP-based) 을 동시에 가리킬 수 있다는 점이 특히 까다롭다. 같은 프로젝트에서 세 구현 중 둘을 함께 쓰는 일도 가능하다 — Particle GPU TOP으로 만든 입자 위치를 TOP→POP을 거쳐 GLSL POP에서 후속 처리하는 식이다. 본 핸드북의 10장이 POP-based 경로를 가르치는 이유는 그것이 GPU compute의 가장 자연스러운 표현이고 attribute 모델과 일관되기 때문이다. 다른 두 구현이 잘못된 것은 아니다 — 각각 다른 시점에 설계된 서로 다른 추상화일 뿐이다.
2.7 부수 충돌 (참고)
- "Pass": GLSL POP의
npasses(compute dispatch 반복 횟수) vs render pass (raster pipeline 단위) vs material pass (Unity ShaderLabPass {}블록). 같은 한 글자가 셋 다 다른 단위를 가리킨다. compute pass는 사용자가 셰이더 한 줄을 반복 실행하는 단위, render pass는 한 번의 framebuffer 출력을 만드는 단위, material pass는 한 mesh를 여러 셰이더로 그릴 때의 단위다. - "Custom": GLSL MAT의 Custom Attributes (vertex stage 입력 추가) vs Niagara Custom Attribute (particle scope 변수) vs Houdini
i@custom(VEX 자동 선언). 모두 "사용자가 정의한 attribute"라는 같은 의도이지만, 선언 방식·범위·메모리 위치가 환경마다 다르다. - "Cache": TD Cache POP (시간축 N 프레임 보관) vs Houdini File Cache SOP (디스크 캐시) vs GPU L1/L2 cache (하드웨어 캐시). 같은 단어, 세 가지 시간 척도 — 프레임, 디스크 세션, 나노초.
- "Instance": GL
glDrawArraysInstanced(한 mesh를 N번 그리기) vs JavaScriptclass instance(객체 인스턴스) vs Unity prefabInstantiate(씬 위 사본). GPU 어휘에서 instance는 항상 첫 번째 의미. - "Sampler": GLSL
sampler2D(텍스처 + 필터링 상태 묶음) vs VulkanVkSampler(필터링 상태만; 텍스처와 분리) vs WGSLsampler(Vulkan과 동일하게 분리). 같은 단어가 환경에 따라 묶임/분리됨. - "Stage": shader stage (vertex / fragment / compute) vs Niagara Simulation Stage (한 emitter의 compute pass 단계) vs pipeline stage (rasterizer 등 fixed-function 포함). compute 맥락에서 "stage"가 등장하면 두 번째 의미일 가능성이 높다.
3. TouchDesigner GLSL 헬퍼 함수 cheat-sheet
본 절은 research/02_chapter_briefs/glsl_pop_deep.md의 verbatim 인용을 그대로 옮긴다. 핸드북 본문 각 챕터에서 이 cheat-sheet를 가리킨다. 일반 GLSL의 gl_GlobalInvocationID는 TD wiki가 명시하지 않으므로 사용하지 않는다 — TDIndex()를 쓴다.
TouchDesigner는 GLSL 컴퓨트 셰이더의 raw 인덱싱 API를 자체 헬퍼 함수로 한 번 감싼다. 이 감싸기의 두 가지 의도가 있다. 첫째, dispatch 모드를 사용자 파라미터로 자동 선택하면서 셰이더 코드는 바뀌지 않게 한다 — Auto / Manual / Indirect 등 어느 모드든 TDIndex() 한 줄이면 된다. 둘째, attribute 단의 SSBO 바인딩을 셰이더 코드 안에 직접 적지 않게 한다 — TDIn_P() 한 줄로 input 0의 P를 읽고, P[id] = ... 한 줄로 출력 SSBO에 쓴다. 결과적으로 TD-flavored compute shader는 일반 GLSL 컴퓨트보다 훨씬 짧지만, 그 짧음의 대가로 명시적 인터페이스 일부가 감춰진다. 본 절은 그 인터페이스의 verbatim 시그니처를 한자리에 모아둔다.
본 절을 읽는 순서는 indexing → element count → input read → output write → 부수 함수다. 모든 컴퓨트 셰이더는 indexing + bounds-check + input read + output write 네 단계를 거치며, 이 순서가 §3.1부터 §3.7까지의 배열과 일치한다. §3.8 이후는 특수 용도 (cache, array attribute, noise, extra output, GLSL MAT 등) 의 헬퍼다.
3.1 Indexing — 모든 GLSL POP의 공통 진입점
uint TDIndex();
// 1d index for current thread.
// undefined when number of threads is manual.
uint TDNumElements();
// number of requested threads based on dispatch mode and number of threads mode.
// actual number of threads is ceil to workgroup size (32 on NVIDIA, 64 on AMD).
// undefined when number of threads is manual.
필수 관용구 (모든 컴퓨트 셰이더의 본문 첫 두 줄):
const uint id = TDIndex();
if (id >= TDNumElements()) return;
wiki verbatim: "The if condition prevents the shader to write outside of the bounds of the allocated SSBO, which can lead to unpredictible results and crashes."
3.2 입력 요소 개수 (Input element counts)
GLSL POP / Advanced POP 공통:
uint TDInputNumPoints(uint inputIndex); // number of points in inputIndex input
uint TDInputNumPrims (uint inputIndex); // number of prims in inputIndex input
uint TDInputNumVerts (uint inputIndex); // number of verts in inputIndex input
// returns 0 if input doesn't exist
// 인자 생략 시 input 0:
TDInputNumPoints() = TDInputNumPoints(0);
TDInputNumPrims() = TDInputNumPrims(0);
TDInputNumVerts() = TDInputNumVerts(0);
GLSL POP 전용 (선택된 attribute class에 따라 자동 분기):
uint TDInputNumElements();
// wrapper for TDInputNumPoints() / TDInputNumPrims() / TDInputNumVerts()
// depending on attribute class.
3.3 Attribute 읽기 — GLSL POP
선택된 class와 같은 class의 attribute:
attribType TDIn_AttribName(uint inputIndex, uint elementId, uint arrayIndex);
// 인자 생략 시: TDIn_AttribName() = TDIn_AttribName(0, TDIndex(), 0);
// arrayIndex 생략 시: TDIn_AttribName(inputIndex, elementId) = TDIn_AttribName(inputIndex, elementId, 0);
// bounds-checked — out-of-range는 마지막 element/arrayIndex 반환.
선택된 class와 다른 class의 attribute (POP만; Advanced POP은 모든 class에 prefix를 강제):
attribType TDInPoint_AttribName(uint inputIndex, uint pointId, uint arrayIndex);
attribType TDInVert_AttribName (uint inputIndex, uint vertId, uint arrayIndex);
attribType TDInPrim_AttribName (uint inputIndex, uint primId, uint arrayIndex);
3.4 Attribute 읽기 — GLSL Advanced POP
모든 class에 prefix 강제:
attribType TDInPoint_AttribName(uint inputIndex, uint pointId, uint arrayIndex);
attribType TDInVert_AttribName (uint inputIndex, uint vertId, uint arrayIndex);
attribType TDInPrim_AttribName (uint inputIndex, uint primId, uint arrayIndex);
3.5 Cache POP 읽기 (시간축 보관)
GLSL POP:
attribType TDInCache_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
GLSL Advanced POP (class prefix 포함):
attribType TDInCachePoint_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCacheVert_AttribName (uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCachePrim_AttribName (uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
3.6 출력 쓰기 — GLSL POP
GLSL POP의 출력은 함수가 아니라 배열 변수다. 이 설계의 이유는 atomic 연산 호환성이다. GLSL의 atomicAdd(mem, data) 같은 함수는 첫 인자로 메모리 위치 참조를 받는데, 함수 호출 결과는 rvalue라서 atomic의 lvalue 인자로 쓸 수 없다. TouchDesigner는 이 한계 때문에 출력을 AttribName[id] = ... 형태의 배열 변수로 노출한다.
attribType AttribName[];
// 함수가 아니라 배열 변수 — atomicAdd 등 atomic 함수에 직접 넘길 수 있다.
대표 사용:
void main() {
const uint id = TDIndex();
if (id >= TDNumElements()) return;
P[id] = TDIn_P();
}
wiki note: "For P[id] = TDIn_P(); to compile without error, P needs to be present in the input, and selected for writing in 'Output Attributes'."
3.7 출력 쓰기 — GLSL Advanced POP
class prefix 강제:
attribType oTDPoint_AttribName[];
attribType oTDVert_AttribName [];
attribType oTDPrim_AttribName [];
대표 사용:
void main() {
const uint id = TDIndex();
if (id >= TDNumElements()) return;
oTDPoint_P[id] = TDInPoint_P();
}
3.8 Index buffer
읽기 (POP 공통):
uint TDInputPointIndex(uint inputIndex, uint vertIndex);
uint TDInputPointIndex(uint vertIndex) = TDInputPointIndex(0, vertIndex);
// bounds-checked.
쓰기 (Advanced POP 전용 — Max Primitives 파라미터를 custom으로 설정한 경우만 활성):
uint I[];
3.9 Array attribute 크기 상수
GLSL POP:
const uint cTDArraySize_AttribName;
GLSL Advanced POP (class별 분리):
const uint cTDArraySizePoint_AttribName;
const uint cTDArraySizeVert_AttribName;
const uint cTDArraySizePrim_AttribName;
3.10 Built-in noise
float TDSimplexNoise(vec3 p);
// GLSL POP의 TDSimplexNoise() 파라미터 메뉴로
// performance vs quality 모드 선택 가능.
3.11 Extra Output (Advanced POP 전용)
GLSL Select POP이 picks하는 추가 출력 통로. 각 extra-output 블록의 사용자 지정 이름을 OutputName이라 할 때:
// 입력 element 개수:
uint TDInputNumPoints_OutputName();
uint TDInputNumPrims_OutputName();
uint TDInputNumVerts_OutputName();
// 입력 attribute 읽기 (inputIndex 인자 없음 — extra output당 source POP 하나):
attribType TDInPoint_OutputName_AttribName(uint pointId, uint arrayIndex);
attribType TDInVert_OutputName_AttribName (uint vertId, uint arrayIndex);
attribType TDInPrim_OutputName_AttribName (uint primId, uint arrayIndex);
// 출력 쓰기:
attribType oTDPoint_OutputName_AttribName[];
attribType oTDVert_OutputName_AttribName [];
attribType oTDPrim_OutputName_AttribName [];
// Array size 상수:
const uint cTDArraySizePoint_OutputName_AttribName;
const uint cTDArraySizeVert_OutputName_AttribName;
const uint cTDArraySizePrim_OutputName_AttribName;
// Index buffer 접근:
uint TDInputPointIndex_OutputName(uint vertIndex);
// wiki에 "TDInputPointIndex_OuputName" 오탈자 그대로 — 실제 함수명은 정정될 수 있다 (실험 필요).
Dimension 헬퍼 (extra output 단위):
const uint cTDDimSize_OutputName;
uint[cTDDimSize_OutputName] TDDimension_OutputName();
uint[cTDDimSize_OutputName] TDDimCoords_OutputName(uint pointIndex);
uint TDDimPointIndex_OutputName(uint[cTDDimSize_OutputName] coords);
3.12 GLSL MAT 측 (14장 참조)
POP attribute를 vertex shader에서 받기 위한 헬퍼. 14장 hands-on에서 verified.
// 위치·법선·UV·점 색 (built-in attribute 접근자)
vec4 TDPos(); // POP P를 vec4(P.xyz, 1.0)로
vec3 TDNormal(); // POP N
vec3 TDTexCoord(uint i);// POP Tex (i번째 UV set)
vec4 TDPointColor(); // POP Cd
// 사용자 정의 attribute (GLSL MAT의 Attributes 페이지에 이름+타입 선언 후)
T TDAttrib_AttribName();
// 예: TDAttrib_vel() — Type vec3로 선언된 vel attribute를 vertex shader에서 읽음.
// POP element-단위 직접 접근 (vertex stage가 아닌 임의 인덱스로 buffer를 읽고 싶을 때)
T TDBuffer_AttribName(uint elementIndex, uint arrayIndex);
// wiki: Write_a_GLSL_Material — "POP attribute access".
// Instancing
uint TDInstanceID(); // 현재 instance index.
mat4 TDInstanceMat(); // per-instance 변환 매트릭스.
vec4 TDInstanceColor(vec4 def); // per-instance 색 (없으면 default).
T TDInstanceCustomAttrib0(); // Geometry COMP의 Instancing 페이지 Custom Attrib 0..3.
T TDInstanceCustomAttrib1();
T TDInstanceCustomAttrib2();
T TDInstanceCustomAttrib3();
// 변환 헬퍼
vec4 TDDeform(vec4 pos); // SOP/POP-space → world-space (instancing/skin 포함).
vec3 TDDeformNorm(vec3 n); // 법선의 world 변환.
vec4 TDWorldToProj(vec4 worldPos); // world → clip-space.
// Fragment 출력 swizzle
vec4 TDOutputSwizzle(vec4 col); // 출력 텍스처 채널 순서 보정.
// Camera matrix uniform
uniform TDMatrix uTDMats[TD_NUM_CAMERAS];
// stereo / multi-camera 렌더 대응. 일반 단일 카메라는 uTDMats[0] 사용.
주의 (wiki 미확정 — 실험 필요): TDAttrib_<name>() / TDBuffer_<name>() / TDInstanceCustomAttribN() 의 시그니처는 Write_a_GLSL_Material 페이지를 1차 출처로 한다. 본 부록은 verbatim 인용을 보장하지 않는 항목이 있다 (14장 hands-on에서 사용된 형태에 한해 검증됨).
3.13 표 — 어디서 무엇을 쓰는가
| 컨텍스트 | Element index | Element count | 입력 read | 출력 write | 인덱스 버퍼 read |
|---|---|---|---|---|---|
| GLSL POP | TDIndex() |
TDNumElements() / TDInputNumElements() |
TDIn_AttribName() (selected class) / TDInPoint_/TDInVert_/TDInPrim_AttribName() (other classes) |
AttribName[id] |
TDInputPointIndex(vertIndex) |
| GLSL Advanced POP | TDIndex() |
TDNumElements() |
TDInPoint_/TDInVert_/TDInPrim_AttribName() |
oTDPoint_/oTDVert_/oTDPrim_AttribName[id] |
TDInputPointIndex(vertIndex) |
| Advanced POP Extra Output | TDIndex() |
TDInputNumPoints_OutputName() 등 |
TDInPoint_OutputName_AttribName() 등 |
oTDPoint_OutputName_AttribName[id] 등 |
TDInputPointIndex_OutputName(vertIndex) |
| GLSL MAT vertex shader | (per-vertex stage; index는 gl_VertexID) |
(mesh이 결정) | TDPos() / TDNormal() / TDAttrib_<name>() / TDBuffer_<name>(i,a) |
gl_Position = TDWorldToProj(...); out block |
n/a (raster pipeline) |
| GLSL MAT fragment shader | n/a (per-fragment) | n/a | in block (vertex shader out의 보간) |
fragColor = TDOutputSwizzle(...) |
n/a |
4. 출처 (Sources, 본 부록에 한정)
- TouchDesigner Wiki —
POP,GLSL POP,GLSL Advanced POP,Write a GLSL POP,Write a GLSL Material,Compute Shader. 핸드북 reference build 2025.31550 기준. (research/02_chapter_briefs/glsl_pop_deep.md 인용) - Khronos OpenGL wiki —
Compute Shader,Buffer Object,Vertex Specification. - Unity Manual —
Compute shaders,Entities(DOTS),Burst compiler. - Houdini Docs —
VEX,Geometry attributes,Attribute PromoteSOP,Particles (DOP). - WebGPU spec (https://gpuweb.github.io/gpuweb/), WGSL spec (https://gpuweb.github.io/gpuweb/wgsl/), WebGPU Fundamentals.
- research/03_theory_mapping.md — Terminology Collisions 섹션.
유지보수 메모: TouchDesigner wiki의 파라미터 페이지는 footer에
wikieditor2025.30000이 적혀 있어 핸드북 reference build 2025.31550보다 약간 뒤처질 수 있다. 새 build에서 신규 helper 함수가 추가될 가능성이 있으므로 출판 직전 §3 cheat-sheet의 시그니처를 재확인해야 한다.
5. 본 부록의 한 줄 명제
같은 GPU 컴퓨트 모델을 다섯 환경이 다섯 단어로 부른다. 한 번 익힌 추상화는 단어만 바꾸면 그대로 다른 환경에서 동작한다. 본 부록은 그 단어 사전이다.
본문 17장 (Ch.17) 의 메타 명제 — "POP에서 손에 익은 dispatch·SSBO·attribute·ping-pong·instancing은 환경이 바뀌어도 이름만 바뀐다" — 의 reference table 판이다. 17장이 산문으로 풀어 쓴 매핑을 본 부록이 표 한 장으로 압축했다. 두 자료를 함께 쓰는 것이 권장된다 — 17장으로 흐름을 잡고, 본 부록으로 정확한 시그니처를 확인한다.
학습자가 본 부록을 가장 자주 펼치는 시점은 새 환경에 처음 들어갈 때다. Unity Compute Shader 문서의 첫 페이지를 읽으면서 [numthreads]가 GLSL POP의 무엇에 해당하는지 즉시 알고 싶을 때, WGSL 스펙의 @workgroup_size가 같은 것임을 즉시 알고 싶을 때, Houdini Attribute Wrangle의 @P가 TDIn_P()와 같음을 즉시 알고 싶을 때 — 이 모든 시점에 본 부록의 §1 매핑 표가 답을 준다. 새 환경의 API quirk를 깊이 파기 전에 단어 매핑을 먼저 잡아두면 학습 시간이 절약된다.