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