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