tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GLES1Shaders.inc (34539B)


      1 //
      2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // GLES1Shaders.inc: Defines GLES1 emulation shader.
      8 
      9 // The following variables are added in GLES1Renderer::initializeRendererProgram
     10 // bool clip_plane_enables
     11 // bool enable_alpha_test
     12 // bool enable_clip_planes
     13 // bool enable_color_material
     14 // bool enable_draw_texture
     15 // bool enable_fog
     16 // bool enable_lighting
     17 // bool enable_normalize
     18 // bool enable_rescale_normal
     19 // bool enable_texture_2d[kMaxTexUnits]
     20 // bool enable_texture_cube_map[kMaxTexUnits]
     21 // bool light_enables[kMaxLights]
     22 // bool light_model_two_sided
     23 // bool point_rasterization
     24 // bool point_sprite_coord_replace
     25 // bool point_sprite_enabled
     26 // bool shade_model_flat
     27 // int texture_format[kMaxTexUnits];
     28 // int texture_env_mode[kMaxTexUnits];
     29 // int combine_rgb[kMaxTexUnits];
     30 // int combine_alpha[kMaxTexUnits];
     31 // int src0_rgb[kMaxTexUnits];
     32 // int src0_alpha[kMaxTexUnits];
     33 // int src1_rgb[kMaxTexUnits];
     34 // int src1_alpha[kMaxTexUnits];
     35 // int src2_rgb[kMaxTexUnits];
     36 // int src2_alpha[kMaxTexUnits];
     37 // int op0_rgb[kMaxTexUnits];
     38 // int op0_alpha[kMaxTexUnits];
     39 // int op1_rgb[kMaxTexUnits];
     40 // int op1_alpha[kMaxTexUnits];
     41 // int op2_rgb[kMaxTexUnits];
     42 // int op2_alpha[kMaxTexUnits];
     43 // int alpha_func;
     44 // int fog_mode;
     45 
     46 constexpr char kGLES1DrawVShaderHeader[] = R"(#version 300 es
     47 precision highp float;
     48 
     49 #define kMaxTexUnits 4
     50 #define kMaxLights   8
     51 )";
     52 
     53 constexpr char kGLES1DrawVShader[] = R"(
     54 
     55 in vec4 pos;
     56 in vec3 normal;
     57 in vec4 color;
     58 in float pointsize;
     59 in vec4 texcoord0;
     60 in vec4 texcoord1;
     61 in vec4 texcoord2;
     62 in vec4 texcoord3;
     63 
     64 uniform mat4 projection;
     65 uniform mat4 modelview;
     66 uniform mat4 modelview_invtr;
     67 uniform mat4 texture_matrix[kMaxTexUnits];
     68 
     69 // Point rasterization//////////////////////////////////////////////////////////
     70 
     71 uniform float point_size_min;
     72 uniform float point_size_max;
     73 uniform vec3 point_distance_attenuation;
     74 
     75 // Shading: flat shading, lighting, and materials///////////////////////////////
     76 
     77 uniform vec4 material_ambient;
     78 uniform vec4 material_diffuse;
     79 uniform vec4 material_specular;
     80 uniform vec4 material_emissive;
     81 uniform float material_specular_exponent;
     82 
     83 uniform vec4 light_model_scene_ambient;
     84 
     85 uniform vec4 light_ambients[kMaxLights];
     86 uniform vec4 light_diffuses[kMaxLights];
     87 uniform vec4 light_speculars[kMaxLights];
     88 uniform vec4 light_positions[kMaxLights];
     89 uniform vec3 light_directions[kMaxLights];
     90 uniform float light_spotlight_exponents[kMaxLights];
     91 uniform float light_spotlight_cutoff_angles[kMaxLights];
     92 uniform float light_attenuation_consts[kMaxLights];
     93 uniform float light_attenuation_linears[kMaxLights];
     94 uniform float light_attenuation_quadratics[kMaxLights];
     95 
     96 // GL_OES_draw_texture uniforms/////////////////////////////////////////////////
     97 
     98 uniform vec4 draw_texture_coords;
     99 uniform vec2 draw_texture_dims;
    100 uniform vec4 draw_texture_normalized_crop_rect[kMaxTexUnits];
    101 
    102 // Varyings/////////////////////////////////////////////////////////////////////
    103 
    104 out vec4 pos_varying;
    105 out vec3 normal_varying;
    106 out vec4 color_varying;
    107 flat out vec4 color_varying_flat;
    108 out vec4 texcoord0_varying;
    109 out vec4 texcoord1_varying;
    110 out vec4 texcoord2_varying;
    111 out vec4 texcoord3_varying;
    112 
    113 float posDot(vec3 a, vec3 b)
    114 {
    115    return max(dot(a, b), 0.0);
    116 }
    117 
    118 vec4 doLighting(vec4 vertexColor)
    119 {
    120    vec4 materialAmbientActual = material_ambient;
    121    vec4 materialDiffuseActual = material_diffuse;
    122 
    123    if (enable_color_material)
    124    {
    125        materialAmbientActual = vertexColor;
    126        materialDiffuseActual = vertexColor;
    127    }
    128 
    129    vec4 lightingResult = material_emissive + materialAmbientActual * light_model_scene_ambient;
    130 
    131    for (int i = 0; i < kMaxLights; i++)
    132    {
    133 
    134        if (!light_enables[i])
    135            continue;
    136 
    137        vec4 lightAmbient  = light_ambients[i];
    138        vec4 lightDiffuse  = light_diffuses[i];
    139        vec4 lightSpecular = light_speculars[i];
    140        vec4 lightPos      = light_positions[i];
    141        vec3 lightDir      = light_directions[i];
    142        float attConst     = light_attenuation_consts[i];
    143        float attLinear    = light_attenuation_linears[i];
    144        float attQuadratic = light_attenuation_quadratics[i];
    145        float spotAngle    = light_spotlight_cutoff_angles[i];
    146        float spotExponent = light_spotlight_exponents[i];
    147 
    148        vec3 toLight;
    149        if (lightPos.w == 0.0)
    150        {
    151            toLight = lightPos.xyz;
    152        }
    153        else
    154        {
    155            toLight = (lightPos.xyz / lightPos.w - pos_varying.xyz);
    156        }
    157 
    158        float lightDist = length(toLight);
    159        vec3 h          = normalize(toLight) + vec3(0.0, 0.0, 1.0);
    160        float ndotL     = posDot(normal_varying, normalize(toLight));
    161        float ndoth     = posDot(normal_varying, normalize(h));
    162 
    163        float specAtt;
    164 
    165        if (ndotL != 0.0)
    166        {
    167            specAtt = 1.0;
    168        }
    169        else
    170        {
    171            specAtt = 0.0;
    172        }
    173 
    174        float att;
    175 
    176        if (lightPos.w != 0.0)
    177        {
    178            float attDenom =
    179                (attConst + attLinear * lightDist + attQuadratic * lightDist * lightDist);
    180            att = 1.0 / attDenom;
    181        }
    182        else
    183        {
    184            att = 1.0;
    185        }
    186 
    187        float spot;
    188 
    189        float spotAngleCos = cos(radians(spotAngle));
    190        vec3 toSurfaceDir  = -normalize(toLight);
    191        float spotDot      = posDot(toSurfaceDir, normalize(lightDir));
    192 
    193        if (spotAngle == 180.0 || lightPos.w == 0.0)
    194        {
    195            spot = 1.0;
    196        }
    197        else
    198        {
    199            if (spotDot < spotAngleCos)
    200            {
    201                spot = 0.0;
    202            }
    203            else
    204            {
    205                spot = pow(spotDot, spotExponent);
    206            }
    207        }
    208 
    209        vec4 contrib = materialAmbientActual * lightAmbient;
    210        contrib += ndotL * materialDiffuseActual * lightDiffuse;
    211        if (ndoth > 0.0 && material_specular_exponent > 0.0)
    212        {
    213            contrib += specAtt * pow(ndoth, material_specular_exponent) * material_specular *
    214                       lightSpecular;
    215        }
    216        else
    217        {
    218            if (ndoth > 0.0)
    219            {
    220                contrib += specAtt * material_specular * lightSpecular;
    221            }
    222        }
    223        contrib *= att * spot;
    224        lightingResult += contrib;
    225    }
    226 
    227    return lightingResult;
    228 }
    229 
    230 const vec4 drawTextureVertices[6] = vec4[](
    231    vec4(0.0, 0.0, 0.0, 1.0),
    232    vec4(1.0, 0.0, 0.0, 1.0),
    233    vec4(1.0, 1.0, 0.0, 1.0),
    234    vec4(0.0, 0.0, 0.0, 1.0),
    235    vec4(1.0, 1.0, 0.0, 1.0),
    236    vec4(0.0, 1.0, 0.0, 1.0));
    237 
    238 vec4 drawTexturePosition(int vertexId)
    239 {
    240 
    241    float drawTexX = draw_texture_coords[0];
    242    float drawTexY = draw_texture_coords[1];
    243    float drawTexZ = draw_texture_coords[2];
    244    float drawTexW = draw_texture_dims[0];
    245    float drawTexH = draw_texture_dims[1];
    246 
    247    return vec4(drawTexX, drawTexY, drawTexZ, 0.0) +
    248           drawTextureVertices[vertexId] *
    249           vec4(drawTexW, drawTexH, 1.0, 1.0);
    250 }
    251 
    252 vec4 drawTextureTexCoord(int vertexId, int textureUnit)
    253 {
    254    float texCropU = draw_texture_normalized_crop_rect[textureUnit].x;
    255    float texCropV = draw_texture_normalized_crop_rect[textureUnit].y;
    256    float texCropW = draw_texture_normalized_crop_rect[textureUnit].z;
    257    float texCropH = draw_texture_normalized_crop_rect[textureUnit].w;
    258 
    259    return vec4(texCropU, texCropV, 0.0, 0.0) +
    260           drawTextureVertices[vertexId] *
    261           vec4(texCropW, texCropH, 0.0, 0.0);
    262 }
    263 
    264 vec4 calcWorldPosition(vec4 posInput)
    265 {
    266    return modelview * posInput;
    267 }
    268 
    269 vec4 calcNdcFromWorldPosition(vec4 worldPos)
    270 {
    271    return projection * worldPos;
    272 }
    273 
    274 float calcPointSize(vec4 ndcPos)
    275 {
    276    float dist         = length(ndcPos.z);
    277    float attConst     = point_distance_attenuation[0];
    278    float attLinear    = point_distance_attenuation[1];
    279    float attQuad      = point_distance_attenuation[2];
    280    float attPart      = attConst + attLinear * dist + attQuad * dist * dist;
    281    float attPointSize = pointsize / pow(attPart, 0.5);
    282 
    283    return clamp(attPointSize, point_size_min, point_size_max);
    284 }
    285 
    286 vec3 calcNormal(vec3 normalInput)
    287 {
    288    mat3 mvInvTr3 = mat3(modelview_invtr);
    289    vec3 result   = mvInvTr3 * normalInput;
    290 
    291    if (enable_rescale_normal)
    292    {
    293        float rescale   = 1.0;
    294        vec3 rescaleVec = vec3(mvInvTr3[2]);
    295        float len       = length(rescaleVec);
    296        if (len > 0.0)
    297        {
    298            rescale = 1.0 / len;
    299        }
    300        result *= rescale;
    301    }
    302 
    303    if (enable_normalize)
    304    {
    305        result = normalize(result);
    306    }
    307 
    308    return result;
    309 }
    310 
    311 void main()
    312 {
    313    if (enable_draw_texture)
    314    {
    315        int vertexId        = gl_VertexID;
    316        vec4 posDrawTexture = drawTexturePosition(vertexId);
    317 
    318        gl_Position = posDrawTexture;
    319        pos_varying = posDrawTexture;
    320 
    321        normal_varying = normal;
    322 
    323        gl_PointSize = pointsize;
    324 
    325        texcoord0_varying = drawTextureTexCoord(vertexId, 0);
    326        texcoord1_varying = drawTextureTexCoord(vertexId, 1);
    327        texcoord2_varying = drawTextureTexCoord(vertexId, 2);
    328        texcoord3_varying = drawTextureTexCoord(vertexId, 3);
    329    }
    330    else
    331    {
    332        vec4 worldPos = calcWorldPosition(pos);
    333        vec4 ndcPos   = calcNdcFromWorldPosition(worldPos);
    334 
    335        gl_Position = ndcPos;
    336        pos_varying = worldPos;
    337 
    338        normal_varying = calcNormal(normal);
    339 
    340        // Avoid calculating point size stuff
    341        // if we are not rendering points.
    342        if (point_rasterization)
    343        {
    344            gl_PointSize = calcPointSize(ndcPos);
    345        }
    346        else
    347        {
    348            gl_PointSize = pointsize;
    349        }
    350 
    351        texcoord0_varying = texture_matrix[0] * texcoord0;
    352        texcoord1_varying = texture_matrix[1] * texcoord1;
    353        texcoord2_varying = texture_matrix[2] * texcoord2;
    354        texcoord3_varying = texture_matrix[3] * texcoord3;
    355    }
    356 
    357    vec4 vertex_color = color;
    358 
    359    if (enable_lighting)
    360    {
    361        vertex_color = doLighting(color);
    362    }
    363 
    364    vertex_color = clamp(vertex_color, vec4(0), vec4(1));
    365 
    366    color_varying      = vertex_color;
    367    color_varying_flat = vertex_color;
    368 }
    369 )";
    370 
    371 constexpr char kGLES1DrawFShaderVersion[] = R"(#version 300 es
    372 )";
    373 
    374 constexpr char kGLES1DrawFShaderHeader[] = R"(precision highp float;
    375 
    376 // Defines for GL constants
    377 #define kMaxTexUnits                         4
    378 #define kMaxClipPlanes                       6
    379 
    380 #define kModulate                       0x2100
    381 #define kDecal                          0x2101
    382 #define kCombine                        0x8570
    383 #define kReplace                        0x1E01
    384 #define kBlend                          0x0BE2
    385 #define kAdd                            0x0104
    386 
    387 #define kAddSigned                      0x8574
    388 #define kInterpolate                    0x8575
    389 #define kSubtract                       0x84E7
    390 #define kDot3Rgb                        0x86AE
    391 #define kDot3Rgba                       0x86AF
    392 
    393 #define kAlpha                          0x1906
    394 #define kRGB                            0x1907
    395 #define kRGBA                           0x1908
    396 #define kLuminance                      0x1909
    397 #define kLuminanceAlpha                 0x190A
    398 
    399 #define kTexture                        0x1702
    400 #define kConstant                       0x8576
    401 #define kPrimaryColor                   0x8577
    402 #define kPrevious                       0x8578
    403 
    404 #define kSrcColor                       0x0300
    405 #define kOneMinusSrcColor               0x0301
    406 #define kSrcAlpha                       0x0302
    407 #define kOneMinusSrcAlpha               0x0303
    408 
    409 #define kLinear                         0x2601
    410 #define kExp                            0x0800
    411 #define kExp2                           0x0801
    412 
    413 #define kNever                          0x0200
    414 #define kLess                           0x0201
    415 #define kEqual                          0x0202
    416 #define kLequal                         0x0203
    417 #define kGreater                        0x0204
    418 #define kNotequal                       0x0205
    419 #define kGequal                         0x0206
    420 #define kAlways                         0x0207
    421 #define kZero                              0x0
    422 #define kOne                               0x1
    423 
    424 #define kAnd                            0u
    425 #define kAndInverted                    1u
    426 #define kAndReverse                     2u
    427 #define kClear                          3u
    428 #define kCopy                           4u
    429 #define kCopyInverted                   5u
    430 #define kEquiv                          6u
    431 #define kInvert                         7u
    432 #define kNand                           8u
    433 #define kNoop                           9u
    434 #define kNor                            10u
    435 #define kOr                             11u
    436 #define kOrInverted                     12u
    437 #define kOrReverse                      13u
    438 #define kSet                            14u
    439 #define kXor                            15u
    440 )";
    441 
    442 constexpr char kGLES1DrawFShaderUniformDefs[] = R"(
    443 
    444 // Texture units ///////////////////////////////////////////////////////////////
    445 
    446 // These are not arrays because hw support for arrays
    447 // of samplers is rather lacking.
    448 
    449 uniform sampler2D tex_sampler0;
    450 uniform samplerCube tex_cube_sampler0;
    451 
    452 uniform sampler2D tex_sampler1;
    453 uniform samplerCube tex_cube_sampler1;
    454 
    455 uniform sampler2D tex_sampler2;
    456 uniform samplerCube tex_cube_sampler2;
    457 
    458 uniform sampler2D tex_sampler3;
    459 uniform samplerCube tex_cube_sampler3;
    460 
    461 uniform vec4 texture_env_color[kMaxTexUnits];
    462 uniform float texture_env_rgb_scale[kMaxTexUnits];
    463 uniform float texture_env_alpha_scale[kMaxTexUnits];
    464 
    465 // Vertex attributes////////////////////////////////////////////////////////////
    466 
    467 in vec4 pos_varying;
    468 in vec3 normal_varying;
    469 in vec4 color_varying;
    470 flat in vec4 color_varying_flat;
    471 in vec4 texcoord0_varying;
    472 in vec4 texcoord1_varying;
    473 in vec4 texcoord2_varying;
    474 in vec4 texcoord3_varying;
    475 
    476 // Alpha test///////////////////////////////////////////////////////////////////
    477 
    478 uniform float alpha_test_ref;
    479 
    480 // Fog /////////////////////////////////////////////////////////////////////////
    481 
    482 uniform float fog_density;
    483 uniform float fog_start;
    484 uniform float fog_end;
    485 uniform vec4 fog_color;
    486 
    487 // User clip plane /////////////////////////////////////////////////////////////
    488 
    489 uniform vec4 clip_planes[kMaxClipPlanes];
    490 
    491 // Logic Op ////////////////////////////////////////////////////////////////////
    492 
    493 // Format is:
    494 // - 4x4 bits depicting the bit width of each channel of color output
    495 // - 4 bits for the op based on LogicalOperation's packing
    496 uniform highp uint logic_op;
    497 
    498 // Point rasterization//////////////////////////////////////////////////////////
    499 
    500 // GL_OES_draw_texture//////////////////////////////////////////////////////////
    501 )";
    502 
    503 constexpr char kGLES1DrawFShaderOutputDef[] = R"(
    504 out vec4 frag_color;
    505 )";
    506 
    507 constexpr char kGLES1DrawFShaderFramebufferFetchOutputDef[] = R"(
    508 inout vec4 frag_color;
    509 )";
    510 
    511 constexpr char kGLES1DrawFShaderFramebufferFetchNonCoherentOutputDef[] = R"(
    512 layout(noncoherent) inout vec4 frag_color;
    513 )";
    514 
    515 constexpr char kGLES1DrawFShaderFunctions[] = R"(
    516 
    517 bool doAlphaTest(vec4 currentFragment)
    518 {
    519    bool shouldPassAlpha = false;
    520    float incAlpha       = currentFragment.a;
    521 
    522    switch (alpha_func)
    523    {
    524        case kNever:
    525            shouldPassAlpha = false;
    526            break;
    527        case kLess:
    528            shouldPassAlpha = incAlpha < alpha_test_ref;
    529            break;
    530        case kLequal:
    531            shouldPassAlpha = incAlpha <= alpha_test_ref;
    532            break;
    533        case kEqual:
    534            shouldPassAlpha = incAlpha == alpha_test_ref;
    535            break;
    536        case kGequal:
    537            shouldPassAlpha = incAlpha >= alpha_test_ref;
    538            break;
    539        case kGreater:
    540            shouldPassAlpha = incAlpha > alpha_test_ref;
    541            break;
    542        case kNotequal:
    543            shouldPassAlpha = incAlpha != alpha_test_ref;
    544            break;
    545        case kAlways:
    546        default:
    547            shouldPassAlpha = true;
    548            break;
    549    }
    550 
    551    return shouldPassAlpha;
    552 }
    553 
    554 bool doClipPlaneTest()
    555 {
    556    bool res = true;
    557 
    558    for (int i = 0; i < kMaxClipPlanes; i++)
    559    {
    560        if (clip_plane_enables[i])
    561        {
    562            float dist = dot(clip_planes[i].xyz, pos_varying.xyz) + clip_planes[i].w * pos_varying.w;
    563            res        = res && (dist >= 0.0);
    564        }
    565    }
    566 
    567    return res;
    568 }
    569 
    570 vec4 doFog(vec4 currentFragment)
    571 {
    572 
    573    float eyeDist = -pos_varying.z / pos_varying.w;
    574    float f       = 1.0;
    575    switch (fog_mode)
    576    {
    577        case kExp:
    578            f = exp(-fog_density * eyeDist);
    579            break;
    580        case kExp2:
    581            f = exp(-(pow(fog_density * eyeDist, 2.0)));
    582            break;
    583        case kLinear:
    584            f = (fog_end - eyeDist) / (fog_end - fog_start);
    585            break;
    586        default:
    587            break;
    588    }
    589 
    590    f = clamp(f, 0.0, 1.0);
    591    vec4 result = vec4(f * currentFragment.rgb + (1.0 - f) * fog_color.rgb, currentFragment.a);
    592    return result;
    593 }
    594 )";
    595 
    596 constexpr char kGLES1DrawFShaderLogicOpFramebufferFetchDisabled[] = R"(
    597 vec4 applyLogicOp(vec4 currentFragment)
    598 {
    599    return currentFragment;
    600 }
    601 )";
    602 
    603 // applyLogicOp takes logic-op information from a packed uniform and applies it to the color
    604 // attachment using framebuffer fetch.  See the description of logic_op above for the format of the
    605 // uniform.
    606 //
    607 // In particular, 4 bits in logic_op (at offset 16) contain the packed logical operation (of
    608 // LogicalOperation type).  Based on the selected operation, the formula specified in the spec is
    609 // applied (applied as bitwise operations on unorm values).
    610 constexpr char kGLES1DrawFShaderLogicOpFramebufferFetchEnabled[] = R"(
    611 vec4 applyLogicOp(vec4 currentFragment)
    612 {
    613    vec4 previousFragment = frag_color;
    614 
    615    mediump uvec4 channelWidths = uvec4(logic_op & 0xFu,
    616                                        logic_op >> 4u & 0xFu,
    617                                        logic_op >> 8u & 0xFu,
    618                                        logic_op >> 12u & 0xFu);
    619 
    620    mediump uvec4 channelMasks = (uvec4(1) << channelWidths) - 1u;
    621 
    622    mediump uvec4 src = uvec4(round(currentFragment * vec4(channelMasks)));
    623    mediump uvec4 dst = uvec4(round(previousFragment * vec4(channelMasks)));
    624    mediump uvec4 result;
    625 
    626    switch (logic_op >> 16u & 0xFu)
    627    {
    628        case kAnd:
    629            result = src & dst;
    630            break;
    631        case kAndInverted:
    632            result = ~src & dst;
    633            break;
    634        case kAndReverse:
    635            result = src & ~dst;
    636            break;
    637        case kClear:
    638            result = uvec4(0);
    639            break;
    640        case kCopy:
    641            result = src;
    642            break;
    643        case kCopyInverted:
    644            result = ~src;
    645            break;
    646        case kEquiv:
    647            result = ~(src ^ dst);
    648            break;
    649        case kInvert:
    650            result = ~dst;
    651            break;
    652        case kNand:
    653            result = ~(src & dst);
    654            break;
    655        case kNoop:
    656            result = dst;
    657            break;
    658        case kNor:
    659            result = ~(src | dst);
    660            break;
    661        case kOr:
    662            result = src | dst;
    663            break;
    664        case kOrInverted:
    665            result = ~src | dst;
    666            break;
    667        case kOrReverse:
    668            result = src | ~dst;
    669            break;
    670        case kSet:
    671            result = channelMasks;
    672            break;
    673        case kXor:
    674            result = src ^ dst;
    675            break;
    676    }
    677 
    678    result &= channelMasks;
    679 
    680    // Avoid division by zero for formats without alpha
    681    channelMasks.a = max(channelMasks.a, 1u);
    682 
    683    return vec4(result) / vec4(channelMasks);
    684 }
    685 )";
    686 
    687 constexpr char kGLES1DrawFShaderMultitexturing[] = R"(
    688 
    689 bool isTextureUnitEnabled(int unit)
    690 {
    691    return enable_texture_2d[unit] || enable_texture_cube_map[unit];
    692 }
    693 
    694 vec4 getTextureColor(int unit)
    695 {
    696    vec4 res;
    697 
    698    switch (unit)
    699    {
    700        case 0:
    701            if (enable_texture_2d[0])
    702            {
    703                res = texture(tex_sampler0, texcoord0_varying.xy);
    704            }
    705            else if (enable_texture_cube_map[0])
    706            {
    707                res = texture(tex_cube_sampler0, texcoord0_varying.xyz);
    708            }
    709            break;
    710        case 1:
    711            if (enable_texture_2d[1])
    712            {
    713                res = texture(tex_sampler1, texcoord1_varying.xy);
    714            }
    715            else if (enable_texture_cube_map[1])
    716            {
    717                res = texture(tex_cube_sampler1, texcoord1_varying.xyz);
    718            }
    719            break;
    720        case 2:
    721            if (enable_texture_2d[2])
    722            {
    723                res = texture(tex_sampler2, texcoord2_varying.xy);
    724            }
    725            else if (enable_texture_cube_map[2])
    726            {
    727                res = texture(tex_cube_sampler2, texcoord2_varying.xyz);
    728            }
    729            break;
    730        case 3:
    731            if (enable_texture_2d[3])
    732            {
    733                res = texture(tex_sampler3, texcoord3_varying.xy);
    734            }
    735            else if (enable_texture_cube_map[3])
    736            {
    737                // TODO: Weird stuff happens
    738                // res = texture(tex_cube_sampler3, texcoord3_varying.xyz);
    739            }
    740            break;
    741        default:
    742            break;
    743    }
    744 
    745    return res;
    746 }
    747 
    748 vec4 getPointSpriteTextureColor(int unit)
    749 {
    750    vec4 res;
    751 
    752    switch (unit)
    753    {
    754        case 0:
    755            if (enable_texture_2d[0])
    756            {
    757                res = texture(tex_sampler0, gl_PointCoord.xy);
    758            }
    759            break;
    760        case 1:
    761            if (enable_texture_2d[1])
    762            {
    763                res = texture(tex_sampler1, gl_PointCoord.xy);
    764            }
    765            break;
    766        case 2:
    767            if (enable_texture_2d[2])
    768            {
    769                res = texture(tex_sampler2, gl_PointCoord.xy);
    770            }
    771            break;
    772        case 3:
    773            if (enable_texture_2d[3])
    774            {
    775                res = texture(tex_sampler3, gl_PointCoord.xy);
    776            }
    777            break;
    778        default:
    779            break;
    780    }
    781 
    782    return res;
    783 }
    784 
    785 vec3 textureCombineSrcnOpnRgb(int srcnRgb,
    786                              int opnRgb,
    787                              vec4 textureEnvColor,
    788                              vec4 vertexColor,
    789                              vec4 texturePrevColor,
    790                              vec4 textureColor)
    791 {
    792    vec3 res;
    793    vec4 op;
    794 
    795    switch (srcnRgb)
    796    {
    797        case kTexture:
    798            op = textureColor;
    799            break;
    800        case kConstant:
    801            op = textureEnvColor;
    802            break;
    803        case kPrimaryColor:
    804            op = vertexColor;
    805            break;
    806        case kPrevious:
    807            op = texturePrevColor;
    808            break;
    809        default:
    810            op = texturePrevColor;
    811            break;
    812    }
    813 
    814    switch (opnRgb)
    815    {
    816        case kSrcColor:
    817            res = op.rgb;
    818            break;
    819        case kOneMinusSrcColor:
    820            res = 1.0 - op.rgb;
    821            break;
    822        case kSrcAlpha:
    823            res = vec3(op.a, op.a, op.a);
    824            break;
    825        case kOneMinusSrcAlpha:
    826            res = vec3(1.0 - op.a, 1.0 - op.a, 1.0 - op.a);
    827            break;
    828        default:
    829            break;
    830    }
    831 
    832    return res;
    833 }
    834 
    835 float textureCombineSrcnOpnAlpha(int srcn,
    836                                 int opn,
    837                                 vec4 textureEnvColor,
    838                                 vec4 vertexColor,
    839                                 vec4 texturePrevColor,
    840                                 vec4 textureColor)
    841 {
    842    float res;
    843    vec4 op;
    844 
    845    switch (srcn)
    846    {
    847        case kTexture:
    848            op = textureColor;
    849            break;
    850        case kConstant:
    851            op = textureEnvColor;
    852            break;
    853        case kPrimaryColor:
    854            op = vertexColor;
    855            break;
    856        case kPrevious:
    857            op = texturePrevColor;
    858            break;
    859        default:
    860            op = texturePrevColor;
    861            break;
    862    }
    863 
    864    switch (opn)
    865    {
    866        case kSrcAlpha:
    867            res = op.a;
    868            break;
    869        case kOneMinusSrcAlpha:
    870            res = 1.0 - op.a;
    871            break;
    872        default:
    873            break;
    874    }
    875 
    876    return res;
    877 }
    878 
    879 vec4 textureCombine(int combineRgb,
    880                    int combineAlpha,
    881                    int src0Rgb,
    882                    int src0Alpha,
    883                    int src1Rgb,
    884                    int src1Alpha,
    885                    int src2Rgb,
    886                    int src2Alpha,
    887                    int op0Rgb,
    888                    int op0Alpha,
    889                    int op1Rgb,
    890                    int op1Alpha,
    891                    int op2Rgb,
    892                    int op2Alpha,
    893                    vec4 textureEnvColor,
    894                    float rgbScale,
    895                    float alphaScale,
    896                    vec4 vertexColor,
    897                    vec4 texturePrevColor,
    898                    vec4 textureColor)
    899 {
    900 
    901    vec3 resRgb;
    902    float resAlpha;
    903 
    904    vec3 arg0Rgb;
    905    float arg0Alpha;
    906    vec3 arg1Rgb;
    907    float arg1Alpha;
    908    vec3 arg2Rgb;
    909    float arg2Alpha;
    910    float dotVal;
    911 
    912    arg0Rgb   = textureCombineSrcnOpnRgb(src0Rgb, op0Rgb, textureEnvColor, vertexColor,
    913                                       texturePrevColor, textureColor);
    914    arg0Alpha = textureCombineSrcnOpnAlpha(src0Alpha, op0Alpha, textureEnvColor, vertexColor,
    915                                           texturePrevColor, textureColor);
    916 
    917    if (combineRgb != kReplace)
    918    {
    919        arg1Rgb = textureCombineSrcnOpnRgb(src1Rgb, op1Rgb, textureEnvColor, vertexColor,
    920                                           texturePrevColor, textureColor);
    921    }
    922 
    923    if (combineAlpha != kReplace)
    924    {
    925        arg1Alpha = textureCombineSrcnOpnAlpha(src1Alpha, op1Alpha, textureEnvColor, vertexColor,
    926                                               texturePrevColor, textureColor);
    927    }
    928 
    929    if (combineRgb == kInterpolate)
    930    {
    931        arg2Rgb = textureCombineSrcnOpnRgb(src2Rgb, op2Rgb, textureEnvColor, vertexColor,
    932                                           texturePrevColor, textureColor);
    933    }
    934 
    935    if (combineAlpha == kInterpolate)
    936    {
    937        arg2Alpha = textureCombineSrcnOpnAlpha(src2Alpha, op2Alpha, textureEnvColor, vertexColor,
    938                                               texturePrevColor, textureColor);
    939    }
    940 
    941    switch (combineRgb)
    942    {
    943        case kReplace:
    944            resRgb = arg0Rgb;
    945            break;
    946        case kModulate:
    947            resRgb = arg0Rgb * arg1Rgb;
    948            break;
    949        case kAdd:
    950            resRgb = arg0Rgb + arg1Rgb;
    951            break;
    952        case kAddSigned:
    953            resRgb = arg0Rgb + arg1Rgb - 0.5;
    954            break;
    955        case kInterpolate:
    956            resRgb = arg0Rgb * arg2Rgb + arg1Rgb * (1.0 - arg2Rgb);
    957            break;
    958        case kSubtract:
    959            resRgb = arg0Rgb - arg1Rgb;
    960            break;
    961        default:
    962            break;
    963    }
    964 
    965    switch (combineAlpha)
    966    {
    967        case kReplace:
    968            resAlpha = arg0Alpha;
    969            break;
    970        case kModulate:
    971            resAlpha = arg0Alpha * arg1Alpha;
    972            break;
    973        case kAdd:
    974            resAlpha = arg0Alpha + arg1Alpha;
    975            break;
    976        case kAddSigned:
    977            resAlpha = arg0Alpha + arg1Alpha - 0.5;
    978            break;
    979        case kInterpolate:
    980            resAlpha = arg0Alpha * arg2Alpha + arg1Alpha * (1.0 - arg2Alpha);
    981            break;
    982        case kSubtract:
    983            resAlpha = arg0Alpha - arg1Alpha;
    984            break;
    985        default:
    986            break;
    987    }
    988 
    989    if (combineRgb == kDot3Rgb || combineRgb == kDot3Rgba)
    990    {
    991        dotVal = 4.0 * dot(arg0Rgb - 0.5, arg1Rgb - 0.5);
    992 
    993        if (combineRgb == kDot3Rgb)
    994        {
    995            return vec4(dotVal, dotVal, dotVal, resAlpha);
    996        }
    997        else
    998        {
    999            return vec4(dotVal, dotVal, dotVal, dotVal);
   1000        }
   1001    }
   1002    else
   1003    {
   1004        return vec4(resRgb, resAlpha);
   1005    }
   1006 }
   1007 
   1008 vec4 textureFunction(int unit,
   1009                     int texFormat,
   1010                     int envMode,
   1011                     int combineRgb,
   1012                     int combineAlpha,
   1013                     int src0Rgb,
   1014                     int src0Alpha,
   1015                     int src1Rgb,
   1016                     int src1Alpha,
   1017                     int src2Rgb,
   1018                     int src2Alpha,
   1019                     int op0Rgb,
   1020                     int op0Alpha,
   1021                     int op1Rgb,
   1022                     int op1Alpha,
   1023                     int op2Rgb,
   1024                     int op2Alpha,
   1025                     vec4 textureEnvColor,
   1026                     float rgbScale,
   1027                     float alphaScale,
   1028                     vec4 vertexColor,
   1029                     vec4 texturePrevColor,
   1030                     vec4 textureColor)
   1031 {
   1032 
   1033    if (!isTextureUnitEnabled(unit))
   1034    {
   1035        return texturePrevColor;
   1036    }
   1037 
   1038    vec4 res;
   1039 
   1040    switch (envMode)
   1041    {
   1042        case kReplace:
   1043            switch (texFormat)
   1044            {
   1045                case kAlpha:
   1046                    res.rgb = texturePrevColor.rgb;
   1047                    res.a   = textureColor.a;
   1048                    break;
   1049                case kRGBA:
   1050                case kLuminanceAlpha:
   1051                    res.rgba = textureColor.rgba;
   1052                    break;
   1053                case kRGB:
   1054                case kLuminance:
   1055                default:
   1056                    res.rgb = textureColor.rgb;
   1057                    res.a   = texturePrevColor.a;
   1058                    break;
   1059            }
   1060            break;
   1061        case kModulate:
   1062            switch (texFormat)
   1063            {
   1064                case kAlpha:
   1065                    res.rgb = texturePrevColor.rgb;
   1066                    res.a   = texturePrevColor.a * textureColor.a;
   1067                    break;
   1068                case kRGBA:
   1069                case kLuminanceAlpha:
   1070                    res.rgba = texturePrevColor.rgba * textureColor.rgba;
   1071                    break;
   1072                case kRGB:
   1073                case kLuminance:
   1074                default:
   1075                    res.rgb = texturePrevColor.rgb * textureColor.rgb;
   1076                    res.a   = texturePrevColor.a;
   1077                    break;
   1078            }
   1079            break;
   1080        case kDecal:
   1081            switch (texFormat)
   1082            {
   1083                case kRGB:
   1084                    res.rgb = textureColor.rgb;
   1085                    res.a   = texturePrevColor.a;
   1086                    break;
   1087                case kRGBA:
   1088                    res.rgb = texturePrevColor.rgb * (1.0 - textureColor.a) +
   1089                              textureColor.rgb * textureColor.a;
   1090                    res.a = texturePrevColor.a;
   1091                    break;
   1092                case kAlpha:
   1093                case kLuminance:
   1094                case kLuminanceAlpha:
   1095                default:
   1096                    res.rgb = texturePrevColor.rgb * textureColor.rgb;
   1097                    res.a   = texturePrevColor.a;
   1098                    break;
   1099            }
   1100            break;
   1101        case kBlend:
   1102            switch (texFormat)
   1103            {
   1104                case kAlpha:
   1105                    res.rgb = texturePrevColor.rgb;
   1106                    res.a   = textureColor.a * texturePrevColor.a;
   1107                    break;
   1108                case kLuminance:
   1109                case kRGB:
   1110                    res.rgb = texturePrevColor.rgb * (1.0 - textureColor.rgb) +
   1111                              textureEnvColor.rgb * textureColor.rgb;
   1112                    res.a = texturePrevColor.a;
   1113                    break;
   1114                case kLuminanceAlpha:
   1115                case kRGBA:
   1116                default:
   1117                    res.rgb = texturePrevColor.rgb * (1.0 - textureColor.rgb) +
   1118                              textureEnvColor.rgb * textureColor.rgb;
   1119                    res.a = textureColor.a * texturePrevColor.a;
   1120                    break;
   1121            }
   1122            break;
   1123        case kAdd:
   1124            switch (texFormat)
   1125            {
   1126                case kAlpha:
   1127                    res.rgb = texturePrevColor.rgb;
   1128                    res.a   = textureColor.a * texturePrevColor.a;
   1129                    break;
   1130                case kLuminance:
   1131                case kRGB:
   1132                    res.rgb = texturePrevColor.rgb + textureColor.rgb;
   1133                    res.a   = texturePrevColor.a;
   1134                    break;
   1135                case kLuminanceAlpha:
   1136                case kRGBA:
   1137                default:
   1138                    res.rgb = texturePrevColor.rgb + textureColor.rgb;
   1139                    res.a   = textureColor.a * texturePrevColor.a;
   1140                    break;
   1141            }
   1142            break;
   1143        case kCombine:
   1144            res = textureCombine(combineRgb, combineAlpha, src0Rgb, src0Alpha, src1Rgb, src1Alpha,
   1145                                 src2Rgb, src2Alpha, op0Rgb, op0Alpha, op1Rgb, op1Alpha, op2Rgb,
   1146                                 op2Alpha, textureEnvColor, rgbScale, alphaScale, vertexColor,
   1147                                 texturePrevColor, textureColor);
   1148            res.rgb *= rgbScale;
   1149            res.a *= alphaScale;
   1150            break;
   1151        default:
   1152            break;
   1153    }
   1154 
   1155    return clamp(res, 0.0, 1.0);
   1156 }
   1157 )";
   1158 
   1159 constexpr char kGLES1DrawFShaderMain[] = R"(
   1160 void main()
   1161 {
   1162    if (enable_clip_planes && !enable_draw_texture)
   1163    {
   1164        if (!doClipPlaneTest())
   1165        {
   1166            discard;
   1167        }
   1168    }
   1169 
   1170    vec4 vertex_color;
   1171 
   1172    if (shade_model_flat)
   1173    {
   1174        vertex_color = color_varying_flat;
   1175    }
   1176    else
   1177    {
   1178        vertex_color = color_varying;
   1179    }
   1180 
   1181    vec4 currentFragment = vertex_color;
   1182 
   1183    vec4 texturePrevColor = currentFragment;
   1184 
   1185    for (int i = 0; i < kMaxTexUnits; i++)
   1186    {
   1187        vec4 textureColor;
   1188 
   1189        if (point_rasterization && point_sprite_enabled &&
   1190            point_sprite_coord_replace[i]) {
   1191            textureColor = getPointSpriteTextureColor(i);
   1192        } else {
   1193            textureColor = getTextureColor(i);
   1194        }
   1195 
   1196        currentFragment = textureFunction(
   1197            i, texture_format[i], texture_env_mode[i], combine_rgb[i], combine_alpha[i],
   1198            src0_rgb[i], src0_alpha[i], src1_rgb[i], src1_alpha[i], src2_rgb[i], src2_alpha[i],
   1199            op0_rgb[i], op0_alpha[i], op1_rgb[i], op1_alpha[i], op2_rgb[i], op2_alpha[i],
   1200            texture_env_color[i], texture_env_rgb_scale[i], texture_env_alpha_scale[i],
   1201            vertex_color, texturePrevColor, textureColor);
   1202 
   1203        texturePrevColor = currentFragment;
   1204    }
   1205 
   1206    if (enable_fog)
   1207    {
   1208        currentFragment = doFog(currentFragment);
   1209    }
   1210 
   1211    if (enable_alpha_test && !doAlphaTest(currentFragment))
   1212    {
   1213        discard;
   1214    }
   1215 
   1216    frag_color = applyLogicOp(currentFragment);
   1217 }
   1218 )";