diff --git a/comfyui_embedded_docs/docs/GLSLShader/ar.md b/comfyui_embedded_docs/docs/GLSLShader/ar.md index 7002476e..18fe82bf 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/ar.md +++ b/comfyui_embedded_docs/docs/GLSLShader/ar.md @@ -1,38 +1,298 @@ -> تم إنشاء هذه الوثيقة بواسطة الذكاء الاصطناعي. إذا وجدت أي أخطاء أو لديك اقتراحات للتحسين، فلا تتردد في المساهمة! [تحرير على GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ar.md) +> تم إنشاء هذه الوثائق بواسطة الذكاء الاصطناعي. إذا وجدت أي أخطاء أو لديك اقتراحات للتحسين، فلا تتردد في المساهمة! [تعديل على GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ar.md) -# عقدة تظليل GLSL +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. -تطبق عقدة تظليل GLSL كود تظليل أجزاء GLSL ES مخصص على الصور المدخلة. تتيح لك كتابة برامج تظليل يمكنها معالجة صور متعددة وقبول معاملات موحدة (أعداد عشرية، أعداد صحيحة، قيم منطقية، ومنحنيات) لإنشاء تأثيرات بصرية معقدة. يمكن تحديد حجم الإخراج بواسطة أول صورة مدخلة أو تعيينه يدويًا. + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + -## المدخلات +## Minimal Shader -| المعامل | نوع البيانات | إلزامي | النطاق | الوصف | -|---------|---------------|--------|---------|-------------| -| `fragment_shader` | STRING | نعم | غير متاح | كود مصدر تظليل الأجزاء GLSL (متوافق مع GLSL ES 3.00 / WebGL 2.0). الافتراضي: تظليل أساسي يخرج أول صورة مدخلة. | -| `size_mode` | COMBO | نعم | `"from_input"`
`"custom"` | حجم الإخراج: 'from_input' يستخدم أبعاد أول صورة مدخلة، 'custom' يسمح بتعيين الحجم يدويًا. | -| `width` | INT | لا | 1 إلى 16384 | عرض الصورة الناتجة عندما يكون `size_mode` مضبوطًا على `"custom"`. الافتراضي: 512. | -| `height` | INT | لا | 1 إلى 16384 | ارتفاع الصورة الناتجة عندما يكون `size_mode` مضبوطًا على `"custom"`. الافتراضي: 512. | -| `images` | IMAGE | نعم | 1 إلى 8 صور | الصور المدخلة المراد معالجتها بواسطة التظليل. تتوفر الصور كـ `u_image0` إلى `u_image7` (sampler2D) في كود التظليل. | -| `floats` | FLOAT | لا | 0 إلى 8 أعداد عشرية | قيم موحدة عشرية للتظليل. تتوفر الأعداد العشرية كـ `u_float0` إلى `u_float7` في كود التظليل. الافتراضي: 0.0. | -| `ints` | INT | لا | 0 إلى 8 أعداد صحيحة | قيم موحدة صحيحة للتظليل. تتوفر الأعداد الصحيحة كـ `u_int0` إلى `u_int7` في كود التظليل. الافتراضي: 0. | -| `القيم المنطقية` | BOOLEAN | لا | 0 إلى 8 قيم منطقية | قيم موحدة منطقية للتظليل. تتوفر القيم المنطقية كـ `u_bool0` إلى `u_bool7` (bool) في كود التظليل. الافتراضي: خطأ. | -| `المنحنيات` | CURVE | لا | 0 إلى 8 منحنيات | قيم موحدة منحنية للتظليل. تتوفر المنحنيات كـ `u_curve0` إلى `u_curve7` (sampler2D، LUT أحادي البعد) في كود التظليل. يتم أخذ عينة باستخدام `texture(u_curve0, vec2(x, 0.5)).r`. | +The simplest possible shader - a passthrough that outputs the input image unchanged: -**ملاحظات:** +```glsl +#version 300 es +precision highp float; -* معاملات `width` و `height` مطلوبة ومرئية فقط عندما يكون `size_mode` مضبوطًا على `"custom"`. -* مطلوب صورة مدخلة واحدة على الأقل. -* يتمتع كود التظليل دائمًا بإمكانية الوصول إلى معامل موحد `u_resolution` (vec2) يحتوي على أبعاد الإخراج. -* يمكن توفير حد أقصى 8 صور مدخلة، و8 معاملات عشرية موحدة، و8 معاملات صحيحة موحدة، و8 معاملات منطقية موحدة، و8 معاملات منحنية موحدة. +uniform sampler2D u_image0; -## المخرجات +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; -| اسم المخرج | نوع البيانات | الوصف | -|-------------|-------------|-------------| -| `IMAGE1` | IMAGE | الصورة الناتجة الأولى من التظليل. متاحة عبر `layout(location = 0) out vec4 fragColor0` في كود التظليل. | -| `IMAGE2` | IMAGE | الصورة الناتجة الثانية من التظليل. متاحة عبر `layout(location = 1) out vec4 fragColor1` في كود التظليل. | -| `IMAGE3` | IMAGE | الصورة الناتجة الثالثة من التظليل. متاحة عبر `layout(location = 2) out vec4 fragColor2` في كود التظليل. | -| `IMAGE3` | IMAGE | الصورة الناتجة الرابعة من التظليل. متاحة عبر `layout(location = 3) out vec4 fragColor3` في كود التظليل. | +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/en.md b/comfyui_embedded_docs/docs/GLSLShader/en.md index a11b03e8..251516d4 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/en.md +++ b/comfyui_embedded_docs/docs/GLSLShader/en.md @@ -1,36 +1,298 @@ > This documentation was AI-generated. If you find any errors or have suggestions for improvement, please feel free to contribute! [Edit on GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/en.md) -The GLSL Shader node applies custom GLSL ES fragment shader code to input images. It allows you to write shader programs that can process multiple images and accept uniform parameters (floats, integers, booleans, and curves) to create complex visual effects. The output size can be determined by the first input image or set manually. - -## Inputs - -| Parameter | Data Type | Required | Range | Description | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | Yes | N/A | GLSL fragment shader source code (GLSL ES 3.00 / WebGL 2.0 compatible). Default: A basic shader that outputs the first input image. | -| `size_mode` | COMBO | Yes | `"from_input"`
`"custom"` | Output size: 'from_input' uses first input image dimensions, 'custom' allows manual size. | -| `width` | INT | No | 1 to 16384 | The width of the output image when `size_mode` is set to `"custom"`. Default: 512. | -| `height` | INT | No | 1 to 16384 | The height of the output image when `size_mode` is set to `"custom"`. Default: 512. | -| `images` | IMAGE | Yes | 1 to 5 images | Input images to be processed by the shader. Images are available as `u_image0` to `u_image4` (sampler2D) in the shader code. | -| `floats` | FLOAT | No | 0 to 20 floats | Floating-point uniform values for the shader. Floats are available as `u_float0` to `u_float19` in the shader code. Default: 0.0. | -| `ints` | INT | No | 0 to 20 integers | Integer uniform values for the shader. Ints are available as `u_int0` to `u_int19` in the shader code. Default: 0. | -| `bools` | BOOLEAN | No | 0 to 10 booleans | Boolean uniform values for the shader. Booleans are available as `u_bool0` to `u_bool9` (bool) in the shader code. Default: False. | -| `curves` | CURVE | No | 0 to 4 curves | Curve uniform values for the shader. Curves are available as `u_curve0` to `u_curve3` (sampler2D, 1D LUT) in the shader code. Sample with `texture(u_curve0, vec2(x, 0.5)).r`. | - -**Notes:** - -* The `width` and `height` parameters are only required and visible when `size_mode` is set to `"custom"`. -* At least one input image is required. -* The shader code always has access to a `u_resolution` (vec2) uniform containing the output dimensions. -* A maximum of 5 input images, 20 float uniforms, 20 integer uniforms, 10 boolean uniforms, and 4 curve uniforms can be provided. - -## Outputs - -| Output Name | Data Type | Description | -|-------------|-----------|-------------| -| `IMAGE0` | IMAGE | The first output image from the shader. Available via `layout(location = 0) out vec4 fragColor0` in the shader code. | -| `IMAGE1` | IMAGE | The second output image from the shader. Available via `layout(location = 1) out vec4 fragColor1` in the shader code. | -| `IMAGE2` | IMAGE | The third output image from the shader. Available via `layout(location = 2) out vec4 fragColor2` in the shader code. | -| `IMAGE3` | IMAGE | The fourth output image from the shader. Available via `layout(location = 3) out vec4 fragColor3` in the shader code. | +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `ded589d5b0cb5413ecc42c7177e3076427ceac1d3218a20cfec6f2e005fe7e27` diff --git a/comfyui_embedded_docs/docs/GLSLShader/es.md b/comfyui_embedded_docs/docs/GLSLShader/es.md index 91258dfc..b72c04c4 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/es.md +++ b/comfyui_embedded_docs/docs/GLSLShader/es.md @@ -1,36 +1,298 @@ > Esta documentación fue generada por IA. Si encuentra algún error o tiene sugerencias de mejora, ¡no dude en contribuir! [Editar en GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/es.md) -El nodo **Shader GLSL** aplica código de fragment shader GLSL ES personalizado a imágenes de entrada. Permite escribir programas de shader que pueden procesar múltiples imágenes y aceptar parámetros uniformes (flotantes, enteros, booleanos y curvas) para crear efectos visuales complejos. El tamaño de salida puede determinarse por la primera imagen de entrada o configurarse manualmente. - -## Entradas - -| Parámetro | Tipo de Dato | Obligatorio | Rango | Descripción | -|-----------|---------------|-------------|-------|-------------| -| `fragment_shader` | STRING | Sí | N/A | Código fuente del fragment shader GLSL (compatible con GLSL ES 3.00 / WebGL 2.0). Valor predeterminado: un shader básico que genera la primera imagen de entrada. | -| `size_mode` | COMBO | Sí | `"from_input"`
`"custom"` | Tamaño de salida: 'from_input' usa las dimensiones de la primera imagen de entrada, 'custom' permite un tamaño manual. | -| `width` | INT | No | 1 a 16384 | Ancho de la imagen de salida cuando `size_mode` está configurado en `"custom"`. Valor predeterminado: 512. | -| `height` | INT | No | 1 a 16384 | Alto de la imagen de salida cuando `size_mode` está configurado en `"custom"`. Valor predeterminado: 512. | -| `images` | IMAGE | Sí | 1 a 8 imágenes | Imágenes de entrada que serán procesadas por el shader. Las imágenes están disponibles como `u_image0` a `u_image7` (sampler2D) en el código del shader. | -| `floats` | FLOAT | No | 0 a 8 flotantes | Valores uniformes de punto flotante para el shader. Los flotantes están disponibles como `u_float0` a `u_float7` en el código del shader. Valor predeterminado: 0.0. | -| `ints` | INT | No | 0 a 8 enteros | Valores uniformes enteros para el shader. Los enteros están disponibles como `u_int0` a `u_int7` en el código del shader. Valor predeterminado: 0. | -| `booleanos` | BOOLEAN | No | 0 a 8 booleanos | Valores uniformes booleanos para el shader. Los booleanos están disponibles como `u_bool0` a `u_bool7` (bool) en el código del shader. Valor predeterminado: Falso. | -| `curvas` | CURVE | No | 0 a 8 curvas | Valores uniformes de curva para el shader. Las curvas están disponibles como `u_curve0` a `u_curve7` (sampler2D, LUT 1D) en el código del shader. Se muestrean con `texture(u_curve0, vec2(x, 0.5)).r`. | - -**Notas:** - -* Los parámetros `width` y `height` solo son obligatorios y visibles cuando `size_mode` está configurado en `"custom"`. -* Se requiere al menos una imagen de entrada. -* El código del shader siempre tiene acceso a un uniforme `u_resolution` (vec2) que contiene las dimensiones de salida. -* Se puede proporcionar un máximo de 8 imágenes de entrada, 8 uniformes flotantes, 8 uniformes enteros, 8 uniformes booleanos y 8 uniformes de curva. - -## Salidas - -| Nombre de Salida | Tipo de Dato | Descripción | -|------------------|---------------|-------------| -| `IMAGE1` | IMAGE | Primera imagen de salida del shader. Disponible mediante `layout(location = 0) out vec4 fragColor0` en el código del shader. | -| `IMAGE2` | IMAGE | Segunda imagen de salida del shader. Disponible mediante `layout(location = 1) out vec4 fragColor1` en el código del shader. | -| `IMAGE3` | IMAGE | Tercera imagen de salida del shader. Disponible mediante `layout(location = 2) out vec4 fragColor2` en el código del shader. | -| `IMAGE3` | IMAGE | Cuarta imagen de salida del shader. Disponible mediante `layout(location = 3) out vec4 fragColor3` en el código del shader. | +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/fa.md b/comfyui_embedded_docs/docs/GLSLShader/fa.md index 3ca1bd4c..d613b40b 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/fa.md +++ b/comfyui_embedded_docs/docs/GLSLShader/fa.md @@ -1,36 +1,298 @@ -> این مستند با هوش مصنوعی تهیه شده است. اگر خطایی دیدید یا پیشنهادی برای بهبود دارید، خوشحال می‌شویم مشارکت کنید! [ویرایش در GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/fa.md) - -گره GLSL Shader، کد شِیدر فرگمنت GLSL ES را روی تصاویر ورودی اعمال می‌کند. این گره به شما امکان می‌دهد برنامه‌های شیدری بنویسید که بتوانند چندین تصویر را پردازش کرده و پارامترهای یکنواخت (اعداد اعشاری، اعداد صحیح، مقادیر بولی و منحنی‌ها) را برای ایجاد افکت‌های بصری پیچیده بپذیرند. اندازه خروجی می‌تواند توسط اولین تصویر ورودی تعیین شود یا به‌صورت دستی تنظیم گردد. - -## ورودی‌ها - -| پارامتر | نوع داده | ضروری | محدوده | توضیحات | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | بله | نامعتبر | کد منبع شیدر فرگمنت GLSL (سازگار با GLSL ES 3.00 / WebGL 2.0). پیش‌فرض: یک شیدر پایه که اولین تصویر ورودی را خروجی می‌دهد. | -| `size_mode` | COMBO | بله | `"from_input"`
`"custom"` | اندازه خروجی: 'from_input' از ابعاد اولین تصویر ورودی استفاده می‌کند، 'custom' امکان تنظیم دستی اندازه را فراهم می‌کند. | -| `width` | INT | خیر | 1 تا 16384 | عرض تصویر خروجی زمانی که `size_mode` روی `"custom"` تنظیم شده است. پیش‌فرض: 512. | -| `height` | INT | خیر | 1 تا 16384 | ارتفاع تصویر خروجی زمانی که `size_mode` روی `"custom"` تنظیم شده است. پیش‌فرض: 512. | -| `images` | IMAGE | بله | 1 تا 8 تصویر | تصاویر ورودی برای پردازش توسط شیدر. تصاویر در کد شیدر به صورت `u_image0` تا `u_image7` (sampler2D) در دسترس هستند. | -| `floats` | FLOAT | خیر | 0 تا 8 عدد اعشاری | مقادیر یکنواخت اعشاری برای شیدر. اعداد اعشاری در کد شیدر به صورت `u_float0` تا `u_float7` در دسترس هستند. پیش‌فرض: 0.0. | -| `ints` | INT | خیر | 0 تا 8 عدد صحیح | مقادیر یکنواخت صحیح برای شیدر. اعداد صحیح در کد شیدر به صورت `u_int0` تا `u_int7` در دسترس هستند. پیش‌فرض: 0. | -| `بول‌ها` | BOOLEAN | خیر | 0 تا 8 مقدار بولی | مقادیر یکنواخت بولی برای شیدر. مقادیر بولی در کد شیدر به صورت `u_bool0` تا `u_bool7` (bool) در دسترس هستند. پیش‌فرض: False. | -| `منحنی‌ها` | CURVE | خیر | 0 تا 8 منحنی | مقادیر یکنواخت منحنی برای شیدر. منحنی‌ها در کد شیدر به صورت `u_curve0` تا `u_curve7` (sampler2D, 1D LUT) در دسترس هستند. نمونه‌برداری با `texture(u_curve0, vec2(x, 0.5)).r`. | - -**نکات:** - -* پارامترهای `width` و `height` تنها زمانی ضروری و قابل مشاهده هستند که `size_mode` روی `"custom"` تنظیم شده باشد. -* حداقل یک تصویر ورودی الزامی است. -* کد شیدر همیشه به یک متغیر یکنواخت `u_resolution` (vec2) حاوی ابعاد خروجی دسترسی دارد. -* حداکثر 8 تصویر ورودی، 8 متغیر یکنواخت اعشاری، 8 متغیر یکنواخت صحیح، 8 متغیر یکنواخت بولی و 8 متغیر یکنواخت منحنی قابل ارائه است. - -## خروجی‌ها - -| نام خروجی | نوع داده | توضیحات | -|-------------|-----------|-------------| -| `IMAGE0` | IMAGE | اولین تصویر خروجی از شیدر. از طریق `layout(location = 0) out vec4 fragColor0` در کد شیدر قابل دسترسی است. | -| `IMAGE1` | IMAGE | دومین تصویر خروجی از شیدر. از طریق `layout(location = 1) out vec4 fragColor1` در کد شیدر قابل دسترسی است. | -| `IMAGE2` | IMAGE | سومین تصویر خروجی از شیدر. از طریق `layout(location = 2) out vec4 fragColor2` در کد شیدر قابل دسترسی است. | -| `IMAGE3` | IMAGE | چهارمین تصویر خروجی از شیدر. از طریق `layout(location = 3) out vec4 fragColor3` در کد شیدر قابل دسترسی است. | +> این مستندات توسط هوش مصنوعی تولید شده است. اگر خطایی یافتید یا پیشنهادی برای بهبود دارید، لطفاً مشارکت کنید! [ویرایش در GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/fa.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/fr.md b/comfyui_embedded_docs/docs/GLSLShader/fr.md index a298935b..c6112ba2 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/fr.md +++ b/comfyui_embedded_docs/docs/GLSLShader/fr.md @@ -1,36 +1,298 @@ > Cette documentation a été générée par IA. Si vous trouvez des erreurs ou avez des suggestions d'amélioration, n'hésitez pas à contribuer ! [Modifier sur GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/fr.md) -Le nœud Shader GLSL applique un code de fragment shader GLSL ES personnalisé aux images d’entrée. Il permet d’écrire des programmes shader capables de traiter plusieurs images et d’accepter des paramètres uniformes (flottants, entiers, booléens et courbes) pour créer des effets visuels complexes. La taille de sortie peut être déterminée par la première image d’entrée ou définie manuellement. - -## Entrées - -| Paramètre | Type de données | Requis | Plage | Description | -|-----------|-----------------|--------|-------|-------------| -| `fragment_shader` | STRING | Oui | N/D | Code source du fragment shader GLSL (compatible GLSL ES 3.00 / WebGL 2.0). Par défaut : un shader basique qui produit la première image d’entrée. | -| `size_mode` | COMBO | Oui | `"from_input"`
`"custom"` | Taille de sortie : 'from_input' utilise les dimensions de la première image d’entrée, 'custom' permet une taille manuelle. | -| `width` | INT | Non | 1 à 16384 | Largeur de l’image de sortie lorsque `size_mode` est défini sur `"custom"`. Par défaut : 512. | -| `height` | INT | Non | 1 à 16384 | Hauteur de l’image de sortie lorsque `size_mode` est défini sur `"custom"`. Par défaut : 512. | -| `images` | IMAGE | Oui | 1 à 8 images | Images d’entrée à traiter par le shader. Les images sont accessibles sous les noms `u_image0` à `u_image7` (sampler2D) dans le code du shader. | -| `floats` | FLOAT | Non | 0 à 8 flottants | Valeurs uniformes flottantes pour le shader. Les flottants sont accessibles sous les noms `u_float0` à `u_float7` dans le code du shader. Par défaut : 0.0. | -| `ints` | INT | Non | 0 à 8 entiers | Valeurs uniformes entières pour le shader. Les entiers sont accessibles sous les noms `u_int0` à `u_int7` dans le code du shader. Par défaut : 0. | -| `booléens` | BOOLEAN | Non | 0 à 8 booléens | Valeurs uniformes booléennes pour le shader. Les booléens sont accessibles sous les noms `u_bool0` à `u_bool7` (bool) dans le code du shader. Par défaut : False. | -| `courbes` | CURVE | Non | 0 à 8 courbes | Valeurs uniformes de courbes pour le shader. Les courbes sont accessibles sous les noms `u_curve0` à `u_curve7` (sampler2D, LUT 1D) dans le code du shader. Échantillonnez avec `texture(u_curve0, vec2(x, 0.5)).r`. | - -**Remarques :** - -* Les paramètres `width` et `height` ne sont requis et visibles que lorsque `size_mode` est défini sur `"custom"`. -* Au moins une image d’entrée est requise. -* Le code du shader a toujours accès à un uniforme `u_resolution` (vec2) contenant les dimensions de sortie. -* Un maximum de 8 images d’entrée, 8 uniformes flottants, 8 uniformes entiers, 8 uniformes booléens et 8 uniformes de courbes peuvent être fournis. - -## Sorties - -| Nom de sortie | Type de données | Description | -|---------------|-----------------|-------------| -| `IMAGE1` | IMAGE | Première image de sortie du shader. Accessible via `layout(location = 0) out vec4 fragColor0` dans le code du shader. | -| `IMAGE2` | IMAGE | Deuxième image de sortie du shader. Accessible via `layout(location = 1) out vec4 fragColor1` dans le code du shader. | -| `IMAGE3` | IMAGE | Troisième image de sortie du shader. Accessible via `layout(location = 2) out vec4 fragColor2` dans le code du shader. | -| `IMAGE3` | IMAGE | Quatrième image de sortie du shader. Accessible via `layout(location = 3) out vec4 fragColor3` dans le code du shader. | +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/ja.md b/comfyui_embedded_docs/docs/GLSLShader/ja.md index c8cf4371..6a822774 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/ja.md +++ b/comfyui_embedded_docs/docs/GLSLShader/ja.md @@ -1,36 +1,298 @@ -> このドキュメントは AI によって生成されました。エラーを見つけた場合や改善のご提案がある場合は、ぜひ貢献してください! [GitHub で編集](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ja.md) - -GLSL Shader ノードは、入力画像にカスタムの GLSL ES フラグメントシェーダーコードを適用します。複数の画像を処理し、浮動小数点、整数、ブーリアン、カーブといったユニフォームパラメータを受け取るシェーダープログラムを作成することで、複雑な視覚効果を実現できます。出力サイズは最初の入力画像から決定するか、手動で設定できます。 - -## 入力 - -| パラメータ | データ型 | 必須 | 範囲 | 説明 | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | はい | N/A | GLSL フラグメントシェーダーのソースコード(GLSL ES 3.00 / WebGL 2.0 互換)。デフォルト:最初の入力画像を出力する基本シェーダー。 | -| `size_mode` | COMBO | はい | `"from_input"`
`"custom"` | 出力サイズ:「from_input」は最初の入力画像の寸法を使用し、「custom」は手動サイズ設定を可能にします。 | -| `width` | INT | いいえ | 1 ~ 16384 | `size_mode` が `"custom"` に設定されている場合の出力画像の幅。デフォルト:512。 | -| `height` | INT | いいえ | 1 ~ 16384 | `size_mode` が `"custom"` に設定されている場合の出力画像の高さ。デフォルト:512。 | -| `images` | IMAGE | はい | 1 ~ 8 枚の画像 | シェーダーで処理される入力画像。シェーダーコード内では `u_image0` から `u_image7`(sampler2D)として利用できます。 | -| `floats` | FLOAT | いいえ | 0 ~ 8 個の浮動小数点 | シェーダー用の浮動小数点ユニフォーム値。シェーダーコード内では `u_float0` から `u_float7` として利用できます。デフォルト:0.0。 | -| `ints` | INT | いいえ | 0 ~ 8 個の整数 | シェーダー用の整数ユニフォーム値。シェーダーコード内では `u_int0` から `u_int7` として利用できます。デフォルト:0。 | -| `bools` | BOOLEAN | いいえ | 0 ~ 8 個のブーリアン | シェーダー用のブーリアンユニフォーム値。シェーダーコード内では `u_bool0` から `u_bool7`(bool)として利用できます。デフォルト:False。 | -| `curves` | CURVE | いいえ | 0 ~ 8 個のカーブ | シェーダー用のカーブユニフォーム値。シェーダーコード内では `u_curve0` から `u_curve7`(sampler2D、1D LUT)として利用できます。`texture(u_curve0, vec2(x, 0.5)).r` でサンプリングします。 | - -**注記:** - -* `width` と `height` パラメータは、`size_mode` が `"custom"` に設定されている場合のみ必須となり、表示されます。 -* 少なくとも 1 つの入力画像が必要です。 -* シェーダーコードは常に、出力寸法を含む `u_resolution`(vec2)ユニフォームにアクセスできます。 -* 最大 8 枚の入力画像、8 個の浮動小数点ユニフォーム、8 個の整数ユニフォーム、8 個のブーリアンユニフォーム、8 個のカーブユニフォームを提供できます。 - -## 出力 - -| 出力名 | データ型 | 説明 | -|-------------|-----------|-------------| -| `IMAGE1` | IMAGE | シェーダーからの最初の出力画像。シェーダーコード内では `layout(location = 0) out vec4 fragColor0` を介して利用できます。 | -| `IMAGE2` | IMAGE | シェーダーからの 2 番目の出力画像。シェーダーコード内では `layout(location = 1) out vec4 fragColor1` を介して利用できます。 | -| `IMAGE3` | IMAGE | シェーダーからの 3 番目の出力画像。シェーダーコード内では `layout(location = 2) out vec4 fragColor2` を介して利用できます。 | -| `IMAGE3` | IMAGE | シェーダーからの 4 番目の出力画像。シェーダーコード内では `layout(location = 3) out vec4 fragColor3` を介して利用できます。 | +> このドキュメントは AI によって生成されました。誤りを見つけた場合や改善の提案がある場合は、ぜひコントリビュートしてください! [GitHub で編集](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ja.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/ko.md b/comfyui_embedded_docs/docs/GLSLShader/ko.md index 2173dbf8..ee1fe600 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/ko.md +++ b/comfyui_embedded_docs/docs/GLSLShader/ko.md @@ -1,36 +1,298 @@ -> 이 문서는 AI에 의해 생성되었습니다. 오류를 발견하거나 개선 제안이 있으시면 기여해 주세요! [GitHub에서 편집](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ko.md) - -GLSL 셰이더 노드는 입력 이미지에 사용자 정의 GLSL ES 프래그먼트 셰이더 코드를 적용합니다. 여러 이미지를 처리하고 균일 매개변수(실수, 정수, 부울, 곡선)를 받아들여 복잡한 시각 효과를 생성하는 셰이더 프로그램을 작성할 수 있습니다. 출력 크기는 첫 번째 입력 이미지에 의해 결정되거나 수동으로 설정할 수 있습니다. - -## 입력 - -| 매개변수 | 데이터 타입 | 필수 여부 | 범위 | 설명 | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | 예 | 해당 없음 | GLSL 프래그먼트 셰이더 소스 코드(GLSL ES 3.00 / WebGL 2.0 호환). 기본값: 첫 번째 입력 이미지를 출력하는 기본 셰이더. | -| `size_mode` | COMBO | 예 | `"from_input"`
`"custom"` | 출력 크기: 'from_input'은 첫 번째 입력 이미지 크기를 사용하고, 'custom'은 수동 크기 설정을 허용합니다. | -| `width` | INT | 아니요 | 1 ~ 16384 | `size_mode`가 `"custom"`으로 설정된 경우 출력 이미지의 너비입니다. 기본값: 512. | -| `height` | INT | 아니요 | 1 ~ 16384 | `size_mode`가 `"custom"`으로 설정된 경우 출력 이미지의 높이입니다. 기본값: 512. | -| `images` | IMAGE | 예 | 1 ~ 8개 이미지 | 셰이더가 처리할 입력 이미지입니다. 이미지는 셰이더 코드에서 `u_image0`부터 `u_image7`(sampler2D)로 사용할 수 있습니다. | -| `floats` | FLOAT | 아니요 | 0 ~ 8개 실수 | 셰이더의 부동소수점 균일 값입니다. 실수는 셰이더 코드에서 `u_float0`부터 `u_float7`로 사용할 수 있습니다. 기본값: 0.0. | -| `ints` | INT | 아니요 | 0 ~ 8개 정수 | 셰이더의 정수 균일 값입니다. 정수는 셰이더 코드에서 `u_int0`부터 `u_int7`로 사용할 수 있습니다. 기본값: 0. | -| `불리언` | BOOLEAN | 아니요 | 0 ~ 8개 부울 | 셰이더의 부울 균일 값입니다. 부울은 셰이더 코드에서 `u_bool0`부터 `u_bool7`(bool)로 사용할 수 있습니다. 기본값: False. | -| `커브` | CURVE | 아니요 | 0 ~ 8개 곡선 | 셰이더의 곡선 균일 값입니다. 곡선은 셰이더 코드에서 `u_curve0`부터 `u_curve7`(sampler2D, 1D LUT)로 사용할 수 있습니다. `texture(u_curve0, vec2(x, 0.5)).r`로 샘플링합니다. | - -**참고:** - -* `width` 및 `height` 매개변수는 `size_mode`가 `"custom"`으로 설정된 경우에만 필요하며 표시됩니다. -* 최소 하나의 입력 이미지가 필요합니다. -* 셰이더 코드는 항상 출력 크기를 포함하는 `u_resolution`(vec2) 균일에 접근할 수 있습니다. -* 최대 8개의 입력 이미지, 8개의 실수 균일 값, 8개의 정수 균일 값, 8개의 부울 균일 값, 8개의 곡선 균일 값을 제공할 수 있습니다. - -## 출력 - -| 출력 이름 | 데이터 타입 | 설명 | -|-------------|-----------|-------------| -| `IMAGE1` | IMAGE | 셰이더의 첫 번째 출력 이미지입니다. 셰이더 코드에서 `layout(location = 0) out vec4 fragColor0`을 통해 사용할 수 있습니다. | -| `IMAGE2` | IMAGE | 셰이더의 두 번째 출력 이미지입니다. 셰이더 코드에서 `layout(location = 1) out vec4 fragColor1`을 통해 사용할 수 있습니다. | -| `IMAGE3` | IMAGE | 셰이더의 세 번째 출력 이미지입니다. 셰이더 코드에서 `layout(location = 2) out vec4 fragColor2`를 통해 사용할 수 있습니다. | -| `IMAGE3` | IMAGE | 셰이더의 네 번째 출력 이미지입니다. 셰이더 코드에서 `layout(location = 3) out vec4 fragColor3`을 통해 사용할 수 있습니다. | +> 이 문서는 AI가 생성했습니다. 오류를 발견하거나 개선 제안이 있으시면 언제든지 기여해 주세요! [GitHub에서 편집](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ko.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md b/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md index 6dcd302d..435123cf 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md +++ b/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md @@ -1,36 +1,298 @@ -> Esta documentação foi gerada por IA. Se você encontrar erros ou tiver sugestões de melhoria, sinta-se à vontade para contribuir! [Editar no GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md) - -O nó GLSL Shader aplica código de shader de fragmento GLSL ES personalizado a imagens de entrada. Ele permite escrever programas de shader que podem processar múltiplas imagens e aceitar parâmetros uniformes (floats, inteiros, booleanos e curvas) para criar efeitos visuais complexos. O tamanho da saída pode ser determinado pela primeira imagem de entrada ou definido manualmente. - -## Entradas - -| Parâmetro | Tipo de Dado | Obrigatório | Intervalo | Descrição | -|-----------|--------------|-------------|-----------|-----------| -| `fragment_shader` | STRING | Sim | N/A | Código-fonte do shader de fragmento GLSL (compatível com GLSL ES 3.00 / WebGL 2.0). Padrão: Um shader básico que gera a primeira imagem de entrada. | -| `modo_tamanho` | COMBO | Sim | `"from_input"`
`"custom"` | Tamanho da saída: 'from_input' usa as dimensões da primeira imagem de entrada, 'custom' permite tamanho manual. | -| `width` | INT | Não | 1 a 16384 | A largura da imagem de saída quando `modo_tamanho` está definido como `"custom"`. Padrão: 512. | -| `height` | INT | Não | 1 a 16384 | A altura da imagem de saída quando `modo_tamanho` está definido como `"custom"`. Padrão: 512. | -| `imagens` | IMAGE | Sim | 1 a 8 imagens | Imagens de entrada a serem processadas pelo shader. As imagens estão disponíveis como `u_image0` a `u_image7` (sampler2D) no código do shader. | -| `floats` | FLOAT | Não | 0 a 8 floats | Valores uniformes de ponto flutuante para o shader. Os floats estão disponíveis como `u_float0` a `u_float7` no código do shader. Padrão: 0.0. | -| `ints` | INT | Não | 0 a 8 inteiros | Valores uniformes inteiros para o shader. Os inteiros estão disponíveis como `u_int0` a `u_int7` no código do shader. Padrão: 0. | -| `booleanos` | BOOLEAN | Não | 0 a 8 booleanos | Valores uniformes booleanos para o shader. Os booleanos estão disponíveis como `u_bool0` a `u_bool7` (bool) no código do shader. Padrão: Falso. | -| `curvas` | CURVE | Não | 0 a 8 curvas | Valores uniformes de curva para o shader. As curvas estão disponíveis como `u_curve0` a `u_curve7` (sampler2D, LUT 1D) no código do shader. Amostre com `texture(u_curve0, vec2(x, 0.5)).r`. | - -**Observações:** - -* Os parâmetros `width` e `height` são obrigatórios e visíveis apenas quando `size_mode` está definido como `"custom"`. -* Pelo menos uma imagem de entrada é necessária. -* O código do shader sempre tem acesso a um uniforme `u_resolution` (vec2) contendo as dimensões da saída. -* No máximo 8 imagens de entrada, 8 uniformes float, 8 uniformes inteiros, 8 uniformes booleanos e 8 uniformes de curva podem ser fornecidos. - -## Saídas - -| Nome da Saída | Tipo de Dado | Descrição | -|---------------|--------------|-----------| -| `IMAGE0` | IMAGE | A primeira imagem de saída do shader. Disponível via `layout(location = 0) out vec4 fragColor0` no código do shader. | -| `IMAGE1` | IMAGE | A segunda imagem de saída do shader. Disponível via `layout(location = 1) out vec4 fragColor1` no código do shader. | -| `IMAGE2` | IMAGE | A terceira imagem de saída do shader. Disponível via `layout(location = 2) out vec4 fragColor2` no código do shader. | -| `IMAGE3` | IMAGE | A quarta imagem de saída do shader. Disponível via `layout(location = 3) out vec4 fragColor3` no código do shader. | +> Esta documentação foi gerada por IA. Se você encontrar algum erro ou tiver sugestões de melhoria, sinta-se à vontade para contribuir! [Editar no GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/pt-BR.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/ru.md b/comfyui_embedded_docs/docs/GLSLShader/ru.md index 7ad1dd87..5dec91f6 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/ru.md +++ b/comfyui_embedded_docs/docs/GLSLShader/ru.md @@ -1,36 +1,298 @@ -> Эта документация была создана с помощью ИИ. Если вы обнаружите ошибки или у вас есть предложения по улучшению, пожалуйста, внесите свой вклад! [Редактировать на GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ru.md) - -Узел GLSL Shader применяет пользовательский код фрагментного шейдера GLSL ES к входным изображениям. Он позволяет писать шейдерные программы, которые могут обрабатывать несколько изображений и принимать однородные параметры (числа с плавающей точкой, целые числа, логические значения и кривые) для создания сложных визуальных эффектов. Размер выходного изображения может определяться первым входным изображением или задаваться вручную. - -## Входные параметры - -| Параметр | Тип данных | Обязательный | Диапазон | Описание | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | Да | Н/Д | Исходный код фрагментного шейдера GLSL (совместимый с GLSL ES 3.00 / WebGL 2.0). По умолчанию: базовый шейдер, выводящий первое входное изображение. | -| `size_mode` | COMBO | Да | `"from_input"`
`"custom"` | Размер вывода: 'from_input' использует размеры первого входного изображения, 'custom' позволяет задать размер вручную. | -| `width` | INT | Нет | от 1 до 16384 | Ширина выходного изображения, когда `size_mode` установлен в `"custom"`. По умолчанию: 512. | -| `height` | INT | Нет | от 1 до 16384 | Высота выходного изображения, когда `size_mode` установлен в `"custom"`. По умолчанию: 512. | -| `images` | IMAGE | Да | от 1 до 8 изображений | Входные изображения для обработки шейдером. Изображения доступны как `u_image0` - `u_image7` (sampler2D) в коде шейдера. | -| `floats` | FLOAT | Нет | от 0 до 8 чисел с плавающей точкой | Однородные значения с плавающей точкой для шейдера. Доступны как `u_float0` - `u_float7` в коде шейдера. По умолчанию: 0.0. | -| `ints` | INT | Нет | от 0 до 8 целых чисел | Целочисленные однородные значения для шейдера. Доступны как `u_int0` - `u_int7` в коде шейдера. По умолчанию: 0. | -| `булевы` | BOOLEAN | Нет | от 0 до 8 логических значений | Логические однородные значения для шейдера. Доступны как `u_bool0` - `u_bool7` (bool) в коде шейдера. По умолчанию: False. | -| `кривые` | CURVE | Нет | от 0 до 8 кривых | Однородные значения кривых для шейдера. Кривые доступны как `u_curve0` - `u_curve7` (sampler2D, 1D LUT) в коде шейдера. Сэмплирование: `texture(u_curve0, vec2(x, 0.5)).r`. | - -**Примечания:** - -* Параметры `width` и `height` обязательны и отображаются только когда `size_mode` установлен в `"custom"`. -* Требуется как минимум одно входное изображение. -* Код шейдера всегда имеет доступ к однородной переменной `u_resolution` (vec2), содержащей размеры выходного изображения. -* Можно передать максимум 8 входных изображений, 8 однородных значений с плавающей точкой, 8 целочисленных однородных значений, 8 логических однородных значений и 8 однородных значений кривых. - -## Выходные параметры - -| Имя выхода | Тип данных | Описание | -|-------------|-----------|-------------| -| `IMAGE0` | IMAGE | Первое выходное изображение из шейдера. Доступно через `layout(location = 0) out vec4 fragColor0` в коде шейдера. | -| `IMAGE1` | IMAGE | Второе выходное изображение из шейдера. Доступно через `layout(location = 1) out vec4 fragColor1` в коде шейдера. | -| `IMAGE2` | IMAGE | Третье выходное изображение из шейдера. Доступно через `layout(location = 2) out vec4 fragColor2` в коде шейдера. | -| `IMAGE3` | IMAGE | Четвёртое выходное изображение из шейдера. Доступно через `layout(location = 3) out vec4 fragColor3` в коде шейдера. | +> Эта документация создана ИИ. Если вы нашли ошибки или у вас есть предложения по улучшению, не стесняйтесь вносить свой вклад! [Редактировать на GitHub](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/ru.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/tr.md b/comfyui_embedded_docs/docs/GLSLShader/tr.md index 5431ded4..200aa15b 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/tr.md +++ b/comfyui_embedded_docs/docs/GLSLShader/tr.md @@ -1,36 +1,298 @@ -> Bu belge yapay zeka tarafından oluşturulmuştur. Herhangi bir hata bulursanız veya iyileştirme önerileriniz varsa, katkıda bulunmaktan çekinmeyin! [GitHub'da Düzenle](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/tr.md) - -GLSL Shader düğümü, giriş görüntülerine özel GLSL ES fragment shader kodu uygular. Birden fazla görüntüyü işleyebilen ve tek tip parametreler (float, integer, boolean ve eğriler) kabul eden shader programları yazarak karmaşık görsel efektler oluşturmanıza olanak tanır. Çıktı boyutu, ilk giriş görüntüsüne göre belirlenebilir veya manuel olarak ayarlanabilir. - -## Girişler - -| Parametre | Veri Türü | Zorunlu | Aralık | Açıklama | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | Evet | Yok | GLSL fragment shader kaynak kodu (GLSL ES 3.00 / WebGL 2.0 uyumlu). Varsayılan: İlk giriş görüntüsünü çıktı olarak veren temel bir shader. | -| `size_mode` | COMBO | Evet | `"from_input"`
`"custom"` | Çıktı boyutu: 'from_input' ilk giriş görüntüsü boyutlarını kullanır, 'custom' manuel boyutlandırmaya izin verir. | -| `width` | INT | Hayır | 1 ila 16384 | `size_mode` değeri `"custom"` olarak ayarlandığında çıktı görüntüsünün genişliği. Varsayılan: 512. | -| `height` | INT | Hayır | 1 ila 16384 | `size_mode` değeri `"custom"` olarak ayarlandığında çıktı görüntüsünün yüksekliği. Varsayılan: 512. | -| `images` | IMAGE | Evet | 1 ila 8 görüntü | Shader tarafından işlenecek giriş görüntüleri. Görüntülere shader kodunda `u_image0` ile `u_image7` (sampler2D) olarak erişilebilir. | -| `floats` | FLOAT | Hayır | 0 ila 8 float | Shader için kayan noktalı tek tip değerler. Float değerlerine shader kodunda `u_float0` ile `u_float7` olarak erişilebilir. Varsayılan: 0.0. | -| `ints` | INT | Hayır | 0 ila 8 integer | Shader için tamsayı tek tip değerler. Tamsayılara shader kodunda `u_int0` ile `u_int7` olarak erişilebilir. Varsayılan: 0. | -| `bools` | BOOLEAN | Hayır | 0 ila 8 boolean | Shader için boolean tek tip değerler. Boolean değerlerine shader kodunda `u_bool0` ile `u_bool7` (bool) olarak erişilebilir. Varsayılan: Yanlış. | -| `curves` | CURVE | Hayır | 0 ila 8 eğri | Shader için eğri tek tip değerler. Eğrilere shader kodunda `u_curve0` ile `u_curve7` (sampler2D, 1D LUT) olarak erişilebilir. `texture(u_curve0, vec2(x, 0.5)).r` ile örnekleyin. | - -**Notlar:** - -* `width` ve `height` parametreleri yalnızca `size_mode` değeri `"custom"` olarak ayarlandığında gereklidir ve görünür. -* En az bir giriş görüntüsü gereklidir. -* Shader kodu her zaman çıktı boyutlarını içeren bir `u_resolution` (vec2) tek tip değerine erişebilir. -* En fazla 8 giriş görüntüsü, 8 float tek tip değeri, 8 integer tek tip değeri, 8 boolean tek tip değeri ve 8 eğri tek tip değeri sağlanabilir. - -## Çıktılar - -| Çıktı Adı | Veri Türü | Açıklama | -|-------------|-----------|-------------| -| `IMAGE1` | IMAGE | Shader'dan gelen ilk çıktı görüntüsü. Shader kodunda `layout(location = 0) out vec4 fragColor0` ile kullanılabilir. | -| `IMAGE2` | IMAGE | Shader'dan gelen ikinci çıktı görüntüsü. Shader kodunda `layout(location = 1) out vec4 fragColor1` ile kullanılabilir. | -| `IMAGE3` | IMAGE | Shader'dan gelen üçüncü çıktı görüntüsü. Shader kodunda `layout(location = 2) out vec4 fragColor2` ile kullanılabilir. | -| `IMAGE3` | IMAGE | Shader'dan gelen dördüncü çıktı görüntüsü. Shader kodunda `layout(location = 3) out vec4 fragColor3` ile kullanılabilir. | +> Bu dokümantasyon yapay zeka tarafından oluşturulmuştur. Herhangi bir hata bulursanız veya iyileştirme öneriniz varsa, katkıda bulunmaktan çekinmeyin! [GitHub'da Düzenle](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/tr.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md b/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md index 32d9bcb7..0f2f79e5 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md +++ b/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md @@ -1,36 +1,298 @@ -> 本文檔由 AI 生成。如果您發現任何錯誤或有改進建議,歡迎貢獻! [在 GitHub 上編輯](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md) - -GLSL 著色器節點可將自訂的 GLSL ES 片段著色器程式碼應用於輸入影像。它允許您編寫能夠處理多張影像並接受統一參數(浮點數、整數、布林值和曲線)的著色器程式,以建立複雜的視覺效果。輸出尺寸可由第一張輸入影像決定,或手動設定。 - -## 輸入 - -| 參數 | 資料類型 | 必要 | 範圍 | 說明 | -|-----------|-----------|----------|-------|-------------| -| `片段著色器` | STRING | 是 | N/A | GLSL 片段著色器原始碼(相容 GLSL ES 3.00 / WebGL 2.0)。預設值:一個輸出第一張輸入影像的基本著色器。 | -| `尺寸模式` | COMBO | 是 | `"from_input"`
`"custom"` | 輸出尺寸:'from_input' 使用第一張輸入影像的尺寸,'custom' 允許手動設定尺寸。 | -| `width` | INT | 否 | 1 至 16384 | 當 `尺寸模式` 設為 `"custom"` 時,輸出影像的寬度。預設值:512。 | -| `height` | INT | 否 | 1 至 16384 | 當 `尺寸模式` 設為 `"custom"` 時,輸出影像的高度。預設值:512。 | -| `影像` | IMAGE | 是 | 1 至 8 張影像 | 要由著色器處理的輸入影像。在著色器程式碼中,影像可作為 `u_image0` 到 `u_image7`(sampler2D)使用。 | -| `浮點數` | FLOAT | 否 | 0 至 8 個浮點數 | 著色器的浮點數統一值。在著色器程式碼中,浮點數可作為 `u_float0` 到 `u_float7` 使用。預設值:0.0。 | -| `整數` | INT | 否 | 0 至 8 個整數 | 著色器的整數統一值。在著色器程式碼中,整數可作為 `u_int0` 到 `u_int7` 使用。預設值:0。 | -| `布林值` | BOOLEAN | 否 | 0 至 8 個布林值 | 著色器的布林統一值。在著色器程式碼中,布林值可作為 `u_bool0` 到 `u_bool7`(bool)使用。預設值:False。 | -| `曲線` | CURVE | 否 | 0 至 8 條曲線 | 著色器的曲線統一值。在著色器程式碼中,曲線可作為 `u_curve0` 到 `u_curve7`(sampler2D,1D LUT)使用。使用 `texture(u_curve0, vec2(x, 0.5)).r` 進行取樣。 | - -**注意事項:** - -* 僅在 `size_mode` 設為 `"custom"` 時,`width` 和 `height` 參數才為必要且可見。 -* 至少需要一張輸入影像。 -* 著色器程式碼始終可以存取包含輸出尺寸的 `u_resolution`(vec2)統一值。 -* 最多可提供 8 張輸入影像、8 個浮點數統一值、8 個整數統一值、8 個布林統一值和 8 條曲線統一值。 - -## 輸出 - -| 輸出名稱 | 資料類型 | 說明 | -|-------------|-----------|-------------| -| `影像1` | IMAGE | 來自著色器的第一張輸出影像。可透過著色器程式碼中的 `layout(location = 0) out vec4 fragColor0` 使用。 | -| `影像2` | IMAGE | 來自著色器的第二張輸出影像。可透過著色器程式碼中的 `layout(location = 1) out vec4 fragColor1` 使用。 | -| `影像3` | IMAGE | 來自著色器的第三張輸出影像。可透過著色器程式碼中的 `layout(location = 2) out vec4 fragColor2` 使用。 | -| `IMAGE3` | IMAGE | 來自著色器的第四張輸出影像。可透過著色器程式碼中的 `layout(location = 3) out vec4 fragColor3` 使用。 | +> 此文件由 AI 生成。如果您發現任何錯誤或有改進建議,歡迎貢獻! [在 GitHub 上編輯](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/zh-TW.md) + +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058` diff --git a/comfyui_embedded_docs/docs/GLSLShader/zh.md b/comfyui_embedded_docs/docs/GLSLShader/zh.md index 5e6dbcb8..938f8b93 100644 --- a/comfyui_embedded_docs/docs/GLSLShader/zh.md +++ b/comfyui_embedded_docs/docs/GLSLShader/zh.md @@ -1,36 +1,298 @@ > 本文档由 AI 生成。如果您发现任何错误或有改进建议,欢迎贡献! [在 GitHub 上编辑](https://github.com/Comfy-Org/embedded-docs/blob/main/comfyui_embedded_docs/docs/GLSLShader/zh.md) -GLSL 着色器节点可将自定义 GLSL ES 片段着色器代码应用于输入图像。它允许您编写着色器程序,处理多个图像并接受统一参数(浮点数、整数、布尔值和曲线),从而创建复杂的视觉效果。输出尺寸可由第一个输入图像决定,也可手动设置。 - -## 输入 - -| 参数 | 数据类型 | 是否必填 | 范围 | 描述 | -|-----------|-----------|----------|-------|-------------| -| `fragment_shader` | STRING | 是 | 不适用 | GLSL 片段着色器源代码(兼容 GLSL ES 3.00 / WebGL 2.0)。默认值:输出第一个输入图像的基本着色器。 | -| `size_mode` | COMBO | 是 | `"from_input"`
`"custom"` | 输出尺寸:'from_input' 使用第一个输入图像的尺寸,'custom' 允许手动设置尺寸。 | -| `width` | INT | 否 | 1 至 16384 | 当 `size_mode` 设置为 `"custom"` 时,输出图像的宽度。默认值:512。 | -| `height` | INT | 否 | 1 至 16384 | 当 `size_mode` 设置为 `"custom"` 时,输出图像的高度。默认值:512。 | -| `images` | IMAGE | 是 | 1 至 8 张图像 | 由着色器处理的输入图像。在着色器代码中,图像可作为 `u_image0` 到 `u_image7`(sampler2D)使用。 | -| `floats` | FLOAT | 否 | 0 至 8 个浮点数 | 着色器的浮点统一值。在着色器代码中,浮点数可作为 `u_float0` 到 `u_float7` 使用。默认值:0.0。 | -| `ints` | INT | 否 | 0 至 8 个整数 | 着色器的整数统一值。在着色器代码中,整数可作为 `u_int0` 到 `u_int7` 使用。默认值:0。 | -| `布尔值` | BOOLEAN | 否 | 0 至 8 个布尔值 | 着色器的布尔统一值。在着色器代码中,布尔值可作为 `u_bool0` 到 `u_bool7`(bool)使用。默认值:False。 | -| `曲线` | CURVE | 否 | 0 至 8 条曲线 | 着色器的曲线统一值。在着色器代码中,曲线可作为 `u_curve0` 到 `u_curve7`(sampler2D,一维查找表)使用。使用 `texture(u_curve0, vec2(x, 0.5)).r` 进行采样。 | - -**注意:** - -* 仅当 `size_mode` 设置为 `"custom"` 时,`width` 和 `height` 参数才为必填项并可见。 -* 至少需要一张输入图像。 -* 着色器代码始终可以访问包含输出尺寸的 `u_resolution`(vec2)统一变量。 -* 最多可提供 8 张输入图像、8 个浮点统一变量、8 个整数统一变量、8 个布尔统一变量和 8 个曲线统一变量。 - -## 输出 - -| 输出名称 | 数据类型 | 描述 | -|-------------|-----------|-------------| -| `IMAGE1` | IMAGE | 着色器的第一个输出图像。在着色器代码中通过 `layout(location = 0) out vec4 fragColor0` 使用。 | -| `IMAGE2` | IMAGE | 着色器的第二个输出图像。在着色器代码中通过 `layout(location = 1) out vec4 fragColor1` 使用。 | -| `IMAGE3` | IMAGE | 着色器的第三个输出图像。在着色器代码中通过 `layout(location = 2) out vec4 fragColor2` 使用。 | -| `IMAGE3` | IMAGE | 着色器的第四个输出图像。在着色器代码中通过 `layout(location = 3) out vec4 fragColor3` 使用。 | +The **GLSL Shader** node lets you write custom fragment shaders in **GLSL ES 3.00** (WebGL 2.0 compatible) to process images directly on the GPU. You can create image effects like blurs, color grading, film grain, glow, and much more - all running at GPU speed. + + +The GLSL Shader node is currently marked as **experimental**, so the node may be updated and extended in future releases. + + +## Minimal Shader + +The simplest possible shader - a passthrough that outputs the input image unchanged: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + + +**Why GLSL ES 3.00?** Shaders need to run in two environments: the **browser** (via WebGL 2.0, which only supports GLSL ES 3.00) for live preview in the ComfyUI frontend, and the **Python backend** (via desktop OpenGL) when the workflow executes. GLSL ES 3.00 is the common denominator that works in both places. + + +## Available Uniforms + +These uniforms are automatically set by ComfyUI. You don't need to declare all of them - only declare the ones you use. + +### Images + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_image0` – `u_image4` | `sampler2D` | Input images (up to 5). Sampled with `texture(u_image0, v_texCoord)`. Images are RGBA float textures with linear filtering and clamp-to-edge wrapping. | + +### Floats + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_float0` – `u_float19` | `float` | Up to 20 user-controlled float values. Mapped from the **floats** input group on the node. | + +### Integers + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_int0` – `u_int19` | `int` | Up to 20 user-controlled integer values. Mapped from the **ints** input group on the node. | + + +**Using int uniforms as dropdowns:** Int uniforms pair well with the **Custom Combo** node's index output - users pick an option from a dropdown and the shader receives the selected item's index. + +```glsl +const int BLEND_SCREEN = 0; +const int BLEND_OVERLAY = 1; +const int BLEND_MULTIPLY = 2; + +// ... + +if (u_int0 == BLEND_SCREEN) { + // ... +} +``` + + +### Booleans + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_bool0` – `u_bool9` | `bool` | Up to 10 user-controlled boolean values. Mapped from the **bools** input group on the node. | + +### Curves (1D LUTs) + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_curve0` – `u_curve3` | `sampler2D` | Up to 4 user-editable curve LUTs from the **curves** input group. Each curve is a 1D lookup table stored as a single-row texture. | + + +**Using curve uniforms:** Curves let users draw arbitrary tone-mapping graphs in the UI (e.g. for contrast, gamma, per-channel grading, or any custom `input → output` remap). Sample the curve using your input value as the X coordinate - remember to clamp it to `[0, 1]` first: + +```glsl +float applyCurve(sampler2D curve, float value) { + return texture(curve, vec2(clamp(value, 0.0, 1.0), 0.5)).r; +} + +// Usage: remap each RGB channel through a master curve +color.r = applyCurve(u_curve0, color.r); +color.g = applyCurve(u_curve0, color.g); +color.b = applyCurve(u_curve0, color.b); +``` + +Common uses: master RGB curves, per-channel R/G/B curves, luminance-driven remaps, custom gamma, and any effect where you want the user to shape a response curve visually. + + +### Resolution + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_resolution` | `vec2` | **Output** framebuffer dimensions in pixels (`width, height`). This is the size you're writing to, which may differ from any input image's size when `size_mode` is `"custom"`. | + + +**Computing texel size for sampling:** Don't use `1.0 / u_resolution` to step one pixel in an input texture. `u_resolution` is the *output* size, which may not match the input's size. Instead use `textureSize()` on the actual texture you're sampling: + +```glsl +vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); +``` + +Use `u_resolution` only when you need the output framebuffer dimensions themselves (e.g. computing `gl_FragCoord.xy / u_resolution` to get screen-space UVs). + + +### Multi-Pass + +| Uniform | Type | Description | +|---------|------|-------------| +| `u_pass` | `int` | Current pass index (0-based). Only meaningful when using `#pragma passes` - see [Multi-Pass Ping-Pong Rendering](#multi-pass-ping-pong-rendering) for details. | + +### Vertex Shader Output + +| Varying | Type | Description | +|---------|------|-------------| +| `v_texCoord` | `vec2` | Texture coordinates ranging from (0,0) at bottom-left to (1,1) at top-right. | + +## Multiple Outputs (MRT) + +The node supports up to **4 simultaneous outputs** using Multiple Render Targets. Declare additional outputs with explicit locations: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; +layout(location = 1) out vec4 fragColor1; +layout(location = 2) out vec4 fragColor2; +layout(location = 3) out vec4 fragColor3; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + fragColor0 = vec4(vec3(color.r), 1.0); // Red channel + fragColor1 = vec4(vec3(color.g), 1.0); // Green channel + fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel + fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel +} +``` + +Each `fragColor` maps to the corresponding `IMAGE` output on the node. ComfyUI auto-detects which outputs you use - unused outputs will be black. + +## Multi-Pass Ping-Pong Rendering + +Some effects (like separable blur) need multiple passes over the image. Use the `#pragma passes N` directive to enable this: + +```glsl +#version 300 es +#pragma passes 2 +precision highp float; + +uniform sampler2D u_image0; +uniform float u_float0; // Blur radius +uniform int u_pass; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec2 texel = 1.0 / vec2(textureSize(u_image0, 0)); + int radius = int(ceil(u_float0)); + + // Pass 0 = horizontal blur, Pass 1 = vertical blur + vec2 dir = (u_pass == 0) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + + vec4 color = vec4(0.0); + float total = 0.0; + + for (int i = -radius; i <= radius; i++) { + vec2 offset = dir * float(i) * texel; + float w = 1.0; // box blur weight + color += texture(u_image0, v_texCoord + offset) * w; + total += w; + } + + fragColor0 = color / total; +} +``` + +### How ping-pong works + +1. **Pass 0**: Reads from the original `u_image0` input, writes to an internal ping-pong texture. +2. **Pass 1–N**: Reads from the *previous pass output* via `u_image0` (the binding is swapped automatically), writes to the other ping-pong texture. +3. **Final pass**: Writes to the actual output framebuffer (`fragColor0`). + + +When using multi-pass with MRT (multiple outputs), only the first output (`fragColor0`) participates in ping-pong. The final pass writes all outputs. + + +## Examples + +### Grayscale Conversion + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 color = texture(u_image0, v_texCoord); + float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + fragColor0 = vec4(vec3(gray), color.a); +} +``` + +### Image Blending + +Blend two input images using a float parameter as the mix factor: + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; +uniform sampler2D u_image1; +uniform float u_float0; // mix factor [0.0 – 1.0] + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + vec4 a = texture(u_image0, v_texCoord); + vec4 b = texture(u_image1, v_texCoord); + fragColor0 = mix(a, b, clamp(u_float0, 0.0, 1.0)); +} +``` + +## Using an LLM to Generate Shaders + +You can use any LLM (Claude, ChatGPT, etc.) to write GLSL shaders for you. Copy the following prompt and fill in your desired effect: + +````markdown +Write a GLSL ES 3.00 fragment shader for ComfyUI's GLSLShader node. + +**Effect I want:** [DESCRIBE YOUR DESIRED EFFECT HERE] + +**Requirements:** +- Must start with `#version 300 es` +- Use `precision highp float;` +- The vertex shader provides `in vec2 v_texCoord` (0–1 UV coordinates, bottom-left origin) +- Output to `layout(location = 0) out vec4 fragColor0` (RGBA) +- Additional outputs available: `fragColor1`, `fragColor2`, `fragColor3` at locations 1–3 + +**Template to follow (minimal passthrough shader - use this exact structure):** + +```glsl +#version 300 es +precision highp float; + +uniform sampler2D u_image0; + +in vec2 v_texCoord; +layout(location = 0) out vec4 fragColor0; + +void main() { + fragColor0 = texture(u_image0, v_texCoord); +} +``` + +**Available uniforms (declare only what you use):** +- `uniform sampler2D u_image0;` through `u_image4` - up to 5 input images (RGBA float, linear filtering, clamp-to-edge) +- `uniform vec2 u_resolution;` - **output framebuffer** width and height in pixels. This is NOT the input texture size (they can differ when the user sets a custom output size). **To step one pixel in an input texture, use `vec2 texel = 1.0 / vec2(textureSize(u_image0, 0));` - do NOT use `1.0 / u_resolution` for this.** +- `uniform float u_float0;` through `u_float19;` - up to 20 user-controlled float parameters +- `uniform int u_int0;` through `u_int19;` - up to 20 user-controlled integer parameters. Tip: int uniforms can be wired from a **Custom Combo** node's index output, so users select from a dropdown and the shader receives the index. Use this for mode selection (e.g. blend mode, blur type). Define named constants for each option and branch on those - do NOT compare against raw integer literals. For example: `const int BLUR_GAUSSIAN = 0; const int BLUR_BOX = 1; ... if (u_int0 == BLUR_GAUSSIAN) { ... }`. +- `uniform bool u_bool0;` through `u_bool9;` - up to 10 user-controlled boolean parameters (use for feature toggles) +- `uniform sampler2D u_curve0;` through `u_curve3;` - up to 4 user-editable 1D LUT curves. Sample with `texture(u_curve0, vec2(clamp(x, 0.0, 1.0), 0.5)).r` where `x` is 0–1. Use for tone curves, remapping, etc. +- `uniform int u_pass;` - current pass index (when using multi-pass) + +**Multi-pass rendering:** +- Add `#pragma passes N` on the second line to enable N passes +- On pass 0, `u_image0` is the original input; on subsequent passes it contains the previous pass output +- Use `u_pass` to vary behavior per pass (e.g., horizontal vs. vertical blur) + +**Important constraints:** +- GLSL ES 3.00 only - no GLSL 1.x `varying`/`attribute`, no `gl_FragColor` +- No `#include`, no external textures, no custom vertex shader +- Document each uniform with a comment showing its purpose and expected range +```` + +### Example prompt fill-in + +> **Effect I want:** A chromatic aberration effect that splits RGB channels outward from the center of the image. u_float0 controls the strength of the offset (0 = no effect, 10 = extremely strong). The offset should scale with distance from the center. --- **Source fingerprint (SHA-256):** `7830977409a5efab205b7c927eb83499a9e1e8299959b34643c9c3f1f586c058`