Search code examples
three.jsglslwebglfragment-shaderreact-three-fiber

Confused about GLSL shader, how it calculates index


I am at the last part of the book of shader that I need to finish learning having already completed everything else. I am having trouble understanding how the shader calculates the index dependent on the function given. I understand how the function mod is used and what the representation of it on a graph looks like but how the shader places the index number according to the position of the mod function assigned is confusing me. I labeled the piece of the code where I am confused at below and put the link to the page in the book of shader to see the code in action.

https://thebookofshaders.com/09/

// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015

#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265358979323846

uniform vec2 u_resolution;
uniform float u_time;

vec2 rotate2D (vec2 _st, float _angle) {
    _st -= 0.5;
    _st =  mat2(cos(_angle),-sin(_angle),
                sin(_angle),cos(_angle)) * _st;
    _st += 0.5;
    return _st;
}

vec2 tile (vec2 _st, float _zoom) {
    _st *= _zoom;
    return fract(_st);
}

vec2 rotateTilePattern(vec2 _st){
    _st *= 2.0;


!!!(THIS SECTION BELOW ON GIVING THE INDEX NUMER)

    //  Give each cell an index number
    //  according to its position
    float index = 0.0;
    index += step(1., mod(_st.x,2.0));
    index += step(1., mod(_st.y,2.0))*(2.0);

    //      |
    //  2   |   3
    //      |
    //--------------
    //      |
    //  0   |   1
    //      |

!!!(THIS SECTION ABOVE ON GIVING THE INDEX NUMER)

    // Make each cell between 0.0 - 1.0
    _st = fract(_st);

    if(index == 1.0){
        _st = rotate2D(_st,PI*0.5);
    } else if(index == 2.0){
        _st = rotate2D(_st,PI*-0.5);
    } else if(index == 3.0){
        _st = rotate2D(_st,PI);
    }

    return _st;
}

void main (void) {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;

    st = tile(st,3.0);
    st = rotateTilePattern(st);
   
    gl_FragColor = vec4(vec3(step(st.x,st.y)),1.0);
}

Solution

  • vec2 rotateTilePattern(vec2 _st){
        // _st argument contains values between [0,3] after tile(st, 3.0)
        // call in main method
        _st *= 2.0; 
        // _st now contains values between [0, 6] 
    
        // going clockwise
        // x axis starts on the right, y axis starts from the bottom
        // The first quadrant with index 2 is for x = [0, 1] and y = [1, 2]
        // The second quadrant with index 3 is for x = [1, 2] and y = [1, 2]
        // The third quadrant with index 1 is for x = [1, 2] and y = [0, 1]
        // The fourth quadrant with index 0 is for x = [0, 1] and y = [0, 1]
    
        // So lets try with values x=.5 and y=.5 which lie in the fourth quadrant
        // index should equal 0
        // mod(.5, 2.0) is .5
        // step(1., .5) is 0
        // so index += 0 is still 0.0
        // mod(.5, 2.0) is .5
        // step(1., .5) is 0
        // 0 * 2 is 0
        // so index += 0 equals 0 as expected
    
        // Lets try with values x=1.5 and y=1.5 which lie in the second quadrant
        // index should equal 3
        // mod(1.5, 2.0) is 1.5
        // step(1., 1.5) is 1
        // so index += 1 is now equal to 1.0
        // mod(1.5, 2.0) is 1.5
        // step(1., 1.5) is 1
        // 1 * 2 is 2
        // so index += 2 equals 3 as expected
    
        // the mod will treat any value [2-4] or [4-6] the same as [0-2]
    
    
    !!!(THIS SECTION BELOW ON GIVING THE INDEX NUMER)
    
        //  Give each cell an index number
        //  according to its position
        float index = 0.0;
        index += step(1., mod(_st.x,2.0));
        index += step(1., mod(_st.y,2.0))*(2.0);
    
        //      |
        //  2   |   3
        //      |
        //--------------
        //      |
        //  0   |   1
        //      |
    
    !!!(THIS SECTION ABOVE ON GIVING THE INDEX NUMER)