Skip to content

Instantly share code, notes, and snippets.

@pfgithub
Last active December 20, 2021 03:42

Revisions

  1. pfgithub revised this gist Dec 20, 2021. 1 changed file with 8 additions and 1 deletion.
    9 changes: 8 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,14 @@ top to bottom: fancyscale, linear, nearest neighbor:

    ## notes:

    the edges are solid pixels, this would likely look better with antialiasing applied
    - the edges are solid pixels
    - how to fix this: apply antialiasing
    - currently there are some differences between pixels because in another pixel, the color same color may be closer to a different color.
    - how to fix this: I'm not sure right now
    - currently we're using a math distance rather than a visual color difference function
    - how to fix this: use a proper visual color difference function
    - https://stackoverflow.com/questions/9018016/how-to-compare-two-colors-for-similarity-difference
    - https://stackoverflow.com/questions/1313/followup-finding-an-accurate-distance-between-colors

    ## try it out:

  2. pfgithub revised this gist Dec 20, 2021. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -7,12 +7,12 @@ default opengl linear:
    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146707204-a7d4fd0b-b907-4aed-b53e-869daf3433dc.png)

    top to bottom: fancyscale, linear, nearest neighbor
    top to bottom: fancyscale, linear, nearest neighbor:
    ![image](https://user-images.githubusercontent.com/6010774/146707969-58db8394-1da7-4f1c-b95e-4d932db55694.png)

    ---

    top to bottom: fancyscale, linear, nearest neighbor
    top to bottom: fancyscale, linear, nearest neighbor:
    ![image](https://user-images.githubusercontent.com/6010774/146707843-b56b7329-7e3b-4219-9af2-8f02528c87ba.png)

    ## notes:
  3. pfgithub revised this gist Dec 20, 2021. 3 changed files with 86 additions and 74 deletions.
    19 changes: 8 additions & 11 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,22 +1,19 @@
    nearest neighbor:
    ![image](https://user-images.githubusercontent.com/6010774/146702216-be96d1d1-9162-49a2-923e-649acc3bff08.png)
    ![image](https://user-images.githubusercontent.com/6010774/146707253-8d9eafcc-9aa5-4cef-adc9-7314c6900306.png)

    default opengl linear:
    ![image](https://user-images.githubusercontent.com/6010774/146702381-b01e22ae-3ce4-4877-8343-cc1e56621fe2.png)
    ![image](https://user-images.githubusercontent.com/6010774/146707226-cfcf5f63-6c35-422b-b6f0-1213ea07778e.png)

    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146702174-bf2fec84-4115-4e0c-80f4-e9b786971c71.png)
    ![image](https://user-images.githubusercontent.com/6010774/146707204-a7d4fd0b-b907-4aed-b53e-869daf3433dc.png)

    ---

    nearest neighbor
    ![image](https://user-images.githubusercontent.com/6010774/146703680-20388bc8-1ca3-4dc0-83ed-4d392fe2889b.png)
    top to bottom: fancyscale, linear, nearest neighbor
    ![image](https://user-images.githubusercontent.com/6010774/146707969-58db8394-1da7-4f1c-b95e-4d932db55694.png)

    default opengl linear:
    ![image](https://user-images.githubusercontent.com/6010774/146703716-8edbde81-f674-4204-8f1b-317aa48550e2.png)
    ---

    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146703646-ad608dcb-bd79-4c38-b0c1-998169150f0f.png)
    top to bottom: fancyscale, linear, nearest neighbor
    ![image](https://user-images.githubusercontent.com/6010774/146707843-b56b7329-7e3b-4219-9af2-8f02528c87ba.png)

    ## notes:

    87 changes: 74 additions & 13 deletions fancyupscale.glsl
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,58 @@
    //// Image
    //// set these settings:
    //// - iChannel0 = Buffer A
    //// - iChannel1 = Image of choice

    #define IMGCHANNEL iChannel1
    //======Start shared code for state
    #define pz_stateYOffset 0.0
    #define pz_stateBuf 0
    #define pz_stateSample(x) texture(iChannel0,x)
    vec2 pz_realBufferResolution;
    vec2 pz_originalBufferResolution;

    void pz_initializeState() {
    pz_realBufferResolution = iChannelResolution[pz_stateBuf].xy;
    pz_originalBufferResolution = pz_stateSample(.5/pz_realBufferResolution).xy;
    }

    vec2 pz_nr2vec(float nr) {
    return vec2(mod(nr, pz_originalBufferResolution.x)
    , pz_stateYOffset+floor(nr / pz_originalBufferResolution.x))+.5;
    }

    vec4 pz_readState(float nr) {
    return pz_stateSample(pz_nr2vec(nr)/pz_realBufferResolution);
    }

    float pz_resetCount() {
    return pz_readState(1.).z;
    }

    vec3 pz_position() {
    return pz_readState(3.).xyz;
    }

    vec2 pz_initializeState(vec2 fragCoord) {
    pz_initializeState();

    vec3 position = pz_position();
    fragCoord -= 0.5*iResolution.xy;
    fragCoord *= position.z;
    fragCoord += (0.5 + position.xy) * iResolution.xy ;
    return fragCoord;
    }
    //======End shared code for state

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    vec2 screenspace = fragCoord / iResolution.xy;

    fragCoord = pz_initializeState(fragCoord);

    vec2 uv = fragCoord;

    ivec2 size = textureSize(iChannel1, 0);
    ivec2 size = textureSize(IMGCHANNEL, 0);

    float ratio = float(size.x) / float(size.y);
    uv.y /= float(iResolution.x)/float(iResolution.y);
    @@ -11,22 +61,25 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )

    //size = ivec2(100, 100);

    ivec2 pixelf = ivec2(floor(uv * vec2(size)));
    ivec2 pixel = ivec2(floor(uv * vec2(size) - vec2(0.5, 0.5)));

    ivec2 px2 = pixel + ivec2(0, 1);
    ivec2 px3 = pixel + ivec2(1, 0);
    ivec2 px4 = pixel + ivec2(1, 1);

    vec2 pxcoordf = (vec2(pixelf) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord = (vec2(pixel) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord2 = (vec2(px2) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord3 = (vec2(px3) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord4 = (vec2(px4) + vec2(0.5, 0.5)) / vec2(size);

    vec4 col1 = vec4(texture(iChannel1, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel1, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel1, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel1, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel1, uv).xyz,1.0);
    vec4 colf = vec4(texture(IMGCHANNEL, pxcoordf).xyz,1.0);
    vec4 col1 = vec4(texture(IMGCHANNEL, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(IMGCHANNEL, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(IMGCHANNEL, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(IMGCHANNEL, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(IMGCHANNEL, uv).xyz,1.0);

    float min = 10000.0;
    vec4 final;
    @@ -49,13 +102,21 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
    //fragColor = mix(col1, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(final, actual, -1.0 ); // looks interesting

    //fragColor = final;
    fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = actual;
    //fragColor = col1;
    //fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(col3, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );

    //fragColor = col2;
    //fragColor = col2;
    //fragColor = col3;
    //fragColor = col4;
    //fragColor = actual;
    if(screenspace.y < 0.33) {
    fragColor = colf;
    }else if(screenspace.y < 0.34) {
    fragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }else if(screenspace.y < 0.66) {
    fragColor = actual;
    }else if(screenspace.y < 0.67) {
    fragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }else{
    fragColor = final;
    }
    //fragColor = vec4(screenspace, 0.0, 1.0);
    }
    54 changes: 4 additions & 50 deletions panandzoom.glsl
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,7 @@
    /// BUFFER A (channel 0 = buffer a) (channel 1 = keyboard)
    //// BUFFER A
    //// set these settings:
    //// - iChannel0 = Buffer A
    //// - iChannel1 = Image of choice

    //======Start shared code for state
    #define pz_stateYOffset 0.0
    @@ -176,52 +179,3 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) {

    // Add multiple state handlers here
    }


    /// IMAGE (channel 0 = buffer a) (channel 1 = image of choice)

    //======Start shared code for state
    #define pz_stateYOffset 0.0
    #define pz_stateBuf 0
    #define pz_stateSample(x) texture(iChannel0,x)
    vec2 pz_realBufferResolution;
    vec2 pz_originalBufferResolution;

    void pz_initializeState() {
    pz_realBufferResolution = iChannelResolution[pz_stateBuf].xy;
    pz_originalBufferResolution = pz_stateSample(.5/pz_realBufferResolution).xy;
    }

    vec2 pz_nr2vec(float nr) {
    return vec2(mod(nr, pz_originalBufferResolution.x)
    , pz_stateYOffset+floor(nr / pz_originalBufferResolution.x))+.5;
    }

    vec4 pz_readState(float nr) {
    return pz_stateSample(pz_nr2vec(nr)/pz_realBufferResolution);
    }

    float pz_resetCount() {
    return pz_readState(1.).z;
    }

    vec3 pz_position() {
    return pz_readState(3.).xyz;
    }

    vec2 pz_initializeState(vec2 fragCoord) {
    pz_initializeState();

    vec3 position = pz_position();
    fragCoord -= 0.5*iResolution.xy;
    fragCoord *= position.z;
    fragCoord += (0.5 + position.xy) * iResolution.xy ;
    return fragCoord;
    }
    //======End shared code for state

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    fragCoord = pz_initializeState(fragCoord);
    … paste from above
    }
  4. pfgithub revised this gist Dec 20, 2021. 2 changed files with 27 additions and 66 deletions.
    38 changes: 26 additions & 12 deletions fancyupscale.glsl
    Original file line number Diff line number Diff line change
    @@ -2,29 +2,31 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    vec2 uv = fragCoord;

    ivec2 size = textureSize(iChannel0, 0);
    ivec2 size = textureSize(iChannel1, 0);

    float ratio = float(size.x) / float(size.y);
    uv.y /= float(iResolution.x)/float(iResolution.y);
    uv.y *= ratio;
    uv /= iResolution.xy;

    ivec2 pixel = ivec2(uv * vec2(size));
    vec2 pxcoord = vec2(pixel) / vec2(size);
    //size = ivec2(100, 100);

    ivec2 pixel = ivec2(floor(uv * vec2(size) - vec2(0.5, 0.5)));

    ivec2 px2 = pixel + ivec2(0, 1);
    ivec2 px3 = pixel + ivec2(1, 0);
    ivec2 px4 = pixel + ivec2(1, 1);

    vec2 pxcoord2 = vec2(px2) / vec2(size);
    vec2 pxcoord3 = vec2(px3) / vec2(size);
    vec2 pxcoord4 = vec2(px4) / vec2(size);
    vec2 pxcoord = (vec2(pixel) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord2 = (vec2(px2) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord3 = (vec2(px3) + vec2(0.5, 0.5)) / vec2(size);
    vec2 pxcoord4 = (vec2(px4) + vec2(0.5, 0.5)) / vec2(size);

    vec4 col1 = vec4(texture(iChannel0, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel0, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel0, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel0, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel0, uv).xyz,1.0);
    vec4 col1 = vec4(texture(iChannel1, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel1, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel1, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel1, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel1, uv).xyz,1.0);

    float min = 10000.0;
    vec4 final;
    @@ -43,5 +45,17 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )

    //fragColor = actual.x > 0.5 ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 0);

    fragColor = final;
    //fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(col1, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(final, actual, -1.0 ); // looks interesting

    //fragColor = final;
    fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(col3, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );

    //fragColor = col2;
    //fragColor = col2;
    //fragColor = col3;
    //fragColor = col4;
    //fragColor = actual;
    }
    55 changes: 1 addition & 54 deletions panandzoom.glsl
    Original file line number Diff line number Diff line change
    @@ -223,58 +223,5 @@ vec2 pz_initializeState(vec2 fragCoord) {
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    fragCoord = pz_initializeState(fragCoord);
    vec2 uv = fragCoord;

    ivec2 size = textureSize(iChannel1, 0);

    float ratio = float(size.x) / float(size.y);
    uv.y /= float(iResolution.x)/float(iResolution.y);
    uv.y *= ratio;
    uv /= iResolution.xy;

    //size = ivec2(100, 100);

    ivec2 pixel = ivec2(floor(uv * vec2(size)));

    ivec2 px2 = pixel + ivec2(0, 1);
    ivec2 px3 = pixel + ivec2(1, 0);
    ivec2 px4 = pixel + ivec2(1, 1);

    vec2 pxcoord = vec2(pixel) / vec2(size);
    vec2 pxcoord2 = vec2(px2) / vec2(size);
    vec2 pxcoord3 = vec2(px3) / vec2(size);
    vec2 pxcoord4 = vec2(px4) / vec2(size);

    vec4 col1 = vec4(texture(iChannel1, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel1, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel1, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel1, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel1, uv).xyz,1.0);

    float min = 10000.0;
    vec4 final;

    float dist1 = distance(col1, actual);
    if(dist1 < min) {min = dist1; final = col1;}

    float dist2 = distance(col2, actual);
    if(dist2 < min) {min = dist2; final = col2;}

    float dist3 = distance(col3, actual);
    if(dist3 < min) {min = dist3; final = col3;}

    float dist4 = distance(col4, actual);
    if(dist4 < min) {min = dist4; final = col4;}

    //fragColor = actual.x > 0.5 ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 0);

    //fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(col1, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(final, actual, -1.0 ); // looks interesting
    fragColor = final;
    //fragColor = col1;
    //fragColor = col2;
    //fragColor = col3;
    //fragColor = col4;
    //fragColor = actual;
    … paste from above
    }
  5. pfgithub revised this gist Dec 20, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    nearest neighbor:
    nearest neighbor:
    ![image](https://user-images.githubusercontent.com/6010774/146702216-be96d1d1-9162-49a2-923e-649acc3bff08.png)

    default opengl linear:
    default opengl linear:
    ![image](https://user-images.githubusercontent.com/6010774/146702381-b01e22ae-3ce4-4877-8343-cc1e56621fe2.png)

    fancyupscale.glsl:
    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146702174-bf2fec84-4115-4e0c-80f4-e9b786971c71.png)

    ---
  6. pfgithub revised this gist Dec 20, 2021. 1 changed file with 280 additions and 0 deletions.
    280 changes: 280 additions & 0 deletions panandzoom.glsl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,280 @@
    /// BUFFER A (channel 0 = buffer a) (channel 1 = keyboard)

    //======Start shared code for state
    #define pz_stateYOffset 0.0
    #define pz_stateBuf 0
    #define pz_stateSample(x) texture(iChannel0,x)
    vec2 pz_realBufferResolution;
    vec2 pz_originalBufferResolution;

    void pz_initializeState() {
    pz_realBufferResolution = iChannelResolution[pz_stateBuf].xy;
    pz_originalBufferResolution = pz_stateSample(.5/pz_realBufferResolution).xy;
    }

    vec2 pz_nr2vec(float nr) {
    return vec2(mod(nr, pz_originalBufferResolution.x)
    , pz_stateYOffset+floor(nr / pz_originalBufferResolution.x))+.5;
    }

    vec4 pz_readState(float nr) {
    return pz_stateSample(pz_nr2vec(nr)/pz_realBufferResolution);
    }

    float pz_resetCount() {
    return pz_readState(1.).z;
    }

    vec3 pz_position() {
    return pz_readState(3.).xyz;
    }

    vec2 pz_initializeState(vec2 fragCoord) {
    pz_initializeState();

    vec3 position = pz_position();
    fragCoord -= 0.5*iResolution.xy;
    fragCoord *= position.z;
    fragCoord += (0.5 + position.xy) * iResolution.xy ;
    return fragCoord;
    }
    //======End shared code for state

    //======Defines for state behaviour
    #define pz_resetOnMove 1
    #define pz_kinetic 0.95

    bool pz_checkCell(float nr, vec2 coord) {
    return distance(pz_nr2vec(nr),coord)<=0.5;
    }

    // Keyboard constants definition
    const float KEY_BSP = 8.5/256.0;
    const float KEY_SP = 32.5/256.0;
    const float KEY_LEFT = 37.5/256.0;
    const float KEY_UP = 38.5/256.0;
    const float KEY_RIGHT = 39.5/256.0;
    const float KEY_DOWN = 40.5/256.0;
    const float KEY_A = 65.5/256.0;
    const float KEY_B = 66.5/256.0;
    const float KEY_C = 67.5/256.0;
    const float KEY_D = 68.5/256.0;
    const float KEY_E = 69.5/256.0;
    const float KEY_F = 70.5/256.0;
    const float KEY_G = 71.5/256.0;
    const float KEY_H = 72.5/256.0;
    const float KEY_I = 73.5/256.0;
    const float KEY_J = 74.5/256.0;
    const float KEY_K = 75.5/256.0;
    const float KEY_L = 76.5/256.0;
    const float KEY_M = 77.5/256.0;
    const float KEY_N = 78.5/256.0;
    const float KEY_O = 79.5/256.0;
    const float KEY_P = 80.5/256.0;
    const float KEY_Q = 81.5/256.0;
    const float KEY_R = 82.5/256.0;
    const float KEY_S = 83.5/256.0;
    const float KEY_T = 84.5/256.0;
    const float KEY_U = 85.5/256.0;
    const float KEY_V = 86.5/256.0;
    const float KEY_W = 87.5/256.0;
    const float KEY_X = 88.5/256.0;
    const float KEY_Y = 89.5/256.0;
    const float KEY_Z = 90.5/256.0;
    const float KEY_COMMA = 188.5/256.0;
    const float KEY_PER = 190.5/256.0;
    const float KEY_ADD = 107.5/256.0;
    const float KEY_SUBS = 109.5/256.0;
    const float KEY_EQUAL = 187.5/256.0;
    const float KEY_MINUS = 189.5/256.0;

    bool checkKey(float key)
    {
    return texture(iChannel1, vec2(key, 0.25)).x > 0.5;
    }

    bool checkKey(float key1, float key2)
    {
    return checkKey(key1) || checkKey(key2);
    }

    bool checkKey(float key1, float key2, float key3)
    {
    return checkKey(key1) || checkKey(key2) || checkKey(key3);
    }

    void pz_mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    pz_initializeState();
    fragColor = pz_stateSample(fragCoord/pz_realBufferResolution);
    if (fragCoord.x < 1.
    && fragCoord.y < 1.) {
    //Lets store the initial buffersize at pos0 and use that for addressing
    if (pz_originalBufferResolution.x == 0.0)
    fragColor = vec4(pz_realBufferResolution,1.0,1.0);

    } else if (pz_checkCell(1.,fragCoord)) {

    // Use postion 1 to trigger screen size changes so we can clear other buffers on going fullscreen
    if (distance(fragColor.xy,pz_realBufferResolution)>1.0
    #if pz_resetOnMove
    || pz_readState(3.).w > 0.0
    #endif
    ) {
    fragColor.xy = pz_realBufferResolution;
    fragColor.z = 60.0;
    } else {
    if (fragColor.z > 0.0)
    fragColor.z -= 1.0;
    }

    } else if (pz_checkCell(2.,fragCoord)) {
    // Store mouse delta if keydown
    if (iMouse.w>0.5) {
    if (fragColor.x>0.0) {
    fragColor.zw = fragColor.xy - iMouse.xy;
    } else {
    fragColor.zw = vec2(0.0);
    }
    fragColor.xy = iMouse.xy;
    } else {

    fragColor.xy = vec2(-1.,-1.);
    #ifdef pz_kinetic
    fragColor.zw = length(fragColor.zw)>0.1?fragColor.zw*pz_kinetic:vec2(0.0,0.0);
    #else
    fragColor.zw = vec2(0.0,0.0);
    #endif
    }

    } else if (pz_checkCell(3.,fragCoord)) {
    // Handle keyboard moves
    vec2 delta = vec2( checkKey(KEY_LEFT ,KEY_A)?-0.02:
    checkKey(KEY_RIGHT,KEY_D )? 0.02:0.0
    , checkKey(KEY_DOWN ,KEY_S )?-0.02:
    checkKey(KEY_UP ,KEY_W)? 0.02:0.0);
    float factor = checkKey(KEY_Q)?1.01:
    checkKey(KEY_E)?0.99:1.0;
    if (fragColor.z<0.0000001)
    fragColor.z = 1.0;

    //Update transform state
    vec2 mouseDelta = pz_readState(2.).zw;
    fragColor.z *= factor;
    fragColor.xy += delta * fragColor.z; //Add keyboard move
    fragColor.xy += mouseDelta / iResolution.xy * fragColor.z; //Add mouse delta

    //Store movement in w
    fragColor.w = abs(factor-1.0)*3. + length(delta) + length(mouseDelta);

    } else
    fragColor = vec4(0.,0.,0.,1.0);
    }

    void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    pz_mainImage( fragColor, fragCoord );

    // Add multiple state handlers here
    }


    /// IMAGE (channel 0 = buffer a) (channel 1 = image of choice)

    //======Start shared code for state
    #define pz_stateYOffset 0.0
    #define pz_stateBuf 0
    #define pz_stateSample(x) texture(iChannel0,x)
    vec2 pz_realBufferResolution;
    vec2 pz_originalBufferResolution;

    void pz_initializeState() {
    pz_realBufferResolution = iChannelResolution[pz_stateBuf].xy;
    pz_originalBufferResolution = pz_stateSample(.5/pz_realBufferResolution).xy;
    }

    vec2 pz_nr2vec(float nr) {
    return vec2(mod(nr, pz_originalBufferResolution.x)
    , pz_stateYOffset+floor(nr / pz_originalBufferResolution.x))+.5;
    }

    vec4 pz_readState(float nr) {
    return pz_stateSample(pz_nr2vec(nr)/pz_realBufferResolution);
    }

    float pz_resetCount() {
    return pz_readState(1.).z;
    }

    vec3 pz_position() {
    return pz_readState(3.).xyz;
    }

    vec2 pz_initializeState(vec2 fragCoord) {
    pz_initializeState();

    vec3 position = pz_position();
    fragCoord -= 0.5*iResolution.xy;
    fragCoord *= position.z;
    fragCoord += (0.5 + position.xy) * iResolution.xy ;
    return fragCoord;
    }
    //======End shared code for state

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    fragCoord = pz_initializeState(fragCoord);
    vec2 uv = fragCoord;

    ivec2 size = textureSize(iChannel1, 0);

    float ratio = float(size.x) / float(size.y);
    uv.y /= float(iResolution.x)/float(iResolution.y);
    uv.y *= ratio;
    uv /= iResolution.xy;

    //size = ivec2(100, 100);

    ivec2 pixel = ivec2(floor(uv * vec2(size)));

    ivec2 px2 = pixel + ivec2(0, 1);
    ivec2 px3 = pixel + ivec2(1, 0);
    ivec2 px4 = pixel + ivec2(1, 1);

    vec2 pxcoord = vec2(pixel) / vec2(size);
    vec2 pxcoord2 = vec2(px2) / vec2(size);
    vec2 pxcoord3 = vec2(px3) / vec2(size);
    vec2 pxcoord4 = vec2(px4) / vec2(size);

    vec4 col1 = vec4(texture(iChannel1, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel1, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel1, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel1, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel1, uv).xyz,1.0);

    float min = 10000.0;
    vec4 final;

    float dist1 = distance(col1, actual);
    if(dist1 < min) {min = dist1; final = col1;}

    float dist2 = distance(col2, actual);
    if(dist2 < min) {min = dist2; final = col2;}

    float dist3 = distance(col3, actual);
    if(dist3 < min) {min = dist3; final = col3;}

    float dist4 = distance(col4, actual);
    if(dist4 < min) {min = dist4; final = col4;}

    //fragColor = actual.x > 0.5 ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 0);

    //fragColor = mix(final, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(col1, actual, sin(iDate.w * 4.0) * 0.5 + 0.5 );
    //fragColor = mix(final, actual, -1.0 ); // looks interesting
    fragColor = final;
    //fragColor = col1;
    //fragColor = col2;
    //fragColor = col3;
    //fragColor = col4;
    //fragColor = actual;
    }
  7. pfgithub created this gist Dec 20, 2021.
    53 changes: 53 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    nearest neighbor:
    ![image](https://user-images.githubusercontent.com/6010774/146702216-be96d1d1-9162-49a2-923e-649acc3bff08.png)

    default opengl linear:
    ![image](https://user-images.githubusercontent.com/6010774/146702381-b01e22ae-3ce4-4877-8343-cc1e56621fe2.png)

    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146702174-bf2fec84-4115-4e0c-80f4-e9b786971c71.png)

    ---

    nearest neighbor
    ![image](https://user-images.githubusercontent.com/6010774/146703680-20388bc8-1ca3-4dc0-83ed-4d392fe2889b.png)

    default opengl linear:
    ![image](https://user-images.githubusercontent.com/6010774/146703716-8edbde81-f674-4204-8f1b-317aa48550e2.png)

    fancyupscale.glsl:
    ![image](https://user-images.githubusercontent.com/6010774/146703646-ad608dcb-bd79-4c38-b0c1-998169150f0f.png)

    ## notes:

    the edges are solid pixels, this would likely look better with antialiasing applied

    ## try it out:

    go to https://www.shadertoy.com/new

    paste the code in the thing

    paste this code in the console to be able to choose your own images:

    ```js
    for (let i = 0; i < 4; ++i) {
    d = document.createElement('div');
    d.className = "upload";
    d.innerHTML = '<button onclick="document.querySelector(\'#texture' + i + '>div.upload>div>input\').click()" style="width:100%;">Upload</button>' +
    '<div style="display:none;"><input type="file" accept="image/*"/>' +
    '<p>#</p></div>';
    document.querySelector('#texture' + i).append(d);
    document.querySelector('#texture' + i + '>div.upload>div>input').addEventListener('change', function () {
    if (this.files && this.files[0]) {
    let p = document.querySelector('#texture' + i + '>div.upload>div>p');
    URL.revokeObjectURL(p.innerText);
    p.innerText = URL.createObjectURL(this.files[0]);
    gShaderToy.SetTexture(i, { mSrc: p.innerText, mType: 'texture', mID: 1, mSampler: { filter: 'mipmap', wrap: 'repeat', vflip: 'true', srgb: 'false', internal: 'byte' } });
    }
    });
    }
    ```

    select an image for iChannel0.

    47 changes: 47 additions & 0 deletions fancyupscale.glsl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    vec2 uv = fragCoord;

    ivec2 size = textureSize(iChannel0, 0);

    float ratio = float(size.x) / float(size.y);
    uv.y /= float(iResolution.x)/float(iResolution.y);
    uv.y *= ratio;
    uv /= iResolution.xy;

    ivec2 pixel = ivec2(uv * vec2(size));
    vec2 pxcoord = vec2(pixel) / vec2(size);

    ivec2 px2 = pixel + ivec2(0, 1);
    ivec2 px3 = pixel + ivec2(1, 0);
    ivec2 px4 = pixel + ivec2(1, 1);

    vec2 pxcoord2 = vec2(px2) / vec2(size);
    vec2 pxcoord3 = vec2(px3) / vec2(size);
    vec2 pxcoord4 = vec2(px4) / vec2(size);

    vec4 col1 = vec4(texture(iChannel0, pxcoord).xyz,1.0);
    vec4 col2 = vec4(texture(iChannel0, pxcoord2).xyz,1.0);
    vec4 col3 = vec4(texture(iChannel0, pxcoord3).xyz,1.0);
    vec4 col4 = vec4(texture(iChannel0, pxcoord4).xyz,1.0);
    vec4 actual = vec4(texture(iChannel0, uv).xyz,1.0);

    float min = 10000.0;
    vec4 final;

    float dist1 = distance(col1, actual);
    if(dist1 < min) {min = dist1; final = col1;}

    float dist2 = distance(col2, actual);
    if(dist2 < min) {min = dist2; final = col2;}

    float dist3 = distance(col3, actual);
    if(dist3 < min) {min = dist3; final = col3;}

    float dist4 = distance(col4, actual);
    if(dist4 < min) {min = dist4; final = col4;}

    //fragColor = actual.x > 0.5 ? vec4(1, 1, 1, 1) : vec4(0, 0, 0, 0);

    fragColor = final;
    }