// SPDX-License-Identifier: Unlicense

#include "shader.h"

#include "opengl.h"
#include "glsl.h"
#include "spirv.h"

GLuint Shader::highwayFadeFar;
GLint Shader::highwayFadeFarUniformViewDistance = -1;
GLint Shader::highwayFadeFarUniformFadeFarDistance = -1;
GLint Shader::highwayFadeFarUniformViewProjection = -1;
GLint Shader::highwayFadeFarUniformModel = -1;
GLint Shader::highwayFadeFarUniformColor = -1;

GLuint Shader::world;
GLint Shader::worldUniformModelViewProjection = -1;
GLint Shader::worldUniformColor = -1;

GLuint Shader::worldNoTexture;
GLint Shader::worldNoTextureUniformModelViewProjection = -1;
GLint Shader::worldNoTextureUniformColor = -1;

GLuint Shader::model;
GLint Shader::modelUniformModelViewProjection = -1;

GLuint Shader::modelUvNotFlipped;
GLint Shader::modelUvNotFlippedUniformModelViewProjection = -1;

GLuint Shader::worldVUMeterMono;
GLint Shader::worldVUMeterMonoUniformModelViewProjection = -1;
GLint Shader::worldVUMeterMonoUniformVolume = -1;
GLint Shader::worldVUMeterMonoUniformPeakVolume = -1;
GLint Shader::worldVUMeterMonoUniformColor = -1;
GLint Shader::worldVUMeterMonoUniformColor2 = -1;
GLint Shader::worldVUMeterMonoUniformColor3 = -1;

GLuint Shader::worldVUMeterStereo;
GLint Shader::worldVUMeterStereoUniformModelViewProjection = -1;
GLint Shader::worldVUMeterStereoUniformVolumeLeft = -1;
GLint Shader::worldVUMeterStereoUniformPeakVolumeLeft = -1;
GLint Shader::worldVUMeterStereoUniformVolumeRight = -1;
GLint Shader::worldVUMeterStereoUniformPeakVolumeRight = -1;
GLint Shader::worldVUMeterStereoUniformColor = -1;
GLint Shader::worldVUMeterStereoUniformColor2 = -1;
GLint Shader::worldVUMeterStereoUniformColor3 = -1;

GLuint Shader::worldTuner;
GLint Shader::worldTunerUniformModelViewProjection = -1;
GLint Shader::worldTunerUniformCentsPos = -1;
GLint Shader::worldTunerUniformColor = -1;
GLint Shader::worldTunerUniformColor2 = -1;
GLint Shader::worldTunerUniformColor3 = -1;

GLuint Shader::worldTunerInFret;
GLint Shader::worldTunerInFretUniformModelViewProjection = -1;
GLint Shader::worldTunerInFretUniformCentsPos = -1;
GLint Shader::worldTunerInFretUniformColor = -1;

GLuint Shader::collisionChord;
GLint Shader::collisionChordUniformSustain = -1;
GLint Shader::collisionChordUniformModelViewProjection = -1;
GLint Shader::collisionChordUniformColor = -1;

GLuint Shader::collisionFret;
GLint Shader::collisionFretUniformModelViewProjection = -1;
GLint Shader::collisionFretUniformColor = -1;

GLuint Shader::collisionNote;
GLint Shader::collisionNoteUniformModelViewProjection = -1;
GLint Shader::collisionNoteUniformColor = -1;
GLint Shader::collisionNoteUniformSustain = -1;

GLuint Shader::dotInlay;
GLint Shader::dotInlayUniformModelViewProjection = -1;
GLint Shader::dotInlayUniformColor = -1;
GLint Shader::dotInlayUniformColor2 = -1;

GLuint Shader::groundFret;
GLint Shader::groundFretUniformViewDistance = -1;
GLint Shader::groundFretUniformFadeFarDistance = -1;
GLint Shader::groundFretUniformFadeNearDistance = -1;
GLint Shader::groundFretUniformFadeNearStrength = -1;
GLint Shader::groundFretUniformModel = -1;
GLint Shader::groundFretUniformViewProjection = -1;
GLint Shader::groundFretUniformColor = -1;
GLint Shader::groundFretUniformColor2 = -1;

GLuint Shader::screen;

#ifdef SHR3D_FONT_BITMAP
GLuint Shader::fontScreen;
GLint Shader::fontScreenUniformColor = -1;

GLuint Shader::fontWorld;
GLint Shader::fontWorldUniformModelViewProjection = -1;
GLint Shader::fontWorldUniformColor = -1;

GLuint Shader::fontWorldFadeFar;
GLint Shader::fontWorldFadeFarUniformViewDistance = -1;
GLint Shader::fontWorldFadeFarUniformFadeFarDistance = -1;
GLint Shader::fontWorldFadeFarUniformViewProjection = -1;
GLint Shader::fontWorldFadeFarUniformModel = -1;
GLint Shader::fontWorldFadeFarUniformColor = -1;

GLuint Shader::fontWorldFadeFarAndNear;
GLint Shader::fontWorldFadeFarAndNearUniformViewDistance = -1;
GLint Shader::fontWorldFadeFarAndNearUniformFadeFarDistance = -1;
GLint Shader::fontWorldFadeFarAndNearUniformFadeNearDistance = -1;
GLint Shader::fontWorldFadeFarAndNearUniformFadeNearStrength = -1;
GLint Shader::fontWorldFadeFarAndNearUniformViewProjection = -1;
GLint Shader::fontWorldFadeFarAndNearUniformModel = -1;
GLint Shader::fontWorldFadeFarAndNearUniformColor = -1;

GLuint Shader::fontRainbowScreen;
GLint Shader::fontRainbowScreenUniformTime = -1;
GLint Shader::fontRainbowScreenUniformAlpha = -1;

//GLuint Shader::fontRainbowWorld;
//GLint Shader::fontRainbowWorldUniformViewDistance = -1;
//GLint Shader::fontRainbowWorldUniformFadeFarDistance = -1;
//GLint Shader::fontRainbowWorldUniformViewProjection = -1;
//GLint Shader::fontRainbowWorldUniformModel = -1;
//GLint Shader::fontRainbowWorldUniformTime = -1;
//GLint Shader::fontRainbowWorldUniformAlpha = -1;
#endif // SHR3D_FONT_BITMAP

#ifdef SHR3D_FONT_MSDF
GLuint Shader::fontMSDFScreen;
GLint Shader::fontMSDFScreenUniformColor = -1;
GLint Shader::fontMSDFScreenUniformScreenPxRange = -1;

GLuint Shader::fontMSDFWorld;
GLint Shader::fontMSDFWorldUniformModelViewProjection = -1;
GLint Shader::fontMSDFWorldUniformColor = -1;
GLint Shader::fontMSDFWorldUniformScreenPxRange = -1;

GLuint Shader::fontMSDFWorldFadeFar;
GLint Shader::fontMSDFWorldFadeFarUniformViewDistance = -1;
GLint Shader::fontMSDFWorldFadeFarUniformFadeFarDistance = -1;
GLint Shader::fontMSDFWorldFadeFarUniformViewProjection = -1;
GLint Shader::fontMSDFWorldFadeFarUniformModel = -1;
GLint Shader::fontMSDFWorldFadeFarUniformColor = -1;
GLint Shader::fontMSDFWorldFadeFarUniformScreenPxRange = -1;

GLuint Shader::fontMSDFWorldFadeFarAndNear;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformViewDistance = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformFadeFarDistance = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearDistance = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearStrength = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformViewProjection = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformModel = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformColor = -1;
GLint Shader::fontMSDFWorldFadeFarAndNearUniformScreenPxRange = -1;

GLuint Shader::fontMSDFRainbowScreen;
GLint Shader::fontMSDFRainbowScreenUniformTime = -1;
GLint Shader::fontMSDFRainbowScreenUniformAlpha = -1;
GLint Shader::fontMSDFRainbowScreenUniformScreenPxRange = -1;
#endif // SHR3D_FONT_MSDF

GLuint Shader::groundAnchor;
GLint Shader::groundAnchorUniformViewDistance = -1;
GLint Shader::groundAnchorUniformFadeFarDistance = -1;
GLint Shader::groundAnchorUniformFadeNearDistance = -1;
GLint Shader::groundAnchorUniformFadeNearStrength = -1;
GLint Shader::groundAnchorUniformModel = -1;
GLint Shader::groundAnchorUniformViewProjection = -1;
GLint Shader::groundAnchorUniformColor = -1;
GLint Shader::groundAnchorUniformColor2 = -1;
GLint Shader::groundAnchorUniformColorExponent = -1;

GLuint Shader::groundBeat;
GLint Shader::groundBeatUniformViewDistance = -1;
GLint Shader::groundBeatUniformFadeFarDistance = -1;
GLint Shader::groundBeatUniformModel = -1;
GLint Shader::groundBeatUniformViewProjection = -1;
GLint Shader::groundBeatUniformColor = -1;

GLuint Shader::groundBeatStrumDirection;
GLint Shader::groundBeatStrumDirectionUniformViewDistance = -1;
GLint Shader::groundBeatStrumDirectionUniformFadeFarDistance = -1;
GLint Shader::groundBeatStrumDirectionUniformModel = -1;
GLint Shader::groundBeatStrumDirectionUniformViewProjection = -1;
GLint Shader::groundBeatStrumDirectionUniformColor = -1;

GLuint Shader::chordBox;
GLint Shader::chordBoxUniformViewDistance = -1;
GLint Shader::chordBoxUniformFadeFarDistance = -1;
GLint Shader::chordBoxUniformViewProjection = -1;
GLint Shader::chordBoxUniformModel = -1;
GLint Shader::chordBoxUniformColor = -1;

GLuint Shader::chordBoxDoubleStop;
GLint Shader::chordBoxDoubleStopUniformViewDistance = -1;
GLint Shader::chordBoxDoubleStopUniformFadeFarDistance = -1;
GLint Shader::chordBoxDoubleStopUniformViewProjection = -1;
GLint Shader::chordBoxDoubleStopUniformModel = -1;
GLint Shader::chordBoxDoubleStopUniformColor = -1;

GLuint Shader::chordBoxHighDensity;
GLint Shader::chordBoxHighDensityUniformViewDistance = -1;
GLint Shader::chordBoxHighDensityUniformFadeFarDistance = -1;
GLint Shader::chordBoxHighDensityUniformViewProjection = -1;
GLint Shader::chordBoxHighDensityUniformModel = -1;
GLint Shader::chordBoxHighDensityUniformColor = -1;

GLuint Shader::chordBoxHighDensityDoubleStop;
GLint Shader::chordBoxHighDensityDoubleStopUniformViewDistance = -1;
GLint Shader::chordBoxHighDensityDoubleStopUniformFadeFarDistance = -1;
GLint Shader::chordBoxHighDensityDoubleStopUniformViewProjection = -1;
GLint Shader::chordBoxHighDensityDoubleStopUniformModel = -1;
GLint Shader::chordBoxHighDensityDoubleStopUniformColor = -1;

GLuint Shader::chordBoxFretMute;
GLint Shader::chordBoxFretMuteUniformViewDistance = -1;
GLint Shader::chordBoxFretMuteUniformFadeFarDistance = -1;
GLint Shader::chordBoxFretMuteUniformViewProjection = -1;
GLint Shader::chordBoxFretMuteUniformModel = -1;
GLint Shader::chordBoxFretMuteUniformColor = -1;

GLuint Shader::chordBoxPalmMute;
GLint Shader::chordBoxPalmMuteUniformViewDistance = -1;
GLint Shader::chordBoxPalmMuteUniformFadeFarDistance = -1;
GLint Shader::chordBoxPalmMuteUniformViewProjection = -1;
GLint Shader::chordBoxPalmMuteUniformModel = -1;
GLint Shader::chordBoxPalmMuteUniformColor = -1;

GLuint Shader::chordBoxArpeggio;
GLint Shader::chordBoxArpeggioUniformViewDistance = -1;
GLint Shader::chordBoxArpeggioUniformFadeFarDistance = -1;
GLint Shader::chordBoxArpeggioUniformViewProjection = -1;
GLint Shader::chordBoxArpeggioUniformModel = -1;
GLint Shader::chordBoxArpeggioUniformColor = -1;

GLuint Shader::timelineLevelScreen;
GLint Shader::timelineLevelScreenUniformProgress = -1;
GLint Shader::timelineLevelScreenUniformSelectedLevel = -1;
GLint Shader::timelineLevelScreenUniformColor = -1;
GLint Shader::timelineLevelScreenUniformColor2 = -1;
GLint Shader::timelineLevelScreenUniformColor3 = -1;
GLint Shader::timelineLevelScreenUniformColor4 = -1;
GLint Shader::timelineLevelScreenUniformColor5 = -1;
GLint Shader::timelineLevelScreenUniformColor6 = -1;
GLint Shader::timelineLevelScreenUniformColor7 = -1;
GLint Shader::timelineLevelScreenUniformColor8 = -1;

#ifdef SHR3D_MUSIC_STRETCHER
GLuint Shader::timelineMusicStretcherScreen;
GLint Shader::timelineMusicStretcherScreenUniformProgress0 = -1;
GLint Shader::timelineMusicStretcherScreenUniformProgress1 = -1;
GLint Shader::timelineMusicStretcherScreenUniformColor = -1;
GLint Shader::timelineMusicStretcherScreenUniformColor2 = -1;
#endif // SHR3D_MUSIC_STRETCHER

GLuint Shader::timelineSimpleScreen;
GLint Shader::timelineSimpleScreenUniformProgress = -1;
GLint Shader::timelineSimpleScreenUniformColor = -1;
GLint Shader::timelineSimpleScreenUniformColor2 = -1;

GLuint Shader::timelineToneScreen;
GLint Shader::timelineToneScreenUniformProgress = -1;
GLint Shader::timelineToneScreenUniformTonePos = -1;
GLint Shader::timelineToneScreenUniformToneColor = -1;

#ifdef SHR3D_OPENXR
GLuint Shader::timelineLevelWorld;
GLint Shader::timelineLevelWorldUniformProgress = -1;
GLint Shader::timelineLevelWorldUniformModelViewProjection = -1;
GLint Shader::timelineLevelWorldUniformSelectedLevel = -1;
GLint Shader::timelineLevelWorldUniformColor = -1;
GLint Shader::timelineLevelWorldUniformColor2 = -1;
GLint Shader::timelineLevelWorldUniformColor3 = -1;
GLint Shader::timelineLevelWorldUniformColor4 = -1;
GLint Shader::timelineLevelWorldUniformColor5 = -1;
GLint Shader::timelineLevelWorldUniformColor6 = -1;
GLint Shader::timelineLevelWorldUniformColor7 = -1;
GLint Shader::timelineLevelWorldUniformColor8 = -1;

GLuint Shader::timelineSimpleWorld;
GLint Shader::timelineSimpleWorldUniformProgress = -1;
GLint Shader::timelineSimpleWorldUniformModelViewProjection = -1;
GLint Shader::timelineSimpleWorldUniformColor = -1;
GLint Shader::timelineSimpleWorldUniformColor2 = -1;

GLuint Shader::timelineToneWorld;
GLint Shader::timelineToneWorldUniformProgress = -1;
GLint Shader::timelineToneWorldUniformModelViewProjection = -1;
GLint Shader::timelineToneWorldUniformTonePos = -1;
GLint Shader::timelineToneWorldUniformToneColor = -1;

#ifdef SHR3D_MUSIC_STRETCHER
GLuint Shader::timelineMusicStretcherWorld;
GLint Shader::timelineMusicStretcherWorldUniformModelViewProjection = -1;
GLint Shader::timelineMusicStretcherWorldUniformProgress0 = -1;
GLint Shader::timelineMusicStretcherWorldUniformProgress1 = -1;
GLint Shader::timelineMusicStretcherWorldUniformColor = -1;
GLint Shader::timelineMusicStretcherWorldUniformColor2 = -1;
#endif // SHR3D_MUSIC_STRETCHER

GLuint Shader::xrPointer;
GLint Shader::xrPointerUniformModelViewProjection = -1;
GLint Shader::xrPointerUniformColor = -1;
#endif // SHR3D_OPENXR

GLuint Shader::groundSustain;
GLint Shader::groundSustainUniformViewDistance = -1;
GLint Shader::groundSustainUniformFadeFarDistance = -1;
GLint Shader::groundSustainUniformFadeNearDistance = -1;
GLint Shader::groundSustainUniformFadeNearStrength = -1;
GLint Shader::groundSustainUniformViewProjection = -1;
GLint Shader::groundSustainUniformModel = -1;
GLint Shader::groundSustainUniformColor = -1;

GLuint Shader::fret;
GLint Shader::fretUniformModelViewProjection = -1;
GLint Shader::fretUniformFretPositionOffsetX = -1;
GLint Shader::fretUniformColor = -1;

GLuint Shader::scoreScreen;
GLint Shader::scoreScreenUniformProgress = -1;
GLint Shader::scoreScreenUniformColor = -1;
GLint Shader::scoreScreenUniformColor2 = -1;

GLuint Shader::string;
GLint Shader::stringUniformModelViewProjection = -1;
GLint Shader::stringUniformColor = -1;
GLuint Shader::stringWound;
GLint Shader::stringWoundUniformModelViewProjection = -1;
GLint Shader::stringWoundUniformColor = -1;

GLuint Shader::sustain;
GLint Shader::sustainUniformViewDistance = -1;
GLint Shader::sustainUniformFadeFarDistance = -1;
GLint Shader::sustainUniformViewProjection = -1;
GLint Shader::sustainUniformModel = -1;
GLint Shader::sustainUniformColor = -1;

GLuint Shader::noteAccent;
GLint Shader::noteAccentUniformViewDistance = -1;
GLint Shader::noteAccentUniformFadeFarDistance = -1;
GLint Shader::noteAccentUniformViewProjection = -1;
GLint Shader::noteAccentUniformModel = -1;
GLint Shader::noteAccentUniformColor = -1;

GLuint Shader::noteStand;
GLint Shader::noteStandUniformViewDistance = -1;
GLint Shader::noteStandUniformFadeFarDistance = -1;
GLint Shader::noteStandUniformViewProjection = -1;
GLint Shader::noteStandUniformModel = -1;
GLint Shader::noteStandUniformColor = -1;

GLuint Shader::noteStandZero;
GLint Shader::noteStandZeroUniformViewDistance = -1;
GLint Shader::noteStandZeroUniformFadeFarDistance = -1;
GLint Shader::noteStandZeroUniformViewProjection = -1;
GLint Shader::noteStandZeroUniformModel = -1;
GLint Shader::noteStandZeroUniformColor = -1;

#ifdef SHR3D_RENDERER_DEVELOPMENT
GLuint Shader::highwayFadeFarInstanced;
GLint Shader::highwayFadeFarInstancedUniformViewDistance = -1;
GLint Shader::highwayFadeFarInstancedUniformFadeFarDistance = -1;

//GLuint Shader::groundFretInstanced;
//GLint Shader::groundFretInstancedUniformViewDistance = -1;
//GLint Shader::groundFretInstancedUniformFadeFarDistance = -1;
//GLint Shader::groundFretInstancedUniformFadeNearDistance = -1;
//GLint Shader::groundFretInstancedUniformFadeNearStrength = -1;
//GLint Shader::groundFretInstancedUniformColor = -1;
//GLint Shader::groundFretInstancedUniformColor2 = -1;
#endif // SHR3D_RENDERER_DEVELOPMENT

#ifdef SHR3D_PARTICLE
GLuint Shader::particleInstanced;
#endif // SHR3D_PARTICLE

GLuint Shader::ui;
GLint Shader::uiUniformModelViewProjection = -1;
GLint Shader::uiUniformResolution = -1;

#ifdef SHR3D_ENVIRONMENT_SKYBOX
GLuint Shader::skybox;
GLint Shader::skyboxUniformModelViewProjection = -1;
GLint Shader::skyboxUniformRotation = -1;
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
GLuint Shader::skyboxCubeTexture;
GLint Shader::skyboxCubeTextureUniformModelViewProjection = -1;
#endif // SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE

static GLuint compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
  const u8* vertexBinary, const u64 vertexBinarySize, const u8* fragBinary, const u64 fragBinarySize
#else // SHR3D_OPENGL_SPIR_V
  const char* vertexSource, const char* fragSource
#endif // SHR3D_OPENGL_SPIR_V
)
{
  GLuint vertexShader;
  GLuint fragmentShader;

  { // compile the shaders
    vertexShader = glCreateShader(GL_VERTEX_SHADER);

#ifdef SHR3D_OPENGL_SPIR_V
    GL(glShaderBinary(1, &vertexShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, vertexBinary, vertexBinarySize));
    GL(glSpecializeShader(vertexShader, "main", 0, nullptr, nullptr));
#else // SHR3D_OPENGL_SPIR_V
    GL(glShaderSource(vertexShader, 1, &vertexSource, nullptr));
    GL(glCompileShader(vertexShader));
#endif // SHR3D_OPENGL_SPIR_V

    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

#ifdef SHR3D_OPENGL_SPIR_V
    GL(glShaderBinary(1, &fragmentShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, fragBinary, fragBinarySize));
    GL(glSpecializeShader(fragmentShader, "main", 0, nullptr, nullptr));
#else // SHR3D_OPENGL_SPIR_V
    GL(glShaderSource(fragmentShader, 1, &fragSource, nullptr));
    GL(glCompileShader(fragmentShader));
#endif // SHR3D_OPENGL_SPIR_V
  }

  { // handle compilation errors
    GLint status;
    char buffer[512];

    GL(glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status));
    if (status != GL_TRUE) {
      GL(glGetShaderInfoLog(vertexShader, 512, NULL, buffer));
      DEBUG_PRINT("%s\n", buffer);
      ASSERT(false);
    }

    GL(glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status));
    if (status != GL_TRUE) {
      GL(glGetShaderInfoLog(fragmentShader, 512, NULL, buffer));
      DEBUG_PRINT("%s\n", buffer);

      ASSERT(false);
    }
  }

  const GLuint programId = glCreateProgram();
  ASSERT(programId >= 1);

  GL(glAttachShader(programId, vertexShader));
  GL(glAttachShader(programId, fragmentShader));

  GL(glLinkProgram(programId));

  GL(glDetachShader(programId, vertexShader));
  GL(glDetachShader(programId, fragmentShader));

  GL(glDeleteShader(vertexShader));
  GL(glDeleteShader(fragmentShader));

  return programId;
}

void Shader::init()
{
  Shader::highwayFadeFar = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::highwayFadeFar_frag_spv, sizeof(Spirv::highwayFadeFar_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::highwayFadeFarFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::highwayFadeFar > 0);
  Shader::highwayFadeFarUniformViewDistance = glGetUniformLocation(Shader::highwayFadeFar, "viewDistance");
  ASSERT(Shader::highwayFadeFarUniformViewDistance >= 0);
  Shader::highwayFadeFarUniformFadeFarDistance = glGetUniformLocation(Shader::highwayFadeFar, "fadeFarDistance");
  ASSERT(Shader::highwayFadeFarUniformFadeFarDistance >= 0);
  Shader::highwayFadeFarUniformViewProjection = glGetUniformLocation(Shader::highwayFadeFar, "viewProjection");
  ASSERT(Shader::highwayFadeFarUniformViewProjection >= 0);
  Shader::highwayFadeFarUniformModel = glGetUniformLocation(Shader::highwayFadeFar, "model");
  ASSERT(Shader::highwayFadeFarUniformModel >= 0);
  Shader::highwayFadeFarUniformColor = glGetUniformLocation(Shader::highwayFadeFar, "color");
  ASSERT(Shader::highwayFadeFarUniformColor >= 0);

  Shader::world = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::world_frag_spv, sizeof(Spirv::world_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::worldFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::world > 0);
  Shader::worldUniformModelViewProjection = glGetUniformLocation(Shader::world, "modelViewProjection");
  ASSERT(Shader::worldUniformModelViewProjection >= 0);
  Shader::worldUniformColor = glGetUniformLocation(Shader::world, "color");
  ASSERT(Shader::worldUniformColor >= 0);

  Shader::worldNoTexture = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::worldNoTexture_vert_spv, sizeof(Spirv::worldNoTexture_vert_spv), Spirv::worldNoTexture_frag_spv, sizeof(Spirv::worldNoTexture_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldNoTextureVert, Glsl::worldNoTextureFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::worldNoTexture > 0);
  Shader::worldNoTextureUniformModelViewProjection = glGetUniformLocation(Shader::worldNoTexture, "modelViewProjection");
  ASSERT(Shader::worldNoTextureUniformModelViewProjection >= 0);
  Shader::worldNoTextureUniformColor = glGetUniformLocation(Shader::worldNoTexture, "color");
  ASSERT(Shader::worldNoTextureUniformColor >= 0);

  Shader::model = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::model_frag_spv, sizeof(Spirv::model_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::modelFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::model > 0);
  Shader::modelUniformModelViewProjection = glGetUniformLocation(Shader::model, "modelViewProjection");
  ASSERT(Shader::modelUniformModelViewProjection >= 0);

  Shader::modelUvNotFlipped = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::modelUvNotFlipped_frag_spv, sizeof(Spirv::modelUvNotFlipped_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::modelUvNotFlippedFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::modelUvNotFlipped > 0);
  Shader::modelUvNotFlippedUniformModelViewProjection = glGetUniformLocation(Shader::modelUvNotFlipped, "modelViewProjection");
  ASSERT(Shader::modelUvNotFlippedUniformModelViewProjection >= 0);

  Shader::worldVUMeterMono = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::worldVUMeterMono_frag_spv, sizeof(Spirv::worldVUMeterMono_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::worldVUMeterMonoFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::worldVUMeterMono > 0);
  Shader::worldVUMeterMonoUniformModelViewProjection = glGetUniformLocation(Shader::worldVUMeterMono, "modelViewProjection");
  ASSERT(Shader::worldVUMeterMonoUniformModelViewProjection >= 0);
  Shader::worldVUMeterMonoUniformVolume = glGetUniformLocation(Shader::worldVUMeterMono, "volume");
  ASSERT(Shader::worldVUMeterMonoUniformVolume >= 0);
  Shader::worldVUMeterMonoUniformPeakVolume = glGetUniformLocation(Shader::worldVUMeterMono, "peakVolume");
  ASSERT(Shader::worldVUMeterMonoUniformPeakVolume >= 0);
  Shader::worldVUMeterMonoUniformColor = glGetUniformLocation(Shader::worldVUMeterMono, "color");
  ASSERT(Shader::worldVUMeterMonoUniformColor >= 0);
  Shader::worldVUMeterMonoUniformColor2 = glGetUniformLocation(Shader::worldVUMeterMono, "color2");
  ASSERT(Shader::worldVUMeterMonoUniformColor2 >= 0);
  Shader::worldVUMeterMonoUniformColor3 = glGetUniformLocation(Shader::worldVUMeterMono, "color3");
  ASSERT(Shader::worldVUMeterMonoUniformColor3 >= 0);

  Shader::worldVUMeterStereo = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::worldVUMeterStereo_frag_spv, sizeof(Spirv::worldVUMeterStereo_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::worldVUMeterStereoFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::worldVUMeterStereo > 0);
  Shader::worldVUMeterStereoUniformModelViewProjection = glGetUniformLocation(Shader::worldVUMeterStereo, "modelViewProjection");
  ASSERT(Shader::worldVUMeterStereoUniformModelViewProjection >= 0);
  Shader::worldVUMeterStereoUniformVolumeLeft = glGetUniformLocation(Shader::worldVUMeterStereo, "volumeLeft");
  ASSERT(Shader::worldVUMeterStereoUniformVolumeLeft >= 0);
  Shader::worldVUMeterStereoUniformPeakVolumeLeft = glGetUniformLocation(Shader::worldVUMeterStereo, "peakVolumeLeft");
  ASSERT(Shader::worldVUMeterStereoUniformPeakVolumeLeft >= 0);
  Shader::worldVUMeterStereoUniformVolumeRight = glGetUniformLocation(Shader::worldVUMeterStereo, "volumeRight");
  ASSERT(Shader::worldVUMeterStereoUniformVolumeRight >= 0);
  Shader::worldVUMeterStereoUniformPeakVolumeRight = glGetUniformLocation(Shader::worldVUMeterStereo, "peakVolumeRight");
  ASSERT(Shader::worldVUMeterStereoUniformPeakVolumeRight >= 0);
  Shader::worldVUMeterStereoUniformColor = glGetUniformLocation(Shader::worldVUMeterStereo, "color");
  ASSERT(Shader::worldVUMeterStereoUniformColor >= 0);
  Shader::worldVUMeterStereoUniformColor2 = glGetUniformLocation(Shader::worldVUMeterStereo, "color2");
  ASSERT(Shader::worldVUMeterStereoUniformColor2 >= 0);
  Shader::worldVUMeterStereoUniformColor3 = glGetUniformLocation(Shader::worldVUMeterStereo, "color3");
  ASSERT(Shader::worldVUMeterStereoUniformColor3 >= 0);

  Shader::worldTuner = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::worldTuner_frag_spv, sizeof(Spirv::worldTuner_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::worldTunerFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::worldTuner > 0);
  Shader::worldTunerUniformModelViewProjection = glGetUniformLocation(Shader::worldTuner, "modelViewProjection");
  ASSERT(Shader::worldTunerUniformModelViewProjection >= 0);
  Shader::worldTunerUniformCentsPos = glGetUniformLocation(Shader::worldTuner, "centsPos");
  ASSERT(Shader::worldTunerUniformCentsPos >= 0);
  Shader::worldTunerUniformColor = glGetUniformLocation(Shader::worldTuner, "color");
  ASSERT(Shader::worldTunerUniformColor >= 0);
  Shader::worldTunerUniformColor2 = glGetUniformLocation(Shader::worldTuner, "color2");
  ASSERT(Shader::worldTunerUniformColor2 >= 0);
  Shader::worldTunerUniformColor3 = glGetUniformLocation(Shader::worldTuner, "color3");
  ASSERT(Shader::worldTunerUniformColor3 >= 0);

  Shader::worldTunerInFret = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::worldTunerInFret_frag_spv, sizeof(Spirv::worldTunerInFret_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::worldTunerInFretFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::worldTunerInFret > 0);
  Shader::worldTunerInFretUniformModelViewProjection = glGetUniformLocation(Shader::worldTunerInFret, "modelViewProjection");
  ASSERT(Shader::worldTunerInFretUniformModelViewProjection >= 0);
  Shader::worldTunerInFretUniformCentsPos = glGetUniformLocation(Shader::worldTunerInFret, "centsPos");
  ASSERT(Shader::worldTunerInFretUniformCentsPos >= 0);
  Shader::worldTunerInFretUniformColor = glGetUniformLocation(Shader::worldTunerInFret, "color");
  ASSERT(Shader::worldTunerInFretUniformColor >= 0);

  Shader::collisionChord = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::collisionChord_frag_spv, sizeof(Spirv::collisionChord_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::collisionChordFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::collisionChord > 0);
  Shader::collisionChordUniformSustain = glGetUniformLocation(Shader::collisionChord, "sustain");
  ASSERT(Shader::collisionChordUniformSustain >= 0);
  Shader::collisionChordUniformModelViewProjection = glGetUniformLocation(Shader::collisionChord, "modelViewProjection");
  ASSERT(Shader::collisionChordUniformModelViewProjection >= 0);
  Shader::collisionChordUniformColor = glGetUniformLocation(Shader::collisionChord, "color");
  ASSERT(Shader::collisionChordUniformColor >= 0);

  Shader::collisionFret = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::collisionFret_frag_spv, sizeof(Spirv::collisionFret_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::collisionFretFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::collisionFret > 0);
  Shader::collisionFretUniformModelViewProjection = glGetUniformLocation(collisionFret, "modelViewProjection");
  ASSERT(Shader::collisionFretUniformModelViewProjection >= 0);
  Shader::collisionFretUniformColor = glGetUniformLocation(collisionFret, "color");
  ASSERT(Shader::collisionFretUniformColor >= 0);

  Shader::collisionNote = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::collisionNote_frag_spv, sizeof(Spirv::collisionNote_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::collisionNoteFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::collisionNote > 0);
  Shader::collisionNoteUniformModelViewProjection = glGetUniformLocation(Shader::collisionNote, "modelViewProjection");
  ASSERT(Shader::collisionNoteUniformModelViewProjection >= 0);
  Shader::collisionNoteUniformColor = glGetUniformLocation(Shader::collisionNote, "color");
  ASSERT(Shader::collisionNoteUniformColor >= 0);
  Shader::collisionNoteUniformSustain = glGetUniformLocation(Shader::collisionNote, "sustain");
  ASSERT(Shader::collisionNoteUniformSustain >= 0);

  Shader::dotInlay = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::dotInlay_frag_spv, sizeof(Spirv::dotInlay_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::dotInlayFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::dotInlay > 0);
  Shader::dotInlayUniformModelViewProjection = glGetUniformLocation(Shader::dotInlay, "modelViewProjection");
  ASSERT(Shader::dotInlayUniformModelViewProjection >= 0);
  Shader::dotInlayUniformColor = glGetUniformLocation(Shader::dotInlay, "color");
  ASSERT(Shader::dotInlayUniformColor >= 0);
  Shader::dotInlayUniformColor2 = glGetUniformLocation(Shader::dotInlay, "color2");
  ASSERT(Shader::dotInlayUniformColor2 >= 0);

  Shader::groundFret = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::groundFret_frag_spv, sizeof(Spirv::groundFret_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::groundFretFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::groundFret > 0);
  Shader::groundFretUniformViewDistance = glGetUniformLocation(Shader::groundFret, "viewDistance");
  ASSERT(Shader::groundFretUniformViewDistance >= 0);
  Shader::groundFretUniformFadeFarDistance = glGetUniformLocation(Shader::groundFret, "fadeFarDistance");
  ASSERT(Shader::groundFretUniformFadeFarDistance >= 0);
  Shader::groundFretUniformFadeNearDistance = glGetUniformLocation(Shader::groundFret, "fadeNearDistance");
  ASSERT(Shader::groundFretUniformFadeNearDistance >= 0);
  Shader::groundFretUniformFadeNearStrength = glGetUniformLocation(Shader::groundFret, "fadeNearStrength");
  ASSERT(Shader::groundFretUniformFadeNearStrength >= 0);
  Shader::groundFretUniformViewProjection = glGetUniformLocation(Shader::groundFret, "viewProjection");
  ASSERT(Shader::groundFretUniformViewProjection >= 0);
  Shader::groundFretUniformModel = glGetUniformLocation(Shader::groundFret, "model");
  ASSERT(Shader::groundFretUniformModel >= 0);
  Shader::groundFretUniformColor = glGetUniformLocation(Shader::groundFret, "color");
  ASSERT(Shader::groundFretUniformColor >= 0);
  Shader::groundFretUniformColor2 = glGetUniformLocation(Shader::groundFret, "color2");
  ASSERT(Shader::groundFretUniformColor2 >= 0);

  Shader::screen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::screen_frag_spv, sizeof(Spirv::screen_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::screenFrag
#endif // SHR3D_OPENGL_SPIR_V
  );

#ifdef SHR3D_FONT_BITMAP

  Shader::fontScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::font_frag_spv, sizeof(Spirv::font_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::fontFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontScreen > 0);
  Shader::fontScreenUniformColor = glGetUniformLocation(Shader::fontScreen, "color");
  ASSERT(Shader::fontScreenUniformColor >= 0);

  Shader::fontWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::highwayFadeFar_frag_spv, sizeof(Spirv::highwayFadeFar_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::fontFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontWorld > 0);
  Shader::fontWorldUniformModelViewProjection = glGetUniformLocation(Shader::fontWorld, "modelViewProjection");
  ASSERT(Shader::fontWorldUniformModelViewProjection >= 0);
  Shader::fontWorldUniformColor = glGetUniformLocation(Shader::fontWorld, "color");
  ASSERT(Shader::fontWorldUniformColor >= 0);

  Shader::fontWorldFadeFar = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::fontWorldFadeFar_frag_spv, sizeof(Spirv::fontWorldFadeFar_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::fontWorldFadeFarFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontWorldFadeFar > 0);
  Shader::fontWorldFadeFarUniformViewDistance = glGetUniformLocation(Shader::fontWorldFadeFar, "viewDistance");
  ASSERT(Shader::fontWorldFadeFarUniformViewDistance >= 0);
  Shader::fontWorldFadeFarUniformFadeFarDistance = glGetUniformLocation(Shader::fontWorldFadeFar, "fadeFarDistance");
  ASSERT(Shader::fontWorldFadeFarUniformFadeFarDistance >= 0);
  Shader::fontWorldFadeFarUniformViewProjection = glGetUniformLocation(Shader::fontWorldFadeFar, "viewProjection");
  ASSERT(Shader::fontWorldFadeFarUniformViewProjection >= 0);
  Shader::fontWorldFadeFarUniformModel = glGetUniformLocation(Shader::fontWorldFadeFar, "model");
  ASSERT(Shader::fontWorldFadeFarUniformModel >= 0);
  Shader::fontWorldFadeFarUniformColor = glGetUniformLocation(Shader::fontWorldFadeFar, "color");
  ASSERT(Shader::fontWorldFadeFarUniformColor >= 0);

  Shader::fontWorldFadeFarAndNear = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::fontWorldFadeFarAndNear_frag_spv, sizeof(Spirv::fontWorldFadeFarAndNear_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::fontWorldFadeFarAndNearFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontWorldFadeFarAndNear > 0);
  Shader::fontWorldFadeFarAndNearUniformViewDistance = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "viewDistance");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformViewDistance >= 0);
  Shader::fontWorldFadeFarAndNearUniformFadeFarDistance = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "fadeFarDistance");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformFadeFarDistance >= 0);
  Shader::fontWorldFadeFarAndNearUniformFadeNearDistance = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "fadeNearDistance");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformFadeNearDistance >= 0);
  Shader::fontWorldFadeFarAndNearUniformFadeNearStrength = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "fadeNearStrength");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformFadeNearStrength >= 0);
  Shader::fontWorldFadeFarAndNearUniformViewProjection = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "viewProjection");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformViewProjection >= 0);
  Shader::fontWorldFadeFarAndNearUniformModel = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "model");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformModel >= 0);
  Shader::fontWorldFadeFarAndNearUniformColor = glGetUniformLocation(Shader::fontWorldFadeFarAndNear, "color");
  ASSERT(Shader::fontWorldFadeFarAndNearUniformColor >= 0);

  Shader::fontRainbowScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::fontRainbowScreen_frag_spv, sizeof(Spirv::fontRainbowScreen_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::fontRainbowScreenFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontRainbowScreen > 0);
  Shader::fontRainbowScreenUniformTime = glGetUniformLocation(Shader::fontRainbowScreen, "time");
  ASSERT(Shader::fontRainbowScreenUniformTime >= 0);
  Shader::fontRainbowScreenUniformAlpha = glGetUniformLocation(Shader::fontRainbowScreen, "alpha");
  ASSERT(Shader::fontRainbowScreenUniformAlpha >= 0);

//  Shader::fontRainbowWorld = compileShader(
//#ifdef SHR3D_OPENGL_SPIR_V
//    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::fontRainbowWorld_frag_spv, sizeof(Spirv::fontRainbowWorld_frag_spv)
//#else // SHR3D_OPENGL_SPIR_V
//    Glsl::highwayFadeFarVert, Glsl::fontRainbowWorldFrag
//#endif // SHR3D_OPENGL_SPIR_V
//  );
//  ASSERT(Shader::fontRainbowWorld > 0);
//  Shader::fontRainbowWorldUniformViewDistance = glGetUniformLocation(Shader::fontRainbowWorld, "viewDistance");
//  ASSERT(Shader::fontRainbowWorldUniformViewDistance >= 0);
//  Shader::fontRainbowWorldUniformFadeFarDistance = glGetUniformLocation(Shader::fontRainbowWorld, "fadeFarDistance");
//  ASSERT(Shader::fontRainbowWorldUniformFadeFarDistance >= 0);
//  Shader::fontRainbowWorldUniformViewProjection = glGetUniformLocation(Shader::fontRainbowWorld, "viewProjection");
//  ASSERT(Shader::fontRainbowWorldUniformViewProjection >= 0);
//  Shader::fontRainbowWorldUniformModel = glGetUniformLocation(Shader::fontRainbowWorld, "model");
//  ASSERT(Shader::fontRainbowWorldUniformModel >= 0);
//  Shader::fontRainbowWorldUniformTime = glGetUniformLocation(Shader::fontRainbowWorld, "time");
//  ASSERT(Shader::fontRainbowWorldUniformTime >= 0);
//  Shader::fontRainbowWorldUniformAlpha = glGetUniformLocation(Shader::fontRainbowWorld, "alpha");
//  ASSERT(Shader::fontRainbowWorldUniformAlpha >= 0);
#endif // SHR3D_FONT_BITMAP

#ifdef SHR3D_FONT_MSDF
  Shader::fontMSDFScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::fontMSDF_frag_spv, sizeof(Spirv::fontMSDF_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::fontMSDFFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontMSDFScreen > 0);
  Shader::fontMSDFScreenUniformColor = glGetUniformLocation(Shader::fontMSDFScreen, "color");
  ASSERT(Shader::fontMSDFScreenUniformColor >= 0);
  Shader::fontMSDFScreenUniformScreenPxRange = glGetUniformLocation(Shader::fontMSDFScreen, "screenPxRange");
  ASSERT(Shader::fontMSDFScreenUniformScreenPxRange >= 0);

  Shader::fontMSDFWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::fontMSDF_frag_spv, sizeof(Spirv::fontMSDF_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::fontMSDFFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontMSDFWorld > 0);
  Shader::fontMSDFWorldUniformModelViewProjection = glGetUniformLocation(Shader::fontMSDFWorld, "modelViewProjection");
  ASSERT(Shader::fontMSDFWorldUniformModelViewProjection >= 0);
  Shader::fontMSDFWorldUniformColor = glGetUniformLocation(Shader::fontMSDFWorld, "color");
  ASSERT(Shader::fontMSDFWorldUniformColor >= 0);
  Shader::fontMSDFWorldUniformScreenPxRange = glGetUniformLocation(Shader::fontMSDFWorld, "screenPxRange");  ASSERT(Shader::fontMSDFWorld > 0);
  ASSERT(Shader::fontMSDFWorldUniformScreenPxRange >= 0);

  Shader::fontMSDFWorldFadeFar = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::fontMSDFWorldFadeFar_frag_spv, sizeof(Spirv::fontMSDFWorldFadeFar_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::fontMSDFWorldFadeFarFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontMSDFWorldFadeFar > 0);
  Shader::fontMSDFWorldFadeFarUniformViewDistance = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "viewDistance");
  ASSERT(Shader::fontMSDFWorldFadeFarUniformViewDistance >= 0);
  Shader::fontMSDFWorldFadeFarUniformFadeFarDistance = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "fadeFarDistance");
  ASSERT(Shader::fontMSDFWorldFadeFarUniformFadeFarDistance >= 0);
  Shader::fontMSDFWorldFadeFarUniformViewProjection = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "viewProjection");
  ASSERT(Shader::fontMSDFWorldFadeFarUniformViewProjection >= 0);
  Shader::fontMSDFWorldFadeFarUniformModel = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "model");
  ASSERT(Shader::fontMSDFWorldFadeFarUniformModel >= 0);
  Shader::fontMSDFWorldFadeFarUniformColor = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "color");
  ASSERT(Shader::fontMSDFWorldFadeFarUniformColor >= 0);
  Shader::fontMSDFWorldFadeFarUniformScreenPxRange = glGetUniformLocation(Shader::fontMSDFWorldFadeFar, "screenPxRange");
  ASSERT(Shader::fontMSDFWorldUniformScreenPxRange >= 0);

  Shader::fontMSDFWorldFadeFarAndNear = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::fontMSDFWorldFadeFarAndNear_frag_spv, sizeof(Spirv::fontMSDFWorldFadeFarAndNear_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::fontMSDFWorldFadeFarAndNearFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontMSDFWorldFadeFarAndNear > 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformViewDistance = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "viewDistance");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformViewDistance >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformFadeFarDistance = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "fadeFarDistance");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformFadeFarDistance >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearDistance = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "fadeNearDistance");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearDistance >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearStrength = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "fadeNearStrength");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformFadeNearStrength >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformViewProjection = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "viewProjection");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformViewProjection >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformModel = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "model");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformModel >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformColor = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "color");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformColor >= 0);
  Shader::fontMSDFWorldFadeFarAndNearUniformScreenPxRange = glGetUniformLocation(Shader::fontMSDFWorldFadeFarAndNear, "screenPxRange");
  ASSERT(Shader::fontMSDFWorldFadeFarAndNearUniformScreenPxRange >= 0);

  Shader::fontMSDFRainbowScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::fontMSDFRainbowScreen_frag_spv, sizeof(Spirv::fontMSDFRainbowScreen_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::fontMSDFRainbowScreenFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fontMSDFRainbowScreen > 0);
  Shader::fontMSDFRainbowScreenUniformTime = glGetUniformLocation(Shader::fontMSDFRainbowScreen, "time");
  ASSERT(Shader::fontMSDFRainbowScreenUniformTime >= 0);
  Shader::fontMSDFRainbowScreenUniformAlpha = glGetUniformLocation(Shader::fontMSDFRainbowScreen, "alpha");
  ASSERT(Shader::fontMSDFRainbowScreenUniformAlpha >= 0);
  Shader::fontMSDFRainbowScreenUniformScreenPxRange = glGetUniformLocation(Shader::fontMSDFRainbowScreen, "screenPxRange");
  ASSERT(Shader::fontMSDFRainbowScreenUniformScreenPxRange >= 0);
#endif // SHR3D_FONT_MSDF

  Shader::groundAnchor = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::groundAnchor_frag_spv, sizeof(Spirv::groundAnchor_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::groundAnchorFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::groundAnchor > 0);
  Shader::groundAnchorUniformViewDistance = glGetUniformLocation(Shader::groundAnchor, "viewDistance");
  ASSERT(Shader::groundAnchorUniformViewDistance >= 0);
  Shader::groundAnchorUniformFadeFarDistance = glGetUniformLocation(Shader::groundAnchor, "fadeFarDistance");
  ASSERT(Shader::groundAnchorUniformFadeFarDistance >= 0);
  Shader::groundAnchorUniformFadeNearDistance = glGetUniformLocation(Shader::groundAnchor, "fadeNearDistance");
  ASSERT(Shader::groundAnchorUniformFadeNearDistance >= 0);
  Shader::groundAnchorUniformFadeNearStrength = glGetUniformLocation(Shader::groundAnchor, "fadeNearStrength");
  ASSERT(Shader::groundAnchorUniformFadeNearStrength >= 0);
  Shader::groundAnchorUniformViewProjection = glGetUniformLocation(Shader::groundAnchor, "viewProjection");
  ASSERT(Shader::groundAnchorUniformViewProjection >= 0);
  Shader::groundAnchorUniformModel = glGetUniformLocation(Shader::groundAnchor, "model");
  ASSERT(Shader::groundAnchorUniformModel >= 0);
  Shader::groundAnchorUniformColor = glGetUniformLocation(Shader::groundAnchor, "color");
  ASSERT(Shader::groundAnchorUniformColor >= 0);
  Shader::groundAnchorUniformColor2 = glGetUniformLocation(Shader::groundAnchor, "color2");
  ASSERT(Shader::groundAnchorUniformColor2 >= 0);
  Shader::groundAnchorUniformColorExponent = glGetUniformLocation(Shader::groundAnchor, "colorExponent");
  ASSERT(Shader::groundAnchorUniformColorExponent >= 0);


  Shader::groundBeat = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::groundBeat_frag_spv, sizeof(Spirv::groundBeat_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::groundBeatFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::groundBeat > 0);
  Shader::groundBeatUniformViewDistance = glGetUniformLocation(Shader::groundBeat, "viewDistance");
  ASSERT(Shader::groundBeatUniformViewDistance >= 0);
  Shader::groundBeatUniformFadeFarDistance = glGetUniformLocation(Shader::groundBeat, "fadeFarDistance");
  ASSERT(Shader::groundBeatUniformFadeFarDistance >= 0);
  Shader::groundBeatUniformViewProjection = glGetUniformLocation(Shader::groundBeat, "viewProjection");
  ASSERT(Shader::groundBeatUniformViewProjection >= 0);
  Shader::groundBeatUniformModel = glGetUniformLocation(Shader::groundBeat, "model");
  ASSERT(Shader::groundBeatUniformModel >= 0);
  Shader::groundBeatUniformColor = glGetUniformLocation(Shader::groundBeat, "color");
  ASSERT(Shader::groundBeatUniformColor >= 0);

  Shader::groundBeatStrumDirection = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::groundBeatStrumDirection_frag_spv, sizeof(Spirv::groundBeatStrumDirection_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::groundBeatStrumDirectionFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::groundBeatStrumDirection > 0);
  Shader::groundBeatStrumDirectionUniformViewDistance = glGetUniformLocation(Shader::groundBeatStrumDirection, "viewDistance");
  ASSERT(Shader::groundBeatStrumDirectionUniformViewDistance >= 0);
  Shader::groundBeatStrumDirectionUniformFadeFarDistance = glGetUniformLocation(Shader::groundBeatStrumDirection, "fadeFarDistance");
  ASSERT(Shader::groundBeatStrumDirectionUniformFadeFarDistance >= 0);
  Shader::groundBeatStrumDirectionUniformViewProjection = glGetUniformLocation(Shader::groundBeatStrumDirection, "viewProjection");
  ASSERT(Shader::groundBeatStrumDirectionUniformViewProjection >= 0);
  Shader::groundBeatStrumDirectionUniformModel = glGetUniformLocation(Shader::groundBeatStrumDirection, "model");
  ASSERT(Shader::groundBeatStrumDirectionUniformModel >= 0);
  Shader::groundBeatStrumDirectionUniformColor = glGetUniformLocation(Shader::groundBeatStrumDirection, "color");
  ASSERT(Shader::groundBeatStrumDirectionUniformColor >= 0);

  Shader::chordBox = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBox_frag_spv, sizeof(Spirv::chordBox_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBox > 0);
  Shader::chordBoxUniformViewDistance = glGetUniformLocation(Shader::chordBox, "viewDistance");
  ASSERT(Shader::chordBoxUniformViewDistance >= 0);
  Shader::chordBoxUniformFadeFarDistance = glGetUniformLocation(Shader::chordBox, "fadeFarDistance");
  ASSERT(Shader::chordBoxUniformFadeFarDistance >= 0);
  Shader::chordBoxUniformViewProjection = glGetUniformLocation(Shader::chordBox, "viewProjection");
  ASSERT(Shader::chordBoxUniformViewProjection >= 0);
  Shader::chordBoxUniformModel = glGetUniformLocation(Shader::chordBox, "model");
  ASSERT(Shader::chordBoxUniformModel >= 0);
  Shader::chordBoxUniformColor = glGetUniformLocation(Shader::chordBox, "color");
  ASSERT(Shader::chordBoxUniformColor >= 0);

  Shader::chordBoxDoubleStop = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxDoubleStop_frag_spv, sizeof(Spirv::chordBoxDoubleStop_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxDoubleStopFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxDoubleStop > 0);
  Shader::chordBoxDoubleStopUniformViewDistance = glGetUniformLocation(Shader::chordBoxDoubleStop, "viewDistance");
  ASSERT(Shader::chordBoxDoubleStopUniformViewDistance >= 0);
  Shader::chordBoxDoubleStopUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxDoubleStop, "fadeFarDistance");
  ASSERT(Shader::chordBoxDoubleStopUniformFadeFarDistance >= 0);
  Shader::chordBoxDoubleStopUniformViewProjection = glGetUniformLocation(Shader::chordBoxDoubleStop, "viewProjection");
  ASSERT(Shader::chordBoxDoubleStopUniformViewProjection >= 0);
  Shader::chordBoxDoubleStopUniformModel = glGetUniformLocation(Shader::chordBoxDoubleStop, "model");
  ASSERT(Shader::chordBoxDoubleStopUniformModel >= 0);
  Shader::chordBoxDoubleStopUniformColor = glGetUniformLocation(Shader::chordBoxDoubleStop, "color");
  ASSERT(Shader::chordBoxDoubleStopUniformColor >= 0);

  Shader::chordBoxHighDensity = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxHighDensity_frag_spv, sizeof(Spirv::chordBoxHighDensity_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxHighDensityFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxHighDensity > 0);
  Shader::chordBoxHighDensityUniformViewDistance = glGetUniformLocation(Shader::chordBoxHighDensity, "viewDistance");
  ASSERT(Shader::chordBoxHighDensityUniformViewDistance >= 0);
  Shader::chordBoxHighDensityUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxHighDensity, "fadeFarDistance");
  ASSERT(Shader::chordBoxHighDensityUniformFadeFarDistance >= 0);
  Shader::chordBoxHighDensityUniformViewProjection = glGetUniformLocation(Shader::chordBoxHighDensity, "viewProjection");
  ASSERT(Shader::chordBoxHighDensityUniformViewProjection >= 0);
  Shader::chordBoxHighDensityUniformModel = glGetUniformLocation(Shader::chordBoxHighDensity, "model");
  ASSERT(Shader::chordBoxHighDensityUniformModel >= 0);
  Shader::chordBoxHighDensityUniformColor = glGetUniformLocation(Shader::chordBoxHighDensity, "color");
  ASSERT(Shader::chordBoxHighDensityUniformColor >= 0);

  Shader::chordBoxHighDensityDoubleStop = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxHighDensityDoubleStop_frag_spv, sizeof(Spirv::chordBoxHighDensityDoubleStop_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxHighDensityDoubleStopFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxHighDensityDoubleStop > 0);
  Shader::chordBoxHighDensityDoubleStopUniformViewDistance = glGetUniformLocation(Shader::chordBoxHighDensityDoubleStop, "viewDistance");
  ASSERT(Shader::chordBoxHighDensityDoubleStopUniformViewDistance >= 0);
  Shader::chordBoxHighDensityDoubleStopUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxHighDensityDoubleStop, "fadeFarDistance");
  ASSERT(Shader::chordBoxHighDensityDoubleStopUniformFadeFarDistance >= 0);
  Shader::chordBoxHighDensityDoubleStopUniformViewProjection = glGetUniformLocation(Shader::chordBoxHighDensityDoubleStop, "viewProjection");
  ASSERT(Shader::chordBoxHighDensityDoubleStopUniformViewProjection >= 0);
  Shader::chordBoxHighDensityDoubleStopUniformModel = glGetUniformLocation(Shader::chordBoxHighDensityDoubleStop, "model");
  ASSERT(Shader::chordBoxHighDensityDoubleStopUniformModel >= 0);
  Shader::chordBoxHighDensityDoubleStopUniformColor = glGetUniformLocation(Shader::chordBoxHighDensityDoubleStop, "color");
  ASSERT(Shader::chordBoxHighDensityDoubleStopUniformColor >= 0);

  Shader::chordBoxFretMute = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxFretMute_frag_spv, sizeof(Spirv::chordBoxFretMute_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxFretMuteFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxFretMute > 0);
  Shader::chordBoxFretMuteUniformViewDistance = glGetUniformLocation(Shader::chordBoxFretMute, "viewDistance");
  ASSERT(Shader::chordBoxFretMuteUniformViewDistance >= 0);
  Shader::chordBoxFretMuteUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxFretMute, "fadeFarDistance");
  ASSERT(Shader::chordBoxFretMuteUniformFadeFarDistance >= 0);
  Shader::chordBoxFretMuteUniformViewProjection = glGetUniformLocation(Shader::chordBoxFretMute, "viewProjection");
  ASSERT(Shader::chordBoxFretMuteUniformViewProjection >= 0);
  Shader::chordBoxFretMuteUniformModel = glGetUniformLocation(Shader::chordBoxFretMute, "model");
  ASSERT(Shader::chordBoxFretMuteUniformModel >= 0);
  Shader::chordBoxFretMuteUniformColor = glGetUniformLocation(Shader::chordBoxFretMute, "color");
  ASSERT(Shader::chordBoxFretMuteUniformColor >= 0);

  Shader::chordBoxPalmMute = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxPalmMute_frag_spv, sizeof(Spirv::chordBoxPalmMute_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxPalmMuteFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxPalmMute > 0);
  Shader::chordBoxPalmMuteUniformViewDistance = glGetUniformLocation(Shader::chordBoxPalmMute, "viewDistance");
  ASSERT(Shader::chordBoxPalmMuteUniformViewDistance >= 0);
  Shader::chordBoxPalmMuteUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxPalmMute, "fadeFarDistance");
  ASSERT(Shader::chordBoxPalmMuteUniformFadeFarDistance >= 0);
  Shader::chordBoxPalmMuteUniformViewProjection = glGetUniformLocation(Shader::chordBoxPalmMute, "viewProjection");
  ASSERT(Shader::chordBoxPalmMuteUniformViewProjection >= 0);
  Shader::chordBoxPalmMuteUniformModel = glGetUniformLocation(Shader::chordBoxPalmMute, "model");
  ASSERT(Shader::chordBoxPalmMuteUniformModel >= 0);
  Shader::chordBoxPalmMuteUniformColor = glGetUniformLocation(Shader::chordBoxPalmMute, "color");
  ASSERT(Shader::chordBoxPalmMuteUniformColor >= 0);

  Shader::chordBoxArpeggio = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::chordBoxArpeggio_frag_spv, sizeof(Spirv::chordBoxArpeggio_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::chordBoxArpeggioFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::chordBoxArpeggio > 0);
  Shader::chordBoxArpeggioUniformViewDistance = glGetUniformLocation(Shader::chordBoxArpeggio, "viewDistance");
  ASSERT(Shader::chordBoxArpeggioUniformViewDistance >= 0);
  Shader::chordBoxArpeggioUniformFadeFarDistance = glGetUniformLocation(Shader::chordBoxArpeggio, "fadeFarDistance");
  ASSERT(Shader::chordBoxArpeggioUniformFadeFarDistance >= 0);
  Shader::chordBoxArpeggioUniformViewProjection = glGetUniformLocation(Shader::chordBoxArpeggio, "viewProjection");
  ASSERT(Shader::chordBoxArpeggioUniformViewProjection >= 0);
  Shader::chordBoxArpeggioUniformModel = glGetUniformLocation(Shader::chordBoxArpeggio, "model");
  ASSERT(Shader::chordBoxArpeggioUniformModel >= 0);
  Shader::chordBoxArpeggioUniformColor = glGetUniformLocation(Shader::chordBoxArpeggio, "color");
  ASSERT(Shader::chordBoxArpeggioUniformColor >= 0);

  Shader::timelineLevelScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::timelineLevel_frag_spv, sizeof(Spirv::timelineLevel_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::timelineLevelFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineLevelScreen > 0);
  Shader::timelineLevelScreenUniformProgress = glGetUniformLocation(Shader::timelineLevelScreen, "progress");
  ASSERT(Shader::timelineLevelScreenUniformProgress >= 0);
  Shader::timelineLevelScreenUniformSelectedLevel = glGetUniformLocation(Shader::timelineLevelScreen, "selectedLevel");
  ASSERT(Shader::timelineLevelScreenUniformSelectedLevel >= 0);
  Shader::timelineLevelScreenUniformColor = glGetUniformLocation(Shader::timelineLevelScreen, "color");
  ASSERT(Shader::timelineLevelScreenUniformColor >= 0);
  Shader::timelineLevelScreenUniformColor2 = glGetUniformLocation(Shader::timelineLevelScreen, "color2");
  ASSERT(Shader::timelineLevelScreenUniformColor2 >= 0);
  Shader::timelineLevelScreenUniformColor3 = glGetUniformLocation(Shader::timelineLevelScreen, "color3");
  ASSERT(Shader::timelineLevelScreenUniformColor3 >= 0);
  Shader::timelineLevelScreenUniformColor4 = glGetUniformLocation(Shader::timelineLevelScreen, "color4");
  ASSERT(Shader::timelineLevelScreenUniformColor4 >= 0);
  Shader::timelineLevelScreenUniformColor5 = glGetUniformLocation(Shader::timelineLevelScreen, "color5");
  ASSERT(Shader::timelineLevelScreenUniformColor5 >= 0);
  Shader::timelineLevelScreenUniformColor6 = glGetUniformLocation(Shader::timelineLevelScreen, "color6");
  ASSERT(Shader::timelineLevelScreenUniformColor6 >= 0);
  Shader::timelineLevelScreenUniformColor7 = glGetUniformLocation(Shader::timelineLevelScreen, "color7");
  ASSERT(Shader::timelineLevelScreenUniformColor7 >= 0);
  Shader::timelineLevelScreenUniformColor8 = glGetUniformLocation(Shader::timelineLevelScreen, "color8");
  ASSERT(Shader::timelineLevelScreenUniformColor8 >= 0);

#ifdef SHR3D_MUSIC_STRETCHER
  Shader::timelineMusicStretcherScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::timelineMusicStretcher_frag_spv, sizeof(Spirv::timelineMusicStretcher_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::timelineMusicStretcherFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineMusicStretcherScreen > 0);
  Shader::timelineMusicStretcherScreenUniformProgress0 = glGetUniformLocation(Shader::timelineMusicStretcherScreen, "progress0");
  ASSERT(Shader::timelineMusicStretcherScreenUniformProgress0 >= 0);
  Shader::timelineMusicStretcherScreenUniformProgress1 = glGetUniformLocation(Shader::timelineMusicStretcherScreen, "progress1");
  ASSERT(Shader::timelineMusicStretcherScreenUniformProgress1 >= 0);
  Shader::timelineMusicStretcherScreenUniformColor = glGetUniformLocation(Shader::timelineMusicStretcherScreen, "color");
  ASSERT(Shader::timelineMusicStretcherScreenUniformColor >= 0);
  Shader::timelineMusicStretcherScreenUniformColor2 = glGetUniformLocation(Shader::timelineMusicStretcherScreen, "color2");
  ASSERT(Shader::timelineMusicStretcherScreenUniformColor2 >= 0);
#endif // SHR3D_MUSIC_STRETCHER

  Shader::timelineSimpleScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::timelineSimple_frag_spv, sizeof(Spirv::timelineSimple_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::timelineSimpleFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineSimpleScreen > 0);
  Shader::timelineSimpleScreenUniformProgress = glGetUniformLocation(Shader::timelineSimpleScreen, "progress");
  ASSERT(Shader::timelineSimpleScreenUniformProgress >= 0);
  Shader::timelineSimpleScreenUniformColor = glGetUniformLocation(Shader::timelineSimpleScreen, "color");
  ASSERT(Shader::timelineSimpleScreenUniformColor >= 0);
  Shader::timelineSimpleScreenUniformColor2 = glGetUniformLocation(Shader::timelineSimpleScreen, "color2");
  ASSERT(Shader::timelineSimpleScreenUniformColor2 >= 0);

  Shader::timelineToneScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::timelineTone_frag_spv, sizeof(Spirv::timelineTone_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::timelineToneFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineToneScreen > 0);
  Shader::timelineToneScreenUniformProgress = glGetUniformLocation(Shader::timelineToneScreen, "progress");
  ASSERT(Shader::timelineToneScreenUniformProgress >= 0);
  Shader::timelineToneScreenUniformTonePos = glGetUniformLocation(Shader::timelineToneScreen, "tonePos");
  ASSERT(Shader::timelineToneScreenUniformTonePos >= 0);
  Shader::timelineToneScreenUniformToneColor = glGetUniformLocation(Shader::timelineToneScreen, "toneColor");
  ASSERT(Shader::timelineToneScreenUniformToneColor >= 0);

#ifdef SHR3D_OPENXR
  Shader::timelineLevelWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::timelineLevel_frag_spv, sizeof(Spirv::timelineLevel_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::timelineLevelFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineLevelWorld > 0);
  Shader::timelineLevelWorldUniformProgress = glGetUniformLocation(Shader::timelineLevelWorld, "progress");
  ASSERT(Shader::timelineLevelWorldUniformProgress >= 0);
  Shader::timelineLevelWorldUniformModelViewProjection = glGetUniformLocation(Shader::timelineLevelWorld, "modelViewProjection");
  ASSERT(Shader::timelineLevelWorldUniformModelViewProjection >= 0);
  Shader::timelineLevelWorldUniformSelectedLevel = glGetUniformLocation(Shader::timelineLevelWorld, "selectedLevel");
  ASSERT(Shader::timelineLevelWorldUniformSelectedLevel >= 0);
  Shader::timelineLevelWorldUniformColor = glGetUniformLocation(Shader::timelineLevelWorld, "color");
  ASSERT(Shader::timelineLevelWorldUniformColor >= 0);
  Shader::timelineLevelWorldUniformColor2 = glGetUniformLocation(Shader::timelineLevelWorld, "color2");
  ASSERT(Shader::timelineLevelWorldUniformColor2 >= 0);
  Shader::timelineLevelWorldUniformColor3 = glGetUniformLocation(Shader::timelineLevelWorld, "color3");
  ASSERT(Shader::timelineLevelWorldUniformColor3 >= 0);
  Shader::timelineLevelWorldUniformColor4 = glGetUniformLocation(Shader::timelineLevelWorld, "color4");
  ASSERT(Shader::timelineLevelWorldUniformColor4 >= 0);
  Shader::timelineLevelWorldUniformColor5 = glGetUniformLocation(Shader::timelineLevelWorld, "color5");
  ASSERT(Shader::timelineLevelWorldUniformColor5 >= 0);
  Shader::timelineLevelWorldUniformColor6 = glGetUniformLocation(Shader::timelineLevelWorld, "color6");
  ASSERT(Shader::timelineLevelWorldUniformColor6 >= 0);
  Shader::timelineLevelWorldUniformColor7 = glGetUniformLocation(Shader::timelineLevelWorld, "color7");
  ASSERT(Shader::timelineLevelWorldUniformColor7 >= 0);
  Shader::timelineLevelWorldUniformColor8 = glGetUniformLocation(Shader::timelineLevelWorld, "color8");
  ASSERT(Shader::timelineLevelWorldUniformColor8 >= 0);

  Shader::timelineSimpleWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::timelineSimple_frag_spv, sizeof(Spirv::timelineSimple_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::timelineSimpleFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineSimpleWorld > 0);
  Shader::timelineSimpleWorldUniformProgress = glGetUniformLocation(Shader::timelineSimpleWorld, "progress");
  ASSERT(Shader::timelineSimpleWorldUniformProgress >= 0);
  Shader::timelineSimpleWorldUniformModelViewProjection = glGetUniformLocation(Shader::timelineSimpleWorld, "modelViewProjection");
  ASSERT(Shader::timelineSimpleWorldUniformModelViewProjection >= 0);
  Shader::timelineSimpleWorldUniformColor = glGetUniformLocation(Shader::timelineSimpleWorld, "color");
  ASSERT(Shader::timelineSimpleWorldUniformColor >= 0);
  Shader::timelineSimpleWorldUniformColor2 = glGetUniformLocation(Shader::timelineSimpleWorld, "color2");
  ASSERT(Shader::timelineSimpleWorldUniformColor2 >= 0);

  Shader::timelineToneWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::timelineTone_frag_spv, sizeof(Spirv::timelineTone_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::timelineToneFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineToneWorld > 0);
  Shader::timelineToneWorldUniformProgress = glGetUniformLocation(Shader::timelineToneWorld, "progress");
  ASSERT(Shader::timelineToneWorldUniformProgress >= 0);
  Shader::timelineToneWorldUniformModelViewProjection = glGetUniformLocation(Shader::timelineToneWorld, "modelViewProjection");
  ASSERT(Shader::timelineToneWorldUniformModelViewProjection >= 0);
  Shader::timelineToneWorldUniformTonePos = glGetUniformLocation(Shader::timelineToneWorld, "tonePos");
  ASSERT(Shader::timelineToneWorldUniformTonePos >= 0);
  Shader::timelineToneWorldUniformToneColor = glGetUniformLocation(Shader::timelineToneWorld, "toneColor");
  ASSERT(Shader::timelineToneWorldUniformToneColor >= 0);

#ifdef SHR3D_MUSIC_STRETCHER
  Shader::timelineMusicStretcherWorld = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::timelineMusicStretcher_frag_spv, sizeof(Spirv::timelineMusicStretcher_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::timelineMusicStretcherFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::timelineMusicStretcherWorld > 0);
  Shader::timelineMusicStretcherWorldUniformModelViewProjection = glGetUniformLocation(Shader::timelineMusicStretcherWorld, "modelViewProjection");
  ASSERT(Shader::timelineMusicStretcherWorldUniformModelViewProjection >= 0);
  Shader::timelineMusicStretcherWorldUniformProgress0 = glGetUniformLocation(Shader::timelineMusicStretcherWorld, "progress0");
  ASSERT(Shader::timelineMusicStretcherWorldUniformProgress0 >= 0);
  Shader::timelineMusicStretcherWorldUniformProgress1 = glGetUniformLocation(Shader::timelineMusicStretcherWorld, "progress1");
  ASSERT(Shader::timelineMusicStretcherWorldUniformProgress1 >= 0);
  Shader::timelineMusicStretcherWorldUniformColor = glGetUniformLocation(Shader::timelineMusicStretcherWorld, "color");
  ASSERT(Shader::timelineMusicStretcherWorldUniformColor >= 0);
  Shader::timelineMusicStretcherWorldUniformColor2 = glGetUniformLocation(Shader::timelineMusicStretcherWorld, "color2");
  ASSERT(Shader::timelineMusicStretcherWorldUniformColor2 >= 0);
#endif // SHR3D_MUSIC_STRETCHER

  Shader::xrPointer = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::xrPointer_frag_spv, sizeof(Spirv::xrPointer_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::xrPointerFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::xrPointer > 0);
  Shader::xrPointerUniformModelViewProjection = glGetUniformLocation(Shader::xrPointer, "modelViewProjection");
  ASSERT(Shader::xrPointerUniformModelViewProjection >= 0);
  Shader::xrPointerUniformColor = glGetUniformLocation(Shader::xrPointer, "color");
  ASSERT(Shader::xrPointerUniformColor >= 0);
#endif // SHR3D_OPENXR

  Shader::groundSustain = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::groundSustain_frag_spv, sizeof(Spirv::groundSustain_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::groundSustainFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::groundSustain > 0);
  Shader::groundSustainUniformViewDistance = glGetUniformLocation(Shader::groundSustain, "viewDistance");
  ASSERT(Shader::groundSustainUniformViewDistance >= 0);
  Shader::groundSustainUniformFadeFarDistance = glGetUniformLocation(Shader::groundSustain, "fadeFarDistance");
  ASSERT(Shader::groundSustainUniformFadeFarDistance >= 0);
  Shader::groundSustainUniformFadeNearDistance = glGetUniformLocation(Shader::groundSustain, "fadeNearDistance");
  ASSERT(Shader::groundSustainUniformFadeNearDistance >= 0);
  Shader::groundSustainUniformFadeNearStrength = glGetUniformLocation(Shader::groundSustain, "fadeNearStrength");
  ASSERT(Shader::groundSustainUniformFadeNearStrength >= 0);
  Shader::groundSustainUniformViewProjection = glGetUniformLocation(Shader::groundSustain, "viewProjection");
  ASSERT(Shader::groundSustainUniformViewProjection >= 0);
  Shader::groundSustainUniformModel = glGetUniformLocation(Shader::groundSustain, "model");
  ASSERT(Shader::groundSustainUniformModel >= 0);
  Shader::groundSustainUniformColor = glGetUniformLocation(Shader::groundSustain, "color");
  ASSERT(Shader::groundSustainUniformColor >= 0);

  Shader::fret = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::fret_vert_spv, sizeof(Spirv::fret_vert_spv), Spirv::world_frag_spv, sizeof(Spirv::world_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::fretVert, Glsl::worldFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::fret > 0);
  Shader::fretUniformModelViewProjection = glGetUniformLocation(Shader::fret, "modelViewProjection");
  ASSERT(Shader::fretUniformModelViewProjection >= 0);
  Shader::fretUniformFretPositionOffsetX = glGetUniformLocation(Shader::fret, "fretPositionOffsetX");
  ASSERT(Shader::fretUniformFretPositionOffsetX >= 0);
  Shader::fretUniformColor = glGetUniformLocation(Shader::fret, "color");
  ASSERT(Shader::fretUniformColor >= 0);

  Shader::scoreScreen = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::screen_vert_spv, sizeof(Spirv::screen_vert_spv), Spirv::scoreScreen_frag_spv, sizeof(Spirv::scoreScreen_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::screenVert, Glsl::scoreScreenFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::scoreScreen > 0);
  Shader::scoreScreenUniformProgress = glGetUniformLocation(Shader::scoreScreen, "progress");
  ASSERT(Shader::scoreScreenUniformProgress >= 0);
  Shader::scoreScreenUniformColor = glGetUniformLocation(Shader::scoreScreen, "color");
  ASSERT(Shader::scoreScreenUniformColor >= 0);
  Shader::scoreScreenUniformColor2 = glGetUniformLocation(Shader::scoreScreen, "color2");
  ASSERT(Shader::scoreScreenUniformColor2 >= 0);

  Shader::string = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::string_frag_spv, sizeof(Spirv::string_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::stringFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::string > 0);
  Shader::stringUniformModelViewProjection = glGetUniformLocation(Shader::string, "modelViewProjection");
  ASSERT(Shader::stringUniformModelViewProjection >= 0);
  Shader::stringUniformColor = glGetUniformLocation(Shader::string, "color");
  ASSERT(Shader::stringUniformColor >= 0);

  Shader::stringWound = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::stringWound_frag_spv, sizeof(Spirv::stringWound_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::stringWoundFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::stringWound > 0);
  Shader::stringWoundUniformModelViewProjection = glGetUniformLocation(Shader::stringWound, "modelViewProjection");
  ASSERT(Shader::stringWoundUniformModelViewProjection >= 0);
  Shader::stringWoundUniformColor = glGetUniformLocation(Shader::stringWound, "color");
  ASSERT(Shader::stringWoundUniformColor >= 0);

  Shader::sustain = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarAndNear_vert_spv, sizeof(Spirv::highwayFadeFarAndNear_vert_spv), Spirv::sustain_frag_spv, sizeof(Spirv::sustain_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarAndNearVert, Glsl::sustainFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::sustain > 0);
  Shader::sustainUniformViewDistance = glGetUniformLocation(Shader::sustain, "viewDistance");
  ASSERT(Shader::sustainUniformViewDistance >= 0);
  Shader::sustainUniformFadeFarDistance = glGetUniformLocation(Shader::sustain, "fadeFarDistance");
  ASSERT(Shader::sustainUniformFadeFarDistance >= 0);
  Shader::sustainUniformViewProjection = glGetUniformLocation(Shader::sustain, "viewProjection");
  ASSERT(Shader::sustainUniformViewProjection >= 0);
  Shader::sustainUniformModel = glGetUniformLocation(Shader::sustain, "model");
  ASSERT(Shader::sustainUniformModel >= 0);
  Shader::sustainUniformColor = glGetUniformLocation(Shader::sustain, "color");
  ASSERT(Shader::sustainUniformColor >= 0);

  Shader::noteAccent = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::noteAccent_frag_spv, sizeof(Spirv::noteAccent_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::noteAccentFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::noteAccent > 0);
  Shader::noteAccentUniformViewDistance = glGetUniformLocation(Shader::noteAccent, "viewDistance");
  ASSERT(Shader::noteAccentUniformViewDistance >= 0);
  Shader::noteAccentUniformFadeFarDistance = glGetUniformLocation(Shader::noteAccent, "fadeFarDistance");
  ASSERT(Shader::noteAccentUniformFadeFarDistance >= 0);
  Shader::noteAccentUniformViewProjection = glGetUniformLocation(Shader::noteAccent, "viewProjection");
  ASSERT(Shader::noteAccentUniformViewProjection >= 0);
  Shader::noteAccentUniformModel = glGetUniformLocation(Shader::noteAccent, "model");
  ASSERT(Shader::noteAccentUniformModel >= 0);
  Shader::noteAccentUniformColor = glGetUniformLocation(Shader::noteAccent, "color");
  ASSERT(Shader::noteAccentUniformColor >= 0);

  Shader::noteStand = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::noteStand_frag_spv, sizeof(Spirv::noteStand_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::noteStandFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::noteStand > 0);
  Shader::noteStandUniformViewDistance = glGetUniformLocation(Shader::noteStand, "viewDistance");
  ASSERT(Shader::noteStandUniformViewDistance >= 0);
  Shader::noteStandUniformFadeFarDistance = glGetUniformLocation(Shader::noteStand, "fadeFarDistance");
  ASSERT(Shader::noteStandUniformFadeFarDistance >= 0);
  Shader::noteStandUniformViewProjection = glGetUniformLocation(Shader::noteStand, "viewProjection");
  ASSERT(Shader::noteStandUniformViewProjection >= 0);
  Shader::noteStandUniformModel = glGetUniformLocation(Shader::noteStand, "model");
  ASSERT(Shader::noteStandUniformModel >= 0);
  Shader::noteStandUniformColor = glGetUniformLocation(Shader::noteStand, "color");
  ASSERT(Shader::noteStandUniformColor >= 0);

  Shader::noteStandZero = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFar_vert_spv, sizeof(Spirv::highwayFadeFar_vert_spv), Spirv::noteStandZero_frag_spv, sizeof(Spirv::noteStandZero_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarVert, Glsl::noteStandZeroFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::noteStandZero > 0);
  Shader::noteStandZeroUniformViewDistance = glGetUniformLocation(Shader::noteStandZero, "viewDistance");
  ASSERT(Shader::noteStandZeroUniformViewDistance >= 0);
  Shader::noteStandZeroUniformFadeFarDistance = glGetUniformLocation(Shader::noteStandZero, "fadeFarDistance");
  ASSERT(Shader::noteStandZeroUniformFadeFarDistance >= 0);
  Shader::noteStandZeroUniformViewProjection = glGetUniformLocation(Shader::noteStandZero, "viewProjection");
  ASSERT(Shader::noteStandZeroUniformViewProjection >= 0);
  Shader::noteStandZeroUniformModel = glGetUniformLocation(Shader::noteStandZero, "model");
  ASSERT(Shader::noteStandZeroUniformModel >= 0);
  Shader::noteStandZeroUniformColor = glGetUniformLocation(Shader::noteStandZero, "color");
  ASSERT(Shader::noteStandZeroUniformColor >= 0);

#ifdef SHR3D_RENDERER_DEVELOPMENT
  Shader::highwayFadeFarInstanced = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::highwayFadeFarInstanced_vert_spv, sizeof(Spirv::highwayFadeFarInstanced_vert_spv), Spirv::highwayFadeFarInstanced_frag_spv, sizeof(Spirv::highwayFadeFarInstanced_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::highwayFadeFarInstancedVert, Glsl::highwayFadeFarInstancedFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::highwayFadeFarInstanced > 0);
  Shader::highwayFadeFarInstancedUniformViewDistance = glGetUniformLocation(Shader::highwayFadeFarInstanced, "viewDistance");
  ASSERT(Shader::highwayFadeFarInstancedUniformViewDistance >= 0);
  Shader::highwayFadeFarInstancedUniformFadeFarDistance = glGetUniformLocation(Shader::highwayFadeFarInstanced, "fadeFarDistance");
  ASSERT(Shader::highwayFadeFarInstancedUniformFadeFarDistance >= 0);

#endif // SHR3D_RENDERER_DEVELOPMENT

#ifdef SHR3D_PARTICLE
  Shader::particleInstanced = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::particleInstanced_vert_spv, sizeof(Spirv::particleInstanced_vert_spv), Spirv::particleInstanced_frag_spv, sizeof(Spirv::particleInstanced_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::particleInstancedVert, Glsl::particleInstancedFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::particleInstanced > 0);
#endif // SHR3D_PARTICLE

  Shader::ui = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::ui_vert_spv, sizeof(Spirv::ui_vert_spv), Spirv::ui_frag_spv, sizeof(Spirv::ui_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::uiVert, Glsl::uiFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::ui > 0);
  Shader::uiUniformModelViewProjection = glGetUniformLocation(Shader::ui, "modelViewProjection");
  ASSERT(Shader::uiUniformModelViewProjection >= 0);
  Shader::uiUniformResolution = glGetUniformLocation(Shader::ui, "resolution");
  ASSERT(Shader::uiUniformResolution >= 0);

#ifdef SHR3D_ENVIRONMENT_SKYBOX
  Shader::skybox = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::world_vert_spv, sizeof(Spirv::world_vert_spv), Spirv::skybox_frag_spv, sizeof(Spirv::skybox_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::worldVert, Glsl::skyboxFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::skybox > 0);
  Shader::skyboxUniformModelViewProjection = glGetUniformLocation(Shader::skybox, "modelViewProjection");
  ASSERT(Shader::skyboxUniformModelViewProjection >= 0);
  Shader::skyboxUniformRotation = glGetUniformLocation(Shader::skybox, "rotation");
  ASSERT(Shader::skyboxUniformRotation >= 0);
#endif // SHR3D_ENVIRONMENT_SKYBOX

#ifdef SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
  Shader::skyboxCubeTexture = compileShader(
#ifdef SHR3D_OPENGL_SPIR_V
    Spirv::skyboxCubeTexture_vert_spv, sizeof(Spirv::skyboxCubeTexture_vert_spv), Spirv::skyboxCubeTexture_frag_spv, sizeof(Spirv::skyboxCubeTexture_frag_spv)
#else // SHR3D_OPENGL_SPIR_V
    Glsl::skyboxCubeTextureVert, Glsl::skyboxCubeTextureFrag
#endif // SHR3D_OPENGL_SPIR_V
  );
  ASSERT(Shader::skyboxCubeTexture > 0);
  Shader::skyboxCubeTextureUniformModelViewProjection = glGetUniformLocation(Shader::skyboxCubeTexture, "modelViewProjection");
  ASSERT(Shader::skyboxCubeTextureUniformModelViewProjection >= 0);
#endif // SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE

  ASSERT(0 == glGetAttribLocation(Shader::world, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::world, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::worldNoTexture, "position"));
  //ASSERT(1 == glGetAttribLocation(Shader::worldNoTexture, "texcoord")); // no texcoord obviously
  ASSERT(0 == glGetAttribLocation(Shader::model, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::model, "texcoord"));
#ifdef PLATFORM_QUEST_3
  //ASSERT(2 == glGetAttribLocation(Shader::model, "vertexTransform"));
#endif // PLATFORM_QUEST_3
  ASSERT(0 == glGetAttribLocation(Shader::worldVUMeterMono, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::worldVUMeterMono, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::worldVUMeterStereo, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::worldVUMeterStereo, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::worldTuner, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::worldTuner, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::worldTunerInFret, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::worldTunerInFret, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::highwayFadeFar, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::highwayFadeFar, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::collisionChord, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::collisionChord, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::collisionFret, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::collisionFret, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::collisionNote, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::collisionNote, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::dotInlay, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::dotInlay, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::groundFret, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::groundFret, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::screen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::screen, "texcoord"));
#ifdef SHR3D_FONT_BITMAP
  ASSERT(0 == glGetAttribLocation(Shader::fontScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontScreen, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontWorldFadeFar, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontWorldFadeFar, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontWorldFadeFarAndNear, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontWorldFadeFarAndNear, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontRainbowScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontRainbowScreen, "texcoord"));
  //ASSERT(0 == glGetAttribLocation(Shader::fontRainbowWorld, "position"));
  //ASSERT(1 == glGetAttribLocation(Shader::fontRainbowWorld, "texcoord"));
#endif // SHR3D_FONT_BITMAP
#ifdef SHR3D_FONT_MSDF
  ASSERT(0 == glGetAttribLocation(Shader::fontMSDFScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontMSDFScreen, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontMSDFWorld, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontMSDFWorld, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontMSDFWorldFadeFar, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontMSDFWorldFadeFar, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontMSDFWorldFadeFarAndNear, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontMSDFWorldFadeFarAndNear, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fontMSDFRainbowScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fontMSDFRainbowScreen, "texcoord"));
#endif // SHR3D_FONT_MSDF
  ASSERT(0 == glGetAttribLocation(Shader::groundAnchor, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::groundAnchor, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::groundBeat, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::groundBeat, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBox, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBox, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxDoubleStop, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxDoubleStop, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxHighDensity, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxHighDensity, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxHighDensityDoubleStop, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxHighDensityDoubleStop, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxFretMute, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxFretMute, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxPalmMute, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxPalmMute, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::chordBoxArpeggio, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::chordBoxArpeggio, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::timelineLevelScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::timelineLevelScreen, "texcoord"));
#ifdef SHR3D_MUSIC_STRETCHER
  ASSERT(0 == glGetAttribLocation(Shader::timelineMusicStretcherScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::timelineMusicStretcherScreen, "texcoord"));
#endif // SHR3D_MUSIC_STRETCHER
  ASSERT(0 == glGetAttribLocation(Shader::timelineSimpleScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::timelineSimpleScreen, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::timelineToneScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::timelineToneScreen, "texcoord"));
  //ASSERT(0 == glGetAttribLocation(Shader::timelineLevelWorld, "position"));
  //ASSERT(1 == glGetAttribLocation(Shader::timelineLevelWorld, "texcoord"));
  //ASSERT(0 == glGetAttribLocation(Shader::timelineSimpleWorld, "position"));
  //ASSERT(1 == glGetAttribLocation(Shader::timelineSimpleWorld, "texcoord"));
  //ASSERT(0 == glGetAttribLocation(Shader::timelineToneWorld, "position"));
  //ASSERT(1 == glGetAttribLocation(Shader::timelineToneWorld, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::groundSustain, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::groundSustain, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::fret, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::fret, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::scoreScreen, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::scoreScreen, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::string, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::string, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::stringWound, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::stringWound, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::sustain, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::sustain, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::noteAccent, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::noteAccent, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::noteStand, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::noteStand, "texcoord"));
  ASSERT(0 == glGetAttribLocation(Shader::noteStandZero, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::noteStandZero, "texcoord"));
#ifdef SHR3D_RENDERER_DEVELOPMENT
  ASSERT(0 == glGetAttribLocation(Shader::highwayFadeFarInstanced, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::highwayFadeFarInstanced, "texcoord"));
#endif // SHR3D_RENDERER_DEVELOPMENT
  ASSERT(0 == glGetAttribLocation(Shader::ui, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::ui, "texcoord"));
  ASSERT(2 == glGetAttribLocation(Shader::ui, "color"));
#ifdef SHR3D_ENVIRONMENT_SKYBOX
  ASSERT(0 == glGetAttribLocation(Shader::skybox, "position"));
  ASSERT(1 == glGetAttribLocation(Shader::skybox, "texcoord"));
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
  ASSERT(0 == glGetAttribLocation(Shader::skyboxCubeTexture, "position"));
#endif // SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
}
