Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #version 130
- precision mediump float;
- #define SAMPLER_ARRAY sampler2DArray
- #define TEXTURE_ARRAY texture
- #define SAMPLER_2D sampler2D
- #define TEXTURE_2D texture
- #define ATLAS_FILTER_MODE 11
- #define DISTANCE_ATLAS 1
- uniform vec4 m_Color;
- varying vec4 color;
- #ifdef DISTANCE_MAP
- uniform sampler2DArray m_DistanceMap;
- varying vec3 texCoord;
- #endif
- #ifdef DISTANCE_ATLAS
- uniform sampler2D m_DistanceAtlas;
- varying vec2 texCoord;
- uniform int m_AtlasWidth;
- uniform int m_AtlasHeight;
- #if (__VERSION__ == 120)
- varying vec2 atlasTileOffsetF;
- varying vec2 atlasTileSizeF;
- ivec2 atlasTileOffset;
- ivec2 atlasTileSize;
- #define TEXEL_FETCH(sampler, coord, lod) texelFetch120(sampler, coord, lod)
- vec4 texelFetch120(sampler2D tex, ivec2 coord, int lod) {
- ivec2 size = ivec2(m_AtlasWidth, m_AtlasHeight);
- vec2 uv = vec2(((coord.x << lod) + 0.5) / size.x, ((coord.y << lod) + 0.5) / size.y);
- return texture2D(tex, uv);
- }
- void getTextureAtlasLayer() {
- atlasTileOffset = ivec2(round(atlasTileOffsetF));
- atlasTileSize = ivec2(round(atlasTileSizeF));
- }
- #define GET_TEXTURE_ATLAS_LAYER getTextureAtlasLayer()
- #elif (__VERSION__ >= 130)
- flat in ivec2 atlasTileOffset;
- flat in ivec2 atlasTileSize;
- #define GET_TEXTURE_ATLAS_LAYER /* empty */
- #define TEXEL_FETCH(sampler, coord, lod) texelFetch(sampler, coord, lod)
- #endif
- #if (__VERSION__ == 120)
- int iclamp(int x, int minVal, int maxVal) {
- if(x < minVal)
- return minVal;
- if(x > maxVal)
- return maxVal;
- return x;
- //return int(clamp(float(x), float(minVal), float(maxVal)));
- }
- #else
- #define iclamp(x, minVal, maxVal) clamp(x, minVal, maxVal)
- #endif
- #define ATLAS_MAG_MIN_FILTER (ATLAS_FILTER_MODE & 0x7)
- #define ATLAS_WRAP_MODE ((ATLAS_FILTER_MODE & 0x8) >> 3)
- #if (ATLAS_MAG_MIN_FILTER == 0) // MagFilter.Nearest + MinFilter.NearestNoMipMaps
- #define TEXTURE_ATLAS getAtlasNearestNoMipmap
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 1) // MagFilter.Nearest + MinFilter.NearestNearestMipMap
- #define TEXTURE_ATLAS getAtlasNearestMipMapNearest
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 2) // MagFilter.Nearest + MinFilter.NearestLinearMipMap
- #define TEXTURE_ATLAS getAtlasNearestMipMapLinear
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 3) // MagFilter.Bilinear + MinFilter.BilinearNoMipMaps
- #define TEXTURE_ATLAS getAtlasBilinearNoMipMaps
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 4) // MagFilter.Bilinear + MinFilter.NearestNearestMipMap
- #define TEXTURE_ATLAS getAtlasBilinearNearestMipMapNearest
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 5) // MagFilter.Bilinear + MinFilter.NearestLinearMipMap
- #define TEXTURE_ATLAS getAtlasBilinearNearestMipMapLinear
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 6) // MagFilter.Bilinear + MinFilter.BilinearNearestMipMap
- #define TEXTURE_ATLAS getAtlasBilinearMipMapNearest
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- #if (ATLAS_MAG_MIN_FILTER == 7) // MagFilter.Bilinear + MinFilter.Trilinear
- #define TEXTURE_ATLAS getAtlasTrilinearMipMap
- #define TEXTURE_ATLAS_ALPHA getAtlasNearestNoMipmap
- #endif
- // This finctions may give edge issues
- // Use TEXTURE_ATLAS to correct filtering
- #define TEXTURE_ATLAS_WRAPPED getAtlasWrapped
- #define TEXTURE_ATLAS_SIMPLE getAtlasSimple
- /******************** Filtering routine *********************************************/
- // Transform tile texcoords to the atlas
- vec2 getAtlasCoords(sampler2D atlas, vec2 uv) {
- ivec2 size = ivec2(m_AtlasWidth, m_AtlasHeight); // textureSize(atlas, 0);
- return vec2((uv.x * atlasTileSize.x + atlasTileOffset.x) / size.x, (uv.y * atlasTileSize.y + atlasTileOffset.y) / size.y);
- }
- // Wrapping texcoords inside the atlas tile
- vec2 getAtlasCoordsWrapped(sampler2D atlas, vec2 uv) {
- #if (ATLAS_WRAP_MODE == 0)
- vec2 wrappedUV = fract(uv);
- #endif
- #if (ATLAS_WRAP_MODE == 1)
- vec2 wrappedUV = clamp(uv, vec2(0), vec2(1));
- #endif
- return getAtlasCoords(atlas, wrappedUV);
- }
- // Wrapping pixel inside the atlas tile
- ivec2 wrapTilePixel(ivec2 pixel, ivec2 tileOffset, ivec2 tileSize) {
- #if (ATLAS_WRAP_MODE == 0)
- ivec2 wrappedPixel = ivec2(mod(pixel.x, tileSize.x), mod(pixel.y, tileSize.y));
- #endif
- #if (ATLAS_WRAP_MODE == 1)
- ivec2 wrappedPixel = ivec2(iclamp(pixel.x, 1, tileSize.x - 2), iclamp(pixel.y, 1, tileSize.y - 2));
- #endif
- return wrappedPixel + tileOffset;
- }
- // Compute nearest pixel at the atlas
- ivec2 computeAtlasNearestPixel(vec2 uv, int level) {
- ivec2 tileOffset = ivec2(atlasTileOffset.x >> level, atlasTileOffset.y >> level);
- ivec2 tileSize = ivec2(atlasTileSize.x >> level, atlasTileSize.y >> level);
- ivec2 pixel = ivec2(floor(uv.x * tileSize.x), floor(uv.y * tileSize.y));
- pixel = wrapTilePixel(pixel, tileOffset, tileSize);
- return pixel;
- }
- // Compute nearest pixels at the atlas for bilinear filtering
- vec2 computeAtlasBilinearPixels(vec2 uv, int level, out ivec2 pixelPrev, out ivec2 pixelNext) {
- ivec2 tileOffset = ivec2(atlasTileOffset.x >> level, atlasTileOffset.y >> level);
- ivec2 tileSize = ivec2(atlasTileSize.x >> level, atlasTileSize.y >> level);
- // Texels centering
- vec2 pixel = vec2(uv.x * tileSize.x - 0.5, uv.y * tileSize.y - 0.5);
- // Get atlas nearest pixels
- pixelPrev = ivec2(floor(pixel.x), floor(pixel.y));
- pixelNext = ivec2(ceil(pixel.x), ceil(pixel.y));
- // Compute interpolation factor
- vec2 pixelInt = pixel - pixelPrev;
- // Wrap pixels inside the atlas tile
- pixelPrev = wrapTilePixel(pixelPrev, tileOffset, tileSize);
- pixelNext = wrapTilePixel(pixelNext, tileOffset, tileSize);
- return pixelInt;
- }
- // Get bilinear interpolated color from the atlas
- vec4 getAtlasBilinearTextel(sampler2D atlas, vec2 uv, int level) {
- ivec2 pixelPrev, pixelNext;
- vec2 pixelInt = computeAtlasBilinearPixels(uv, level, pixelPrev, pixelNext);
- // Compute bilinear interpolation
- vec4 c0 = TEXEL_FETCH(atlas, ivec2(pixelPrev.x, pixelPrev.y), level);
- vec4 c1 = TEXEL_FETCH(atlas, ivec2(pixelNext.x, pixelPrev.y), level);
- vec4 c2 = TEXEL_FETCH(atlas, ivec2(pixelPrev.x, pixelNext.y), level);
- vec4 c3 = TEXEL_FETCH(atlas, ivec2(pixelNext.x, pixelNext.y), level);
- return mix(mix(c0, c1, pixelInt.x), mix(c2, c3, pixelInt.x), pixelInt.y);
- }
- // Get nearest color from the atlas
- vec4 getAtlasNearestTextel(sampler2D atlas, vec2 uv, int level) {
- ivec2 pixel = computeAtlasNearestPixel(uv, level);
- return TEXEL_FETCH(atlas, pixel, level); // Lookup texels directly
- }
- // Mathemagically estimates mipmap level
- float getMipMapLevel(in vec2 uv) {
- int tileSize = atlasTileSize.x; // TODO use both sizes for rectangular textures
- // dFdx and dFdy use texcoors in texel units
- vec2 dx_vtc = dFdx(uv * tileSize);
- vec2 dy_vtc = dFdy(uv * tileSize);
- float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
- float mml = 0.5 * log2(delta_max_sqr);
- return clamp(mml, 0, log2(tileSize));
- }
- // Get nearest mipmap level for atlas texture
- int getAtlasNearestMipMapLevel(vec2 uv) {
- float level = getMipMapLevel(uv);
- return int(floor(level));
- }
- // Computes nearest mipmap levels for atlas mipmap linear filtering
- float computeAtlasLinearMipMapLevels(vec2 uv, out int levelPrev, out int levelNext) {
- float level = getMipMapLevel(uv);
- levelPrev = int(floor(level));
- levelNext = int(ceil(level));
- float levelInt = level - levelPrev; // interpolation factor
- return levelInt;
- }
- /******************** Filtering methods functions *************************************/
- vec4 getAtlasNearestNoMipmap(sampler2D atlas, vec2 uv) {
- return getAtlasNearestTextel(atlas, uv, 0);
- }
- vec4 getAtlasNearestMipMapNearest(sampler2D atlas, vec2 uv) {
- int level = getAtlasNearestMipMapLevel(uv);
- return getAtlasNearestTextel(atlas, uv, level);
- }
- vec4 getAtlasNearestMipMapLinear(sampler2D atlas, vec2 uv) {
- int levelPrev, levelNext;
- float levelInt = computeAtlasLinearMipMapLevels(uv, levelPrev, levelNext);
- ivec2 pixelPrev = computeAtlasNearestPixel(uv, levelPrev);
- if(levelNext == 0) { // Magnification
- return TEXEL_FETCH(atlas, pixelPrev, levelPrev);
- } else { // Minification
- ivec2 pixelNext = pixelPrev / 2; // Don't calculate again
- // Compute linear imterpolation from mipmaps
- vec4 c0 = TEXEL_FETCH(atlas, pixelPrev, levelPrev);
- vec4 c1 = TEXEL_FETCH(atlas, pixelNext, levelNext);
- return mix(c0, c1, levelInt);
- }
- }
- vec4 getAtlasBilinearNearestMipMapNearest(sampler2D atlas, vec2 uv) {
- int level = getAtlasNearestMipMapLevel(uv);
- if(level == 0) { // Magnification
- return getAtlasBilinearTextel(atlas, uv, 0);
- } else { // Minification
- return getAtlasNearestTextel(atlas, uv, level);
- }
- }
- vec4 getAtlasBilinearNearestMipMapLinear(sampler2D atlas, vec2 uv) {
- int levelPrev, levelNext;
- float levelInt = computeAtlasLinearMipMapLevels(uv, levelPrev, levelNext);
- if(levelNext == 0) { // Magnification
- return getAtlasBilinearTextel(atlas, uv, 0);
- } else { // Minification
- ivec2 pixelPrev = computeAtlasNearestPixel(uv, levelPrev);
- ivec2 pixelNext = pixelPrev / 2; // Don't calculate again
- // Compute linear imterpolation from mipmaps
- vec4 c0 = TEXEL_FETCH(atlas, pixelPrev, levelPrev);
- vec4 c1 = TEXEL_FETCH(atlas, pixelNext, levelNext);
- return mix(c0, c1, levelInt);
- }
- }
- vec4 getAtlasBilinearNoMipMaps(sampler2D atlas, vec2 uv) {
- return getAtlasBilinearTextel(atlas, uv, 0);
- }
- vec4 getAtlasBilinearMipMapNearest(sampler2D atlas, vec2 uv) {
- int level = getAtlasNearestMipMapLevel(uv);
- return getAtlasBilinearTextel(atlas, uv, level);
- }
- vec4 getAtlasTrilinearMipMap(sampler2D atlas, vec2 uv) {
- int levelPrev, levelNext;
- float levelInt = computeAtlasLinearMipMapLevels(uv, levelPrev, levelNext);
- if(levelNext == 0) { // Magnification
- return getAtlasBilinearTextel(atlas, uv, 0);
- } else { // Minification
- // Compute linear imterpolation from mipmaps
- vec4 c0 = getAtlasBilinearTextel(atlas, uv, levelPrev);
- vec4 c1 = getAtlasBilinearTextel(atlas, uv, levelNext);
- return mix(c0, c1, levelInt);
- }
- }
- vec4 getAtlasSimple(sampler2D atlas, vec2 uv) {
- // Can be used for atlas texture with no filtering
- // And texCoords limited to [0..1]
- uv = getAtlasCoords(atlas, uv);
- return TEXTURE_2D(atlas, uv);
- }
- vec4 getAtlasWrapped(sampler2D atlas, vec2 uv) {
- // Can be used for atlas texture with no filtering
- uv = getAtlasCoordsWrapped(atlas, uv);
- return TEXTURE_2D(atlas, uv);
- }
- #endif
- float getDistance() {
- #ifdef DISTANCE_MAP
- return TEXTURE_ARRAY(m_DistanceMap, texCoord).a;
- #endif
- #ifdef DISTANCE_ATLAS
- GET_TEXTURE_ATLAS_LAYER;
- return TEXTURE_ATLAS(m_DistanceAtlas, texCoord).a;
- #endif
- }
- void main(){
- vec4 fColor = color;
- if(fColor.a == 0.0) { // if have 0 alpha value, use material color
- fColor = m_Color;
- }
- #ifdef APPLY_COLOR
- else {
- fColor *= m_Color;
- }
- #endif
- float dist = getDistance();
- #ifdef FLAT_ALPHA
- if(dist < 0.5)
- discard;
- #else
- float alpha = smoothstep(0.25, 0.75, dist);
- fColor.a *= alpha;
- #endif
- gl_FragColor = fColor;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement