bool preventPomSil(int blockID, ivec3 edgePlane, ivec3 cubeFace, vec3 surfacePos) {
    // sides of stairs are rendered with two textures: upper half / lower half.
    // applying Pom Silhouette to each of these would also apply it to the boundary between upper half and lower half of the stair block, so prevent it in that area.
    float verticalPos = surfacePos.y;  // bottom 0.0 ... 1.0 top : vertical position in block(voxel)
    float horizontalPosEW = surfacePos.x;  //  west 0.0 ... 1.0 east
    float horizontalPosNS = surfacePos.z;  // north 0.0 ... 1.0 south
    bool verticalMiddle = (blockID >= 1000 && blockID <= 1023 && edgePlane.y != 0 && verticalPos > 0.25 && verticalPos < 0.75);  // horizontal central boundary (middle of top and bottom) of the stair block
    
    //                                                         back of stair      side of stair      flat part of side
    bool straightN = ((blockID == 1000 || blockID == 1012) && (cubeFace.z < 0 || (cubeFace.x != 0 && horizontalPosNS < 0.53)));  //stairs-north-straight-(bottom/top)
    bool straightS = ((blockID == 1001 || blockID == 1013) && (cubeFace.z > 0 || (cubeFace.x != 0 && horizontalPosNS > 0.47)));  //stairs-south-straight-(bottom/top)
    bool straightE = ((blockID == 1002 || blockID == 1014) && (cubeFace.x > 0 || (cubeFace.z != 0 && horizontalPosEW > 0.47)));  //stairs-east-straight-(bottom/top)
    bool straightW = ((blockID == 1003 || blockID == 1015) && (cubeFace.x < 0 || (cubeFace.z != 0 && horizontalPosEW < 0.53)));  //stairs-west-straight-(bottom/top)
    bool horizontalFlatPart1 = straightN || straightS || straightE || straightW;
    
    bool innerNW = ((blockID == 1004 || blockID == 1016) && (cubeFace.z < 0 || cubeFace.x < 0 || (cubeFace.x > 0 && horizontalPosNS < 0.53) || (cubeFace.z > 0 && horizontalPosEW < 0.53)));  //stairs-(north-inner_left / west-inner_right)-(bottom/top)
    bool innerNE = ((blockID == 1005 || blockID == 1017) && (cubeFace.z < 0 || cubeFace.x > 0 || (cubeFace.x < 0 && horizontalPosNS < 0.53) || (cubeFace.z > 0 && horizontalPosEW > 0.47)));  //stairs-(north-inner_right / east-inner_left)-(bottom/top)
    bool innerSE = ((blockID == 1006 || blockID == 1018) && (cubeFace.z > 0 || cubeFace.x > 0 || (cubeFace.x < 0 && horizontalPosNS > 0.47) || (cubeFace.z < 0 && horizontalPosEW > 0.47)));  //stairs-(south-inner_left / east-inner_right)-(bottom/top)
    bool innerSW = ((blockID == 1007 || blockID == 1019) && (cubeFace.z > 0 || cubeFace.x < 0 || (cubeFace.x > 0 && horizontalPosNS > 0.47) || (cubeFace.z < 0 && horizontalPosEW < 0.53)));  //stairs-(south-inner_right / west-inner_left)-(bottom/top)
    bool horizontalFlatPart2 = innerNW || innerNE || innerSE || innerSW;
    
    bool innerNW_vertical = ((blockID == 1004 || blockID == 1017) && (cubeFace.z < 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(north-inner_left / west-inner_right)-bottom / (north-inner_right / east-inner_left)-top
    bool innerNE_vertical = ((blockID == 1005 || blockID == 1018) && (cubeFace.x > 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(north-inner_right / east-inner_left)-bottom / (south-inner_left / east-inner_right)-top
    bool innerSE_vertical = ((blockID == 1006 || blockID == 1019) && (cubeFace.z > 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(south-inner_left / east-inner_right)-bottom / (south-inner_right / west-inner_left)-top
    bool innerSW_vertical = ((blockID == 1007 || blockID == 1016) && (cubeFace.x < 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(south-inner_right / west-inner_left)-bottom / (north-inner_left / west-inner_right)-top
    bool verticalFlatPart = innerNW_vertical || innerNE_vertical || innerSE_vertical || innerSW_vertical;
    
    bool innerNW_above = (blockID == 1004 && (cubeFace.y > 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(north-inner_left / west-inner_right)-bottom
    bool innerNE_above = (blockID == 1005 && (cubeFace.y > 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(north-inner_right / east-inner_left)-bottom
    bool innerSE_above = (blockID == 1006 && (cubeFace.y > 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(south-inner_left / east-inner_right)-bottom
    bool innerSW_above = (blockID == 1007 && (cubeFace.y > 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(south-inner_right / west-inner_left)-bottom
    bool aboveFlatPart = innerNW_above || innerNE_above || innerSE_above || innerSW_above;
    
    bool innerNW_below = (blockID == 1016 && (cubeFace.y < 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(north-inner_left / west-inner_right)-top
    bool innerNE_below = (blockID == 1017 && (cubeFace.y < 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(north-inner_right / east-inner_left)-top
    bool innerSE_below = (blockID == 1018 && (cubeFace.y < 0 && edgePlane.z != 0 && horizontalPosNS > 0.25 && horizontalPosNS < 0.75));  //stairs-(south-inner_left / east-inner_right)-top
    bool innerSW_below = (blockID == 1019 && (cubeFace.y < 0 && edgePlane.x != 0 && horizontalPosEW > 0.25 && horizontalPosEW < 0.75));  //stairs-(south-inner_right / west-inner_left)-top
    bool belowFlatPart = innerNW_below || innerNE_below || innerSE_below || innerSW_below;
    
    bool outerNW = ((blockID == 1008 || blockID == 1020) && ((cubeFace.z < 0 && horizontalPosEW < 0.53) || (cubeFace.x < 0 && horizontalPosNS < 0.53)));  //stairs-(north-outer_left / west-outer_right)-(bottom/top)
    bool outerNE = ((blockID == 1009 || blockID == 1021) && ((cubeFace.z < 0 && horizontalPosEW > 0.47) || (cubeFace.x > 0 && horizontalPosNS < 0.53)));  //stairs-(north-outer_right / east-outer_left)-(bottom/top)
    bool outerSE = ((blockID == 1010 || blockID == 1022) && ((cubeFace.z > 0 && horizontalPosEW > 0.47) || (cubeFace.x > 0 && horizontalPosNS > 0.47)));  //stairs-(south-outer_left / east-outer_right)-(bottom/top)
    bool outerSW = ((blockID == 1011 || blockID == 1023) && ((cubeFace.z > 0 && horizontalPosEW < 0.53) || (cubeFace.x < 0 && horizontalPosNS > 0.47)));  //stairs-(south-outer_right / west-outer_left)-(bottom/top)
    bool horizontalFlatPart3 = outerNW || outerNE || outerSE || outerSW;
    
    bool preventPomSilhouette = verticalMiddle && (horizontalFlatPart1 || horizontalFlatPart2 || horizontalFlatPart3);
    preventPomSilhouette = preventPomSilhouette || verticalFlatPart || aboveFlatPart || belowFlatPart;
    return preventPomSilhouette;
}

void deceiveStairsTexture(int blockID, ivec3 cubeFace, vec3 surfacePos, inout ivec2 pom_sprite_size, inout vec2 pom_corner_texcoord, inout vec3 pom_tangent_pos) {
    // sides of stairs are rendered with two textures: upper half / lower half.
    // in such cases, the texture size and coordinates are processed not as the original one-block texture in the texture atlas, 
    // but as if only a portion of it (such as the lower half of a square texture) were a single texture.
    // however, this can cause malfunctions in POM calculations, so implementing a workaround to process the size and coordinates 
    // relative to the entire square texture, not just a portion.

    float verticalPos = surfacePos.y;  // bottom 0.0 ... 1.0 top : vertical position in block(voxel)
    float horizontalPosEW = surfacePos.x;  //  west 0.0 ... 1.0 east
    float horizontalPosNS = surfacePos.z;  // north 0.0 ... 1.0 south
    // cubeFace   x>0:east side of block   x<0:west side of block
    //            z>0:south side of block  z<0:north side of block
    //            y>0:top side of block    y<0:bottom side of block
    
    //if ( !(blockID >= 1000 && blockID <= 1023) ) return;
    
    // 1000-1003 : stairs shapes normal
    bool insideFace01 = ((blockID >= 1000 && blockID <= 1003) && (cubeFace.x != 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53));
    bool insideFace02 = ((blockID >= 1000 && blockID <= 1003) && (cubeFace.z != 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53));
    // 1004-1007 : stairs shapes inside the corner
    bool insideFaceUpperL = ((blockID >= 1004 && blockID <= 1007) && 
                             ((cubeFace.x != 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53) || 
                              (cubeFace.z != 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53)));
    bool insideFaceUpperR = ((blockID >= 1004 && blockID <= 1007) && 
                             ((cubeFace.z > 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53 && horizontalPosEW > 0.5) || 
                              (cubeFace.z < 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53 && horizontalPosEW < 0.5) || 
                              (cubeFace.x > 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53 && horizontalPosNS < 0.5) || 
                              (cubeFace.x < 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53 && horizontalPosNS > 0.5)));
    // 1012-1015 : stairs upside down shapes normal
    bool insideFaceLower1 = ((blockID >= 1012 && blockID <= 1015) && (cubeFace.x != 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53));
    bool insideFaceLower2 = ((blockID >= 1012 && blockID <= 1015) && (cubeFace.z != 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53));
    // 1016-1019 : stairs upside down shapes inside the corner
    bool insideFaceLowerR = ((blockID >= 1016 && blockID <= 1019) && 
                             ((cubeFace.x != 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53) || 
                              (cubeFace.z != 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53)));
    bool insideFaceLowerL = ((blockID >= 1016 && blockID <= 1019) && 
                             ((cubeFace.z > 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53 && horizontalPosEW < 0.5) || 
                              (cubeFace.z < 0 && horizontalPosNS > 0.47 && horizontalPosNS < 0.53 && horizontalPosEW > 0.5) || 
                              (cubeFace.x > 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53 && horizontalPosNS > 0.5) || 
                              (cubeFace.x < 0 && horizontalPosEW > 0.47 && horizontalPosEW < 0.53 && horizontalPosNS < 0.5)));
    
    // 1000-1003 : stairs shapes normal    1004-1007 : stairs shapes inside the corner
    bool outsideFace1 = (((blockID == 1000 && cubeFace.z < 0) || (blockID == 1001 && cubeFace.z > 0) || 
                          (blockID == 1002 && cubeFace.x > 0) || (blockID == 1003 && cubeFace.x < 0) || 
                          (blockID == 1004 && cubeFace.x < 0) || (blockID == 1005 && cubeFace.z < 0) || 
                          (blockID == 1006 && cubeFace.x > 0) || (blockID == 1007 && cubeFace.z > 0)) && 
                          verticalPos > 0.5);
    bool outsideFace2 = ((blockID >= 1000 && blockID <= 1011) && (cubeFace.x != 0 || cubeFace.z != 0) && verticalPos < 0.5);
    // 1008-1011 : stairs shapes outside the corner
    /*
    bool outsideFaceUpperL1 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.z > 0 && horizontalPosEW < 0.5 && verticalPos > 0.5)) || 
                              (blockID == 1004 && cubeFace.z < 0 && horizontalPosEW > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1005 && cubeFace.x > 0 && horizontalPosNS > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1006 && cubeFace.z > 0 && horizontalPosEW < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1007 && cubeFace.x < 0 && horizontalPosNS < 0.5 && verticalPos > 0.5);
    bool outsideFaceUpperL2 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.z < 0 && horizontalPosEW > 0.5 && verticalPos > 0.5));
    bool outsideFaceUpperL3 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.x > 0 && horizontalPosNS > 0.5 && verticalPos > 0.5));
    bool outsideFaceUpperL4 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.x < 0 && horizontalPosNS < 0.5 && verticalPos > 0.5));
    */
    bool outsideFaceUpperL1 = (verticalPos > 0.5 && (blockID >= 1008 && blockID <= 1011) && 
                               ((cubeFace.z > 0 && horizontalPosEW < 0.5) || (cubeFace.z < 0 && horizontalPosEW > 0.5) || 
                                (cubeFace.x > 0 && horizontalPosNS > 0.5) || (cubeFace.x < 0 && horizontalPosNS < 0.5)));
    bool outsideFaceUpperL2 = (blockID == 1004 && cubeFace.z < 0 && horizontalPosEW > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1005 && cubeFace.x > 0 && horizontalPosNS > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1006 && cubeFace.z > 0 && horizontalPosEW < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1007 && cubeFace.x < 0 && horizontalPosNS < 0.5 && verticalPos > 0.5);
    /*
    bool outsideFaceUpperR1 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.z > 0 && horizontalPosEW > 0.5 && verticalPos > 0.5)) || 
                              (blockID == 1004 && cubeFace.z < 0 && horizontalPosEW < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1005 && cubeFace.x > 0 && horizontalPosNS < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1006 && cubeFace.z > 0 && horizontalPosEW > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1007 && cubeFace.x < 0 && horizontalPosNS > 0.5 && verticalPos > 0.5);
    bool outsideFaceUpperR2 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.z < 0 && horizontalPosEW < 0.5 && verticalPos > 0.5));
    bool outsideFaceUpperR3 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.x > 0 && horizontalPosNS < 0.5 && verticalPos > 0.5));
    bool outsideFaceUpperR4 = ((blockID >= 1008 && blockID <= 1011) && (cubeFace.x < 0 && horizontalPosNS > 0.5 && verticalPos > 0.5));
    */
    bool outsideFaceUpperR1 = (verticalPos > 0.5 && (blockID >= 1008 && blockID <= 1011) && 
                               ((cubeFace.z > 0 && horizontalPosEW > 0.5) || (cubeFace.z < 0 && horizontalPosEW < 0.5) || 
                                (cubeFace.x > 0 && horizontalPosNS < 0.5) || (cubeFace.x < 0 && horizontalPosNS > 0.5)));
    bool outsideFaceUpperR2 = (blockID == 1004 && cubeFace.z < 0 && horizontalPosEW < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1005 && cubeFace.x > 0 && horizontalPosNS < 0.5 && verticalPos > 0.5) || 
                              (blockID == 1006 && cubeFace.z > 0 && horizontalPosEW > 0.5 && verticalPos > 0.5) || 
                              (blockID == 1007 && cubeFace.x < 0 && horizontalPosNS > 0.5 && verticalPos > 0.5);
    // 1012-1015 : stairs upside down shapes normal
    bool outsideFaceUSD1 = (((blockID == 1012 && cubeFace.z < 0) || (blockID == 1013 && cubeFace.z > 0) ||
                             (blockID == 1014 && cubeFace.x > 0) || (blockID == 1015 && cubeFace.x < 0)) && 
                             verticalPos < 0.5);
    bool outsideFaceUSD2 = ((blockID >= 1012 && blockID <= 1023) && (cubeFace.x != 0 || cubeFace.z != 0) && verticalPos > 0.5);
    // 1020-1023 : stairs upside down shapes outside the corner
    bool outsideFaceLowerL = (verticalPos < 0.5 && (blockID >= 1020 && blockID <= 1023) && 
                              ((cubeFace.z > 0 && horizontalPosEW < 0.5) || (cubeFace.z < 0 && horizontalPosEW > 0.5) || 
                               (cubeFace.x > 0 && horizontalPosNS > 0.5) || (cubeFace.x < 0 && horizontalPosNS < 0.5)));
    bool outsideFaceLowerR = (verticalPos < 0.5 && (blockID >= 1020 && blockID <= 1023) && 
                              ((cubeFace.z > 0 && horizontalPosEW > 0.5) || (cubeFace.z < 0 && horizontalPosEW < 0.5) || 
                               (cubeFace.x > 0 && horizontalPosNS < 0.5) || (cubeFace.x < 0 && horizontalPosNS > 0.5)));
    
    if (insideFaceUpperR || 
        outsideFaceUpperR1 || outsideFaceUpperR2 || 
        outsideFaceLowerR) {
        // sprite-size-x prior to adjustment serves exactly as the value used to adjust coordinate offset.
        pom_corner_texcoord.x -= float(pom_sprite_size.x) / float(atlasSize.x);
        pom_tangent_pos.x = pom_sprite_size.x + pom_tangent_pos.x;
    }
    
    if (outsideFace2 || 
        insideFaceLower1 || insideFaceLower2 || insideFaceLowerR || insideFaceLowerL || 
        outsideFaceUSD1 || 
        outsideFaceLowerL || outsideFaceLowerR) {
        // sprite-size-y prior to adjustment serves exactly as the value used to adjust coordinate offset.
        pom_corner_texcoord.y -= float(pom_sprite_size.y) / float(atlasSize.y);
        pom_tangent_pos.y = pom_sprite_size.y + pom_tangent_pos.y;
    }
    
    if (insideFaceUpperL || insideFaceUpperR || insideFace01 || insideFace02 || 
        outsideFace1 || outsideFace2 || 
        outsideFaceUpperR1 || outsideFaceUpperR2 || 
        outsideFaceUpperL1 || outsideFaceUpperL2 || 
        insideFaceLower1 || insideFaceLower2 || insideFaceLowerR || insideFaceLowerL || 
        outsideFaceUSD1 || outsideFaceUSD2 || 
        outsideFaceLowerL || outsideFaceLowerR) {
        pom_sprite_size.y *= 2;
    }
    
    if (insideFaceUpperR || 
        outsideFaceUpperR1 || outsideFaceUpperR2 || 
        outsideFaceUpperL1 || outsideFaceUpperL2 || 
        insideFaceLowerL || 
        outsideFaceLowerL || outsideFaceLowerR) {
        pom_sprite_size.x *= 2;
    }
    /*
    if (outsideFace2 || 
        insideFaceLower1 || insideFaceLower2 || 
        insideFaceLowerR1 || insideFaceLowerR2 || insideFaceLowerL1 || insideFaceLowerL2 || insideFaceLowerL3 || insideFaceLowerL4 || 
        outsideFaceUSD1 || 
        outsideFaceLowerL1 || outsideFaceLowerL2 || outsideFaceLowerL3 || outsideFaceLowerL4 || 
        outsideFaceLowerR1 || outsideFaceLowerR2 || outsideFaceLowerR3 || outsideFaceLowerR4) {
        // sprite-size-y prior to adjustment serves exactly as the value used to adjust coordinate offset.
        pom_corner_texcoord.y -= float(pom_sprite_size.y) / float(atlasSize.y);
        pom_tangent_pos.y = pom_sprite_size.y + pom_tangent_pos.y;
    }
    
    if (insideFaceUpperL1 || insideFaceUpperL2 || insideFaceUpperR1 || insideFaceUpperR2 || insideFaceUpperR3 || insideFaceUpperR4 || insideFace01 || insideFace02 || 
        outsideFace1 || outsideFace2 || 
        outsideFaceUpperR1 || outsideFaceUpperR2 || outsideFaceUpperR3 || outsideFaceUpperR4 || 
        outsideFaceUpperL1 || outsideFaceUpperL2 || outsideFaceUpperL3 || outsideFaceUpperL4 || 
        insideFaceLower1 || insideFaceLower2 || insideFaceLowerR1 || insideFaceLowerR2 || 
        insideFaceLowerL1 || insideFaceLowerL2 || insideFaceLowerL3 || insideFaceLowerL4 || 
        outsideFaceUSD1 || outsideFaceUSD2 || 
        outsideFaceLowerL1 || outsideFaceLowerL2 || outsideFaceLowerL3 || outsideFaceLowerL4 || 
        outsideFaceLowerR1 || outsideFaceLowerR2 || outsideFaceLowerR3 || outsideFaceLowerR4) pom_sprite_size.y *= 2;
    
    if (insideFaceUpperR1 || insideFaceUpperR2 || insideFaceUpperR3 || insideFaceUpperR4 || 
        outsideFaceUpperR1 || outsideFaceUpperR2 || outsideFaceUpperR3 || outsideFaceUpperR4 || 
        outsideFaceUpperL1 || outsideFaceUpperL2 || outsideFaceUpperL3 || outsideFaceUpperL4 || 
        insideFaceLowerL1 || insideFaceLowerL2 || insideFaceLowerL3 || insideFaceLowerL4 || 
        outsideFaceLowerL1 || outsideFaceLowerL2 || outsideFaceLowerL3 || outsideFaceLowerL4 || 
        outsideFaceLowerR1 || outsideFaceLowerR2 || outsideFaceLowerR3 || outsideFaceLowerR4) pom_sprite_size.x *= 2;
    */
    //return true;
}
