Skip to content

Shader Replacement Based on Program Type#2424

Open
mathsvisualization wants to merge 1 commit into3b1b:masterfrom
mathsvisualization:feature/program-type-specific-shader-replacement
Open

Shader Replacement Based on Program Type#2424
mathsvisualization wants to merge 1 commit into3b1b:masterfrom
mathsvisualization:feature/program-type-specific-shader-replacement

Conversation

@mathsvisualization
Copy link
Contributor

Motivation

Currently, shader code replacement in set_color_by_code is not program-type aware.
If set_color_by_code is called multiple times on the same VMobject with different program_type values (e.g., "fill", "stroke" and "depth"), only the last applied shader modification takes effect.

This happens because shader code replacement is not scoped to individual program types, causing unintended overrides when both fill and stroke shaders are customized.

This change introduces program-type aware shader code replacement, ensuring that:

  • fill, stroke, and depth shader programs are handled independently.
  • Multiple shader modifications on the same VMobject no longer override each other.
  • Custom fill and stroke shaders can coexist correctly.

This improves flexibility and makes shader customization more predictable and robust.


Proposed changes

  • Added program-type specific shader code handling.
  • Modified shader replacement logic to scope changes per program_type.
  • Ensured that fill, stroke, and depth programs maintain separate shader modifications.
  • Prevented unintended overwriting when set_color_by_code is called multiple times on the same object.
  • Maintained backward compatibility for existing shader usage.

Test

Code

from manimlib import *

class StrokeGradient(Scene):
    def construct(self):
        text = Square()

        text.set_fill(opacity=1)
        text.set_stroke(width=10)
        text.set_color_by_proportion(lambda h: Color(hsl=(h, 0.5, 0.5)))

        text.set_color_by_code(
        """
        vec3 color1 = vec3(1.0, 0.0, 0.0);   // Red
        vec3 color2 = vec3(0.0, 1.0, 0.0);   // Green

        // Normalize x coordinate manually
        float t = (point.x + 4.0) / 8.0;
        t = clamp(t, 0.0, 1.0);

        color.rgb = mix(color1, color2, t);
        """,
        program_type="fill"
        )

        self.add(text)

Before

StrokeGradientBefore

After

StrokeGradientAfterFill StrokeGradientAfterStroke StrokeGradientAfterSetStrokeWithaProportionAndFill

in VShaderWrapper, allowing independent GLSL modifications for:

- stroke programs
- fill programs
- depth programs

Previously, `set_color_by_code()` relied on a single global
replacement mechanism. As a result:

- Multiple calls to `set_color_by_code()` would override each other.
- Applying different GLSL logic to stroke and fill was not possible.
- The last shader replacement always won.

This update solves that limitation by:

1. Storing shader code replacements per program type.
2. Applying replacements only to shaders matching the given program_type.
3. Preserving previously applied replacements for other program types.
4. Maintaining backward compatibility when program_type is None.

Now users can safely do:

    set_color_by_code(..., program_type="stroke")
    set_color_by_code(..., program_type="fill")

without one affecting the other.

This makes stroke and fill shader logic fully independent,
opening the door for:

- Different gradients for stroke and fill
- Custom sheen effects per layer
- Advanced shader experimentation
- Cleaner shader architecture

Backward compatibility:
If no program_type is provided, behavior falls back to the
original global replacement logic.

This improves flexibility without breaking existing scenes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant