// SPDX-License-Identifier: Unlicense

#include "glsl.h"

#ifndef SHR3D_OPENGL_SPIR_V

const char* Glsl::screenVert =
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;

void main()
{
    Texcoord = texcoord;
    gl_Position = vec4(position, 1.0);
}
)";

const char* Glsl::screenFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform sampler2D texture0;

void main()
{
  FragColor = texture(texture0, Texcoord);
}
)";

const char* Glsl::worldVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
uniform mat4 modelViewProjection;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * ( sm.ViewMatrix[gl_ViewID_OVR] * ( modelViewProjection * ( vec4( position, 1.0 ) ) ) );
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
uniform mat4 modelViewProjection;

void main()
{
  Texcoord = texcoord;
  gl_Position = modelViewProjection * vec4(position, 1.0);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::worldFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x , 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);
  lowp vec4 col = vec4(mix(color.rgb, tex.rgb, tex.a), color.a);
  
  FragColor = col;
}
)";

const char* Glsl::worldNoTextureVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
uniform mat4 modelViewProjection;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * modelViewProjection * vec4(position, 1.0);
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
uniform mat4 modelViewProjection;

void main()
{
  gl_Position = modelViewProjection * vec4(position, 1.0);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::worldNoTextureFrag =
R"(#version 300 es

out lowp vec4 FragColor;
uniform lowp vec4 color;

void main()
{
  FragColor = color;
}
)";

const char* Glsl::modelFrag =
R"(#version 300 es

in highp vec2 Texcoord;
out lowp vec4 FragColor;
uniform sampler2D texture0;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x, 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);

  FragColor = tex;
}
)";

const char* Glsl::modelUvNotFlippedFrag =
R"(#version 300 es

in highp vec2 Texcoord;
out lowp vec4 FragColor;
uniform sampler2D texture0;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x, Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);

  FragColor = tex;
}
)";

const char* Glsl::worldVUMeterMonoFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float volume;
uniform lowp float peakVolume;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp vec4 color3;

void main()
{
  if (peakVolume - 0.01 < Texcoord.y && peakVolume > Texcoord.y)
    FragColor = color3;
  else if (volume > Texcoord.y)
    FragColor = color2;
  else
    FragColor = color;
}
)";

const char* Glsl::worldVUMeterStereoFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float volumeLeft;
uniform lowp float peakVolumeLeft;
uniform lowp float volumeRight;
uniform lowp float peakVolumeRight;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp vec4 color3;

void main()
{
  if (Texcoord.x < 0.48)
  {
    if (peakVolumeLeft - 0.01 < Texcoord.y && peakVolumeLeft > Texcoord.y)
      FragColor = color3;
    else if (volumeLeft > Texcoord.y)
      FragColor = color2;
    else
      FragColor = color;
  }
  else if (Texcoord.x > 0.52)
  {
    if (peakVolumeRight - 0.01 < Texcoord.y && peakVolumeRight > Texcoord.y)
      FragColor = color3;
    else if (volumeRight > Texcoord.y)
      FragColor = color2;
    else
      FragColor = color;
  }
  else
  {
    FragColor = color;
  }
}
)";

const char* Glsl::worldTunerFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float centsPos;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp vec4 color3;

void main()
{
  if (centsPos - 0.03 < Texcoord.x && Texcoord.x < centsPos + 0.03)
    FragColor = color3;
  else  if (0.47 < Texcoord.x && Texcoord.x <  0.53)
    FragColor = color2;
  else
    FragColor = color;
}
)";

const char* Glsl::worldTunerInFretFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float centsPos;
uniform lowp vec4 color;

void main()
{
  if (centsPos - 0.03 < Texcoord.x && Texcoord.x < centsPos + 0.03)
    FragColor = color;
  else
    discard;
    //FragColor = vec4(1.0, 1.0, 1.0, 0.2);
}
)";

const char* Glsl::highwayFadeFarVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
out float VertDistance; // needed for fade-far effect in frag shader
uniform mat4 viewProjection;
uniform mat4 model;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  vec4 worldPosition = model * vec4(position, 1.0);
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * viewProjection * worldPosition;
  VertDistance = length(worldPosition.xyz);
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
out float VertDistance; // needed for fade-far effect in frag shader
uniform mat4 viewProjection;
uniform mat4 model;

void main()
{
  Texcoord = texcoord;
  vec4 worldPosition = model * vec4(position, 1.0);
  gl_Position = viewProjection * worldPosition;
  VertDistance = length(worldPosition.xyz);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::highwayFadeFarAndNearVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
out lowp float VertDistance; // needed for fade-far effect in frag shader
out lowp float PosZ; // needed for fade-near effect in frag shader
uniform mat4 viewProjection;
uniform mat4 model;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  vec4 worldPosition = model * vec4(position, 1.0); // on my rtx 2070 a long ground anchor will not be visible on lowp/mediump
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * viewProjection * worldPosition;
  VertDistance = length(worldPosition.xyz);
  PosZ = worldPosition.z;
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
out lowp float VertDistance; // needed for fade-far effect in frag shader
out lowp float PosZ; // needed for fade-near effect in frag shader
uniform mat4 viewProjection;
uniform mat4 model;

void main()
{
  Texcoord = texcoord;
  vec4 worldPosition = model * vec4(position, 1.0); // on my rtx 2070 a long ground anchor will not be visible on lowp/mediump
  gl_Position = viewProjection * worldPosition;
  VertDistance = length(worldPosition.xyz);
  PosZ = worldPosition.z;
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::highwayFadeFarFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x , 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);
  lowp vec4 col = vec4(mix(color.rgb, tex.rgb, tex.a), color.a);

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::collisionChordFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float sustain;

void main()
{
  lowp float x =  max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5));

  if (x <= 0.45)
    discard;

  lowp float a = 1.0 / (1.0 + sustain); // x=0, y=1 and then slowly fade y to 0. The fade of is strong near x=0

  a *= 1.0 - (abs(0.50 - x) * 20.0); // fade the inner borders

  if (a <= 0.0)
    discard;

  FragColor = vec4(color.rgb, color.a * a);
}
)";

const char* Glsl::collisionFretFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;

void main()
{
  lowp float a = 2.0 * (0.5 - distance(Texcoord, vec2(0.5)));

  if (a <= 0.0)
    discard;

  a = pow(a, 0.4);

  a = clamp(a, 0.0, 1.0);

  FragColor = vec4(color.rgb, color.a * a);
}
)";

const char* Glsl::collisionNoteFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float sustain;

void main()
{
  lowp float a = 1.0 / (1.0 + sustain); // x=0, y=1 and then slowly fade y to 0. The fade of is strong near x=0

  a = a * (1.0 - 2.0 * distance(Texcoord, vec2(0.5)));

  FragColor = vec4(color.rgb, color.a * a);
}
)";

const char* Glsl::dotInlayFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;

lowp float circle(lowp vec2 dist, lowp float radius)
{
  return 1.0 - smoothstep(radius-(radius * 0.04), radius+(radius * 0.04), dot(dist,dist)*4.0);
}

void main()
{
  lowp vec2 dist = vec2(Texcoord.x - 0.5, Texcoord.y - 0.5);
  
  lowp float a = circle(dist, 0.9);
  if (a <= 0.0)
    discard;

  lowp vec4 resColor = mix(color, color2, 1.0 - circle(dist, 0.6));

  FragColor = vec4(resColor.rgb, resColor.a * a);
}
)";

const char* Glsl::groundFretFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float fadeNearDistance;
uniform lowp float fadeNearStrength;

void main()
{
  lowp float a = cos((Texcoord.x - 0.5) * 3.0);
  
  lowp vec4 col = mix(color2, color, a);
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  // fade-near effect
  col.a *= smoothstep(1.0, 0.0, (PosZ + fadeNearDistance) * fadeNearStrength);
  
  FragColor = col;
}
)";

#ifdef SHR3D_FONT_BITMAP
const char* Glsl::fontFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;

void main()
{
  lowp float texAlpha = texture(texture0, Texcoord).r;
  
  if (texAlpha <= 0.0)
    discard;
  
  FragColor = vec4(color.rgb, color.a * texAlpha);
}
)";

const char* Glsl::fontWorldFadeFarFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp float texAlpha = texture(texture0, Texcoord).r;
  
  if (texAlpha <= 0.0)
    discard;
  
  lowp vec4 col = color;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = mix(col, vec4(texAlpha), 1.0 - texAlpha);
}
)";

const char* Glsl::fontWorldFadeFarAndNearFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float fadeNearDistance;
uniform lowp float fadeNearStrength;

void main()
{
  lowp float texAlpha = texture(texture0, Texcoord).r;
  
  if (texAlpha <= 0.0)
    discard;
  
  lowp vec4 col = color;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  // fade-near effect
  col.a *= smoothstep(1.0, 0.0, (PosZ + fadeNearDistance) * fadeNearStrength);
  
  FragColor = mix(col, vec4(texAlpha), 1.0 - texAlpha);
}
)";

const char* Glsl::fontRainbowScreenFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float time;
uniform lowp float alpha;
uniform sampler2D texture0;

lowp float Maskline(lowp float pos, lowp float lineNumber)
{
  return step(pos, 0.125 * lineNumber) - (step(pos, 0.125 * (lineNumber - 1.)));
}

lowp vec3 GetRainbowColor(lowp float i)
{
  lowp vec3 Red2 = vec3(1.0, 0.0, 0.0) * Maskline(i, 8.);
  lowp vec3 Violet = vec3(0.57, 0.0, 1.0) * Maskline(i, 7.);
  lowp vec3 Purple = vec3(0.27, 0.0, 0.51) * Maskline(i, 6.);
  lowp vec3 blue = vec3(0.0, 0.0, 1.0) * Maskline(i, 5.);
  lowp vec3 Green = vec3(0.0, 1.0, 0.0) * Maskline(i, 4.);
  lowp vec3 Yellow = vec3(1.0, 1.0, 0.0) * Maskline(i, 3.);
  lowp vec3 Orange = vec3(1.0, 0.5, 0.0) * Maskline(i, 2.);
  lowp vec3 Red = vec3(1.0, 0.0, 0.0) * Maskline(i, 1.);
  return Red2 + Violet + Purple + blue + Green + Yellow + Orange + Red;
}

lowp vec3 SmoothRainbowColor(lowp float i)
{
  i *= 0.125 * 7.;
  lowp float gradinStep = mod(i, 0.125) * 8.;
  lowp vec3 firstColor = GetRainbowColor(i);
  lowp vec3 NextColor = GetRainbowColor(i + 0.125);
  return mix(firstColor, NextColor, gradinStep);
}

void main()
{
  lowp float texAlpha = texture(texture0, Texcoord).r;

  if (texAlpha <= 0.0)
    discard;

  lowp vec3 rainbowColor = SmoothRainbowColor(mod(time, 1.0));

  FragColor = vec4(rainbowColor, alpha * texAlpha);
}
)";

//const char* Glsl::fontRainbowWorldFrag =
//R"(#version 300 es
//
//in lowp vec2 Texcoord;
//in lowp float VertDistance;
//out lowp vec4 FragColor;
//uniform lowp float time;
//uniform lowp float alpha;
//uniform sampler2D texture0;
//uniform lowp float viewDistance;
//uniform lowp float fadeFarDistance;
//
//lowp float Maskline(lowp float pos, lowp float lineNumber)
//{
//  return step(pos, 0.125 * lineNumber) - (step(pos, 0.125 * (lineNumber - 1.)));
//}
//
//lowp vec3 GetRainbowColor(lowp float i)
//{
//  lowp vec3 Red2 = vec3(1.0, 0.0, 0.0) * Maskline(i, 8.);
//  lowp vec3 Violet = vec3(0.57, 0.0, 1.0) * Maskline(i, 7.);
//  lowp vec3 Purple = vec3(0.27, 0.0, 0.51) * Maskline(i, 6.);
//  lowp vec3 blue = vec3(0.0, 0.0, 1.0) * Maskline(i, 5.);
//  lowp vec3 Green = vec3(0.0, 1.0, 0.0) * Maskline(i, 4.);
//  lowp vec3 Yellow = vec3(1.0, 1.0, 0.0) * Maskline(i, 3.);
//  lowp vec3 Orange = vec3(1.0, 0.5, 0.0) * Maskline(i, 2.);
//  lowp vec3 Red = vec3(1.0, 0.0, 0.0) * Maskline(i, 1.);
//  return Red2 + Violet + Purple + blue + Green + Yellow + Orange + Red;
//}
//
//lowp vec3 SmoothRainbowColor(lowp float i)
//{
//  i *= 0.125 * 7.;
//  lowp float gradinStep = mod(i, 0.125) * 8.;
//  lowp vec3 firstColor = GetRainbowColor(i);
//  lowp vec3 NextColor = GetRainbowColor(i + 0.125);
//  return mix(firstColor, NextColor, gradinStep);
//}
//
//void main()
//{
//  lowp float texAlpha = texture(texture0, Texcoord).r;
//  lowp vec4 tex = texture(texture0, Texcoord);
//
//  if (texAlpha <= 0.0)
//    discard;
//
//  lowp vec3 rainbowColor = SmoothRainbowColor(mod(time, 1.0));
//  
//  lowp float alpha2 = alpha * texAlpha;
//  
//  // fade-far effect
//  alpha2 *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
//
//  FragColor = vec4(rainbowColor, alpha2);
//}
//)";
#endif // SHR3D_FONT_BITMAP

#ifdef SHR3D_FONT_MSDF
const char* Glsl::fontMSDFFrag =
R"(#version 300 es

in highp vec2 Texcoord;
out highp vec4 FragColor;
uniform highp vec4 color;
uniform sampler2D texture0;
uniform highp float screenPxRange;

highp float median(lowp float r, lowp float g, lowp float b)
{
    return max(min(r, g), min(max(r, g), b));
}

void main()
{
  highp vec3 msd = texture(texture0, Texcoord).rgb;
  highp float sd = median(msd.r, msd.g, msd.b);
  highp float screenPxDistance = screenPxRange * (sd - 0.5);
  highp float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);

  if (opacity <= 0.0)
    discard;
  
  FragColor = mix(vec4(0.0), color, opacity);
}
)";
const char* Glsl::fontMSDFWorldFadeFarFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float screenPxRange;

lowp float median(lowp float r, lowp float g, lowp float b)
{
  return max(min(r, g), min(max(r, g), b));
}

void main()
{
  lowp vec3 msd = texture(texture0, Texcoord).rgb;
  lowp float sd = median(msd.r, msd.g, msd.b);
  lowp float screenPxDistance = screenPxRange * (sd - 0.5);
  lowp float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);

  if (opacity <= 0.0)
    discard;
  
  lowp vec4 col = color;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = mix(vec4(0.0), col, opacity);
}
)";
const char* Glsl::fontMSDFWorldFadeFarAndNearFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float fadeNearDistance;
uniform lowp float fadeNearStrength;
uniform lowp float screenPxRange;

lowp float median(lowp float r, lowp float g, lowp float b)
{
  return max(min(r, g), min(max(r, g), b));
}

void main()
{
  lowp vec3 msd = texture(texture0, Texcoord).rgb;
  lowp float sd = median(msd.r, msd.g, msd.b);
  lowp float screenPxDistance = screenPxRange * (sd - 0.5);
  lowp float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);

  if (opacity <= 0.0)
    discard;

  lowp vec4 col = color;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  // fade-near effect
  col.a *= smoothstep(1.0, 0.0, (PosZ + fadeNearDistance) * fadeNearStrength);
  
  FragColor = col;
}
)";

const char* Glsl::fontMSDFRainbowScreenFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float time;
uniform lowp float alpha;
uniform sampler2D texture0;
uniform highp float screenPxRange;

lowp float Maskline(lowp float pos, lowp float lineNumber)
{
  return step(pos, 0.125 * lineNumber) - (step(pos, 0.125 * (lineNumber - 1.)));
}

lowp vec3 GetRainbowColor(lowp float i)
{
  lowp vec3 Red2 = vec3(1.0, 0.0, 0.0) * Maskline(i, 8.);
  lowp vec3 Violet = vec3(0.57, 0.0, 1.0) * Maskline(i, 7.);
  lowp vec3 Purple = vec3(0.27, 0.0, 0.51) * Maskline(i, 6.);
  lowp vec3 blue = vec3(0.0, 0.0, 1.0) * Maskline(i, 5.);
  lowp vec3 Green = vec3(0.0, 1.0, 0.0) * Maskline(i, 4.);
  lowp vec3 Yellow = vec3(1.0, 1.0, 0.0) * Maskline(i, 3.);
  lowp vec3 Orange = vec3(1.0, 0.5, 0.0) * Maskline(i, 2.);
  lowp vec3 Red = vec3(1.0, 0.0, 0.0) * Maskline(i, 1.);
  return Red2 + Violet + Purple + blue + Green + Yellow + Orange + Red;
}

lowp vec3 SmoothRainbowColor(lowp float i)
{
  i *= 0.125 * 7.;
  lowp float gradinStep = mod(i, 0.125) * 8.;
  lowp vec3 firstColor = GetRainbowColor(i);
  lowp vec3 NextColor = GetRainbowColor(i + 0.125);
  return mix(firstColor, NextColor, gradinStep);
}

highp float median(lowp float r, lowp float g, lowp float b)
{
    return max(min(r, g), min(max(r, g), b));
}

void main()
{
  highp vec3 msd = texture(texture0, Texcoord).rgb;
  highp float sd = median(msd.r, msd.g, msd.b);
  highp float screenPxDistance = screenPxRange * (sd - 0.5);
  highp float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);

  if (opacity <= 0.0)
    discard;

  lowp vec3 rainbowColor = SmoothRainbowColor(mod(time, 1.0));

  FragColor = vec4(rainbowColor, alpha * opacity);
}
)";
#endif // SHR3D_FONT_MSDF

const char* Glsl::groundAnchorFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp float colorExponent;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float fadeNearDistance;
uniform lowp float fadeNearStrength;

void main()
{
  lowp float strength = pow(0.5 * -cos(Texcoord.x * 3.141592653589793 * 2.0) + 0.5, colorExponent);

  lowp vec4 col = mix(color2, color, strength);

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  // fade-near effect
  col.a *= smoothstep(1.0, 0.0, (PosZ + fadeNearDistance) * fadeNearStrength);
  
  FragColor = col;
}
)";

const char* Glsl::groundBeatFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;
  
  col.a *= pow(0.5 * -cos(Texcoord.x * 3.141592653589793 * 2.0) + 0.5, 0.2);
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::groundBeatStrumDirectionFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  if (abs(Texcoord.x - 0.5) > 0.25)
    discard;

  lowp vec4 col = color;
  
  col.a *= pow(0.5 * -cos(Texcoord.x * 3.141592653589793 * 2.0) + 0.5, 0.2);
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::chordBoxFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5)) - 0.47, 0.0);
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  
  if (col.a <= 0.0)
    discard;

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::chordBoxDoubleStopFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), 1.0 - Texcoord.y - 0.5) - 0.47, 0.0);
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  col.a *= 1.0 - Texcoord.y;
  
  if (col.a <= 0.0)
    discard;

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::chordBoxHighDensityFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5)) - 0.47, 0.0);
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  
  if (col.a <= 0.0)
    discard;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);

  FragColor = col;
}
)";

const char* Glsl::chordBoxHighDensityDoubleStopFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), 1.0 - Texcoord.y - 0.5) - 0.47, 0.0);
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  col.a *= 1.0 - Texcoord.y;
  
  if (col.a <= 0.0)
    discard;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);

  FragColor = col;
}
)";

const char* Glsl::chordBoxFretMuteFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

lowp mat2 rotate45()
{
    return mat2(cos(0.7853981), -sin(0.7853981), sin(0.7853981), cos(0.7853981));
}

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5)) - 0.47, 0.0);
  
  lowp vec2 coord = vec2(Texcoord.x * (16.0 / 9.0), Texcoord.y);
  coord -= vec2(0.5);
  coord = rotate45() * coord;
  coord += vec2(0.5);
  lowp vec2 crossX = step(vec2(0.06, 0.06), abs(vec2(coord.x - 0.75, coord.y - 0.25)));
  
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += (1.0 - crossX.x * crossX.y) * 0.12;
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  
  if (col.a <= 0.0)
    discard;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);

  FragColor = col;
}
)";

const char* Glsl::chordBoxPalmMuteFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

lowp mat2 rotate45(){
    return mat2(cos(0.7853981),-sin(0.7853981), sin(0.7853981),cos(0.7853981));
}

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5)) - 0.47, 0.0);
  
  lowp vec2 coord = Texcoord;
  coord -= vec2(0.5);
  coord = rotate45() * coord;
  coord += vec2(0.5);
  lowp vec2 crossX = step(vec2(0.06, 0.06), abs(vec2(coord.x - 0.5, coord.y - 0.5)));
  
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += (1.0 - crossX.x * crossX.y) * 0.12;
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  
  if (col.a <= 0.0)
    discard;

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::chordBoxArpeggioFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;

  lowp float x =  max(max(abs(Texcoord.x - 0.5), abs(Texcoord.y - 0.5)) - 0.47, 0.0);
  col.a = pow(sin(x * 3.141592653589793 * 6.0), 0.8);
  col.a += min(col.a, 1.1 - Texcoord.y);
  col.a += max(col.a, (1.0 - Texcoord.y) * 0.25);
  
  if (col.a <= 0.0)
    discard;

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::timelineLevelFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp vec4 color3;
uniform lowp vec4 color4;
uniform lowp vec4 color5;
uniform lowp vec4 color6;
uniform lowp vec4 color7;
uniform lowp vec4 color8;
uniform lowp float progress;
uniform lowp float selectedLevel;

void main()
{
  lowp vec4 progressColor;
  lowp vec4 progressColor2;

  if (Texcoord.y < selectedLevel)
  {
    if (Texcoord.x > progress)
    {
      progressColor = color;
      progressColor2 = color3;
    }
    else
    {
      progressColor = color2;
      progressColor2 = color4;
    }
  }
  else
  {
    if (Texcoord.x > progress)
    {
      progressColor = color5;
      progressColor2 = color6;
    }
    else
    {
      progressColor = color7;
      progressColor2 = color8;
    }
  }

    FragColor = mix(progressColor, progressColor2, Texcoord.y);
}
)";

#ifdef SHR3D_MUSIC_STRETCHER
const char* Glsl::timelineMusicStretcherFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp float progress0;
uniform lowp float progress1;

void main()
{
  if (Texcoord.x < progress0 && Texcoord.x > progress1)
    FragColor = vec4(mix(color2.rgb, vec3(0.05, 0.05, 0.05), 0.7 - Texcoord.y), color2.a);
  else
    FragColor = vec4(mix(color.rgb, vec3(0.05, 0.05, 0.05), 0.7 - Texcoord.y), color.a);
}
)";
#endif //SHR3D_MUSIC_STRETCHER

const char* Glsl::timelineSimpleFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp float progress;

void main()
{
  lowp vec4 progressColor = color;
  if (Texcoord.x < progress)
    progressColor = color2;

  lowp vec4 gradient = vec4(0.05, 0.05, 0.05, 0.7 - Texcoord.y);
  FragColor = mix(progressColor, vec4(gradient.rgb, 1.0), gradient.a);
}
)";

const char* Glsl::timelineToneFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float progress;
uniform lowp float tonePos[100];
uniform lowp vec4 toneColor[102];

void main()
{
  lowp vec4 gradient = vec4(0.05, 0.05, 0.05, 0.7 - Texcoord.y);
  lowp vec4 progressColor = toneColor[1];

  if (Texcoord.x < progress)
  {
    progressColor = toneColor[0];
  }
  else
  {
    for (int i = 0; i < 100; ++i)
    {
      if (Texcoord.x >= tonePos[i])
      {
        progressColor = toneColor[i + 2];
      }
    }
  }
  FragColor = mix(progressColor, vec4(gradient.rgb, 1.0), gradient.a);
}
)";

const char* Glsl::groundSustainFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;
uniform lowp float fadeNearDistance;
uniform lowp float fadeNearStrength;

void main()
{
  lowp float x = abs(Texcoord.x - 0.5) - 0.45;

  if (x <= 0.0)
    discard;

  lowp vec4 col = color;

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  // fade-near effect
  col.a *= smoothstep(1.0, 0.0, (PosZ + fadeNearDistance) * fadeNearStrength);
  
  FragColor = col;
}
)";

const char* Glsl::fretVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;
uniform mat4 modelViewProjection;
uniform float fretPositionOffsetX[25];
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  vec3 instancePosition = position;
  instancePosition.x += fretPositionOffsetX[gl_InstanceID];
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * modelViewProjection * vec4(instancePosition, 1.0);
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
out vec2 Texcoord;

uniform mat4 modelViewProjection;
uniform float fretPositionOffsetX[25];

void main()
{
  Texcoord = texcoord;
  vec3 instancePosition = position;
  instancePosition.x += fretPositionOffsetX[gl_InstanceID];
  gl_Position = modelViewProjection * vec4(instancePosition, 1.0);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::scoreScreenFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp vec4 color2;
uniform lowp float progress;

void main()
{
  lowp vec4 progressColor = color;
  if (Texcoord.x < progress)
    progressColor = color2;

  lowp vec4 gradient = vec4(0.05, 0.05, 0.05, 0.7 - Texcoord.y);
  FragColor = mix(progressColor, vec4(gradient.rgb, 1.0), gradient.a);
}
)";

const char* Glsl::stringFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp vec4 color;

void main()
{
  lowp vec3 stringColor = color.rgb * pow((0.5 * -cos(Texcoord.y * 3.141592653589793 * 2.0) + 0.5), 1.5);
  FragColor = vec4(stringColor, color.a);
}
)";

const char* Glsl::stringWoundFrag =
R"(#version 300 es

in highp vec2 Texcoord; // without highp the winding will be pixelated
out lowp vec4 FragColor;
uniform lowp vec4 color;

void main()
{
  lowp vec3 stringColor = color.rgb * pow((0.5 * -cos(Texcoord.y * 3.141592653589793 * 2.0) + 0.5), 1.5);
  lowp vec3 woundStringColor = stringColor * pow(0.2 * sin(Texcoord.x * 15000.0 + Texcoord.y * 2.2) + 0.8, 1.0);
  FragColor = vec4(woundStringColor, color.a);
}
)";

const char* Glsl::sustainFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp float PosZ;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  if (PosZ > 0.0)
    discard;

  lowp float x = abs(Texcoord.x - 0.5);
  
  lowp vec3 mixer = color.rgb;
  lowp vec3 white = vec3(0.9);

  lowp float line = step(x, 0.43);
  mixer = mix(mixer, white, line);
  line = step(x, 0.28);
  mixer = mix(mixer, color.rgb, line);
  
  lowp float alpha = 0.65;

  // fade-far effect
  alpha *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = vec4(mixer, alpha);
}
)";

const char* Glsl::noteAccentFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp float dist = distance(Texcoord,vec2(0.5));
  
  if (dist > 0.50)
    discard;
  
  lowp vec4 col = color;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";

const char* Glsl::noteStandFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;
  
  col.a *= max(0.9 - Texcoord.y, 0.0);
  col.a *= pow(1.0 - abs(Texcoord.x - 0.5), 0.5);
  col.a *= 0.6;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = vec4(col.rgb, col.a);
}
)";

const char* Glsl::noteStandZeroFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
out lowp vec4 FragColor;
uniform lowp vec4 color;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec4 col = color;
  
  col.a *= 0.5 * pow(2.0 * abs(Texcoord.x - 0.5), 50.5) + 0.5 * pow(1.0 - Texcoord.y, 20.5);
  col.a *= 1.0 - Texcoord.y;
  col.a *= pow(2.0 * abs(Texcoord.x - 0.5), 5.0);
  
  if (col.a <= 0.001)
    discard;
  
  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = vec4(col.rgb, col.a);
}
)";

#ifdef SHR3D_RENDERER_DEVELOPMENT
const char* Glsl::highwayFadeFarInstancedVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in mat4 modelViewProjection;
layout(location = 6) in vec4 color;
out vec2 Texcoord;
out float VertDistance; // needed for fade-far effect in frag shader
out vec4 Color;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * modelViewProjection * vec4(position, 1.0);
  VertDistance = length(gl_Position.xyz);
  Color = color;
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in mat4 modelViewProjection;
layout(location = 6) in vec4 color;
out vec2 Texcoord;
out float VertDistance; // needed for fade-far effect in frag shader
out vec4 Color;

void main()
{
  Texcoord = texcoord;
  gl_Position = modelViewProjection * vec4(position, 1.0);
  VertDistance = length(gl_Position.xyz);
  Color = color;
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::highwayFadeFarInstancedFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp float VertDistance;
in lowp vec4 Color;
out lowp vec4 FragColor;
uniform sampler2D texture0;
uniform lowp float viewDistance;
uniform lowp float fadeFarDistance;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x , 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);
  lowp vec4 col = vec4(mix(Color.rgb, tex.rgb, tex.a), Color.a);

  // fade-far effect
  col.a *= smoothstep(0.0, 1.0, (viewDistance - VertDistance) / fadeFarDistance);
  
  FragColor = col;
}
)";
#endif // SHR3D_RENDERER_DEVELOPMENT

#ifdef SHR3D_PARTICLE
const char* Glsl::particleInstancedVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in mat4 modelViewProjection;
layout(location = 6) in vec4 color;
out vec2 Texcoord;
out vec4 Color;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * modelViewProjection * vec4(position, 1.0);
  Color = color;
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in mat4 modelViewProjection;
layout(location = 6) in vec4 color;
out vec2 Texcoord;
out vec4 Color;

void main()
{
  Texcoord = texcoord;
  gl_Position = modelViewProjection * vec4(position, 1.0);
  Color = color;
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::particleInstancedFrag =
R"(#version 300 es

in lowp vec2 Texcoord;
in lowp vec4 Color;
out lowp vec4 FragColor;
uniform sampler2D texture0;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x , 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);

  tex.a = tex.a * tex.a;

  if (tex.a <= 0.01)
    discard;

  lowp vec4 col = vec4(Color.rgb * tex.rgb, tex.a);

  FragColor = col;
}
)";
#endif // SHR3D_PARTICLE

const char* Glsl::uiVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in vec4 color;
out vec2 Texcoord;
out vec4 Color;
uniform mat4 modelViewProjection;
uniform vec2 resolution;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = texcoord;
  Color = color;
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * ( sm.ViewMatrix[gl_ViewID_OVR] * ( modelViewProjection * ( vec4(((position.x) / (0.5 * resolution.x) - 1.0), (-position.y / (0.5 * resolution.y)) + 1.0, 0.0, 1.0) ) ) );
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in vec4 color;
out vec2 Texcoord;
out vec4 Color;
uniform mat4 modelViewProjection;
uniform vec2 resolution;

void main()
{
    Texcoord = texcoord;
    Color = color;
    gl_Position = modelViewProjection * vec4(((position.x) / (0.5 * resolution.x) - 1.0), (-position.y / (0.5 * resolution.y)) + 1.0, 0.0, 1.0);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::uiFrag =
R"(#version 300 es

in mediump vec2 Texcoord;
in mediump vec4 Color;
out mediump vec4 FragColor;
uniform sampler2D texture0;

void main()
{
    FragColor = Color * texture(texture0, Texcoord);
}
)";

#ifdef SHR3D_OPENXR
const char* Glsl::xrPointerFrag =
R"(#version 300 es

in mediump vec2 Texcoord;
out mediump vec4 FragColor;
uniform lowp vec4 color;

void main()
{
    FragColor = vec4(color.rgb, (1.0 - pow(1.0 - Texcoord.x, 4.0)) * color.a);
}
)";
#endif // SHR3D_OPENXR

#ifdef SHR3D_ENVIRONMENT_SKYBOX
const char* Glsl::skyboxFrag =
R"(#version 300 es

in highp vec2 Texcoord;
out lowp vec4 FragColor;
uniform lowp float rotation;
uniform sampler2D texture0;

void main()
{
  lowp vec2 texcoord = vec2(Texcoord.x + rotation, 1.0 - Texcoord.y);
  lowp vec4 tex = texture(texture0, texcoord);

  FragColor = tex;
}
)";
#endif // SHR3D_ENVIRONMENT_SKYBOX

#ifdef SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
const char* Glsl::skyboxCubeTextureVert =
#ifdef PLATFORM_QUEST_3
R"(#version 300 es

#extension GL_OVR_multiview2 : require
layout(num_views=2) in;
layout(location = 0) in vec3 position;
out vec3 Texcoord;
uniform mat4 modelViewProjection;
uniform SceneMatrices
{
  uniform mat4 ViewMatrix[2];
  uniform mat4 ProjectionMatrix[2];
} sm;
void main()
{
  Texcoord = position;
  gl_Position = sm.ProjectionMatrix[gl_ViewID_OVR] * sm.ViewMatrix[gl_ViewID_OVR] * modelViewProjection * vec4(position, 1.0);
}
)";
#else // PLATFORM_QUEST_3
R"(#version 300 es

layout(location = 0) in vec3 position;
out vec3 Texcoord;
uniform mat4 modelViewProjection;

void main()
{
  Texcoord = position;
  gl_Position = modelViewProjection * vec4(position, 1.0);
}
)";
#endif // PLATFORM_QUEST_3

const char* Glsl::skyboxCubeTextureFrag =
R"(#version 300 es

in highp vec3 Texcoord;
out lowp vec4 FragColor;
uniform samplerCube texture0;

void main()
{
  lowp vec3 texcoord = vec3(Texcoord.x, Texcoord.y, Texcoord.z);
  FragColor = texture(texture0, texcoord);
}
)";
#endif // SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE

#endif // SHR3D_OPENGL_SPIR_V
