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