All Questions

Community

Daniel Queiroz Porto

Doesn't seem to be needed to use mix two times. Is it something from 3.2.2?

Hello!

I've just started to follow this course and I'm at the recently released 3.2.2! I was following this step by step and watching what happened with the sprite to understand the effect of each step (it was specially usefull to understand the inverse product thing, it was cool to see the result without masking it) and when I got to do this:

vec4 outlined_result = mix(color, line_color, outline + inline);
COLOR = outlined_result;

The end result for me was already equal to the finished example! I never needed to apply mix twice. What is going on? Is this something new on 3.2.2?

This also happened with the in-out-stroke, but for reference here is my code for the in-stroke since it's shorter but still a bit different from what's in the course, as I give a lot longer names for variables and use more variables to help me separate and understand what's happening. Maybe I changed something by accident and I'm not seeing it?

shader_type canvas_item;

uniform vec4 line_color: hint_color = vec4(1.0); // White
uniform float line_thikness: hint_range(0.0, 20.0) = 1.0;

void fragment(){
  vec2 line_size_in_units = TEXTURE_PIXEL_SIZE * line_thikness;
  
  // We are sampling around the current UV position in all 8 directions
  //and self multiplying the results
  float outline_sample = texture(TEXTURE, UV + 
    vec2(-line_size_in_units.x, 0)).a;
  outline_sample *= texture(TEXTURE, UV +
    vec2(-line_size_in_units.x, line_size_in_units.y)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(0,
    line_size_in_units.y)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(line_size_in_units.x,
    line_size_in_units.y)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(line_size_in_units.x,
    0)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(line_size_in_units.x,
    -line_size_in_units.y)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(0,
    -line_size_in_units.y)).a;
  outline_sample *= texture(TEXTURE, UV + vec2(-line_size_in_units.x,
    -line_size_in_units.y)).a;
                                                      
  // Then we get the "inverse product" of the samples (???)	
  // The middle wil be transparent because theresult of this will be 0
  // The outside will be fully opaque
  // The edges will have some other value	
  float outline_alpha = 1.0 - outline_sample;		
                                                                
  vec4 color = texture(TEXTURE, UV);
                                                  
  // Since inside is 0 and outside is 1 we "mask" the image by
  //multiplying the alphas
  float outline_mask = outline_alpha * color.a;	
  vec4 inlined_result = mix(color, line_color, outline_mask);
  COLOR = inlined_result;
}
  • Nathan Lovato replied
    Solution

    The reason to do two mix calls can be hard to spot, but here's the reason:

    outline + inline
    

    This code produces values outside of the [0.0, 1.0] value range where the two outlines stem from and overlap a bit. It could have visual side effects, I'm not sure, but in general you want to ensure you're in full control of the ranges you're working with.

  • Daniel Queiroz Porto replied

    Thanks Nathan!