Skip to content

Commit

Permalink
Score: fix precision issue when displaying labels.
Browse files Browse the repository at this point in the history
  • Loading branch information
kosua20 committed Aug 18, 2023
1 parent af882af commit 77f83bb
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 15 deletions.
10 changes: 6 additions & 4 deletions resources/shaders/score_labels.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ in INTERFACE {

uniform sampler2D font;
uniform vec3 color;
uniform int maxDigitCount;

out vec4 fragColor;

void main(){
vec2 globalUV = In.uv;

int digitLoc = int(floor(globalUV.x));
int measure = int(In.id);


int measure = int(floor(In.id));

int powTen = 1;
for(int i = 0; i < digitLoc; ++i){
for(int i = 0; i <= maxDigitCount; ++i){
if(i >= digitLoc ){
continue;
}
powTen *= 10;
}

Expand Down
22 changes: 16 additions & 6 deletions resources/shaders/score_labels.vert
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ uniform vec2 baseOffset;
uniform vec2 nextOffset;
uniform vec2 scale;
uniform bool horizontalMode;
uniform int digitCount;
uniform int maxDigitCount;
uniform int firstMeasure;

vec2 flipIfNeeded(vec2 inPos){
Expand All @@ -20,12 +20,23 @@ out INTERFACE {


void main(){
float fullID = float(firstMeasure + gl_InstanceID);

float currentDigitCount = floor(log(max(1, fullID))/log(10.0)) + 1;
int fullID = firstMeasure + gl_InstanceID;

// floor(log(fullId)/log(10)) + 1, but accuracy issues...
int powTen = 1;
int digitCount = 0;
for( ; digitCount <= maxDigitCount; ++digitCount){
if(powTen > fullID){
break;
}
powTen *= 10;
}

float currentDigitCount = float(max(1, digitCount));

vec2 size = vec2(currentDigitCount, 1.0);
vec2 maxSize = vec2(float(digitCount), 1.0);
vec2 maxSize = vec2(float(maxDigitCount), 1.0);
vec2 finalScale = 2.f * scale * size;
vec2 maxFinalScale = 2.f * scale * maxSize;

Expand All @@ -48,7 +59,6 @@ void main(){
// Output the UV coordinates computed from the positions.
// We flip the UVs so that the integer part corresponds to a power of ten
Out.uv = (-v.xy + 0.5) * size;
Out.id = fullID;

Out.id = float(fullID);

}
8 changes: 5 additions & 3 deletions src/rendering/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,8 +649,10 @@ void Renderer::drawScore(const std::shared_ptr<MIDIScene>& scene, float time, co
// Based on texture size.
const glm::vec2 digitResolution = glm::vec2(200.0f, 256.0f);
const glm::vec2 digitSize = textScale * qualityScale * invScreenSize * digitResolution;
const float maxMeasureCount = float(scene->duration() / scene->secondsPerMeasure()) + 1.f / measureScale;
const float digitCount = std::floor(std::log10((std::max)(1.f, maxMeasureCount))) + 1;
// Ensure at least one measure.
const float maxMeasureCount = float(scene->duration() / scene->secondsPerMeasure()) + 1;
// Add one extra digit so that postroll measures are displayed entirely in all cases.
const float digitCount = (std::floor(std::log10((std::max)(1.f, maxMeasureCount))) + 1) + 1;

const glm::vec2 offset = 2.0f * digitSize * state.digitsOffset;
const glm::vec2 margin = horizontalMode ? glm::vec2(offset.y, offset.x) : offset;
Expand All @@ -660,7 +662,7 @@ void Renderer::drawScore(const std::shared_ptr<MIDIScene>& scene, float time, co
_programScoreLabels.uniform("nextOffset", glm::vec2(0.0f, nextBarDeltaCoord));
_programScoreLabels.uniform("scale", digitSize);
_programScoreLabels.uniform("color", state.digitsColor);
_programScoreLabels.uniform("digitCount", int(digitCount));
_programScoreLabels.uniform("maxDigitCount", int(digitCount));
_programScoreLabels.uniform("firstMeasure", firstMeasure);
_programScoreLabels.texture("font", _texFont, GL_TEXTURE_2D);
glBindVertexArray(_vaoQuad);
Expand Down
4 changes: 2 additions & 2 deletions src/resources/shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ const std::unordered_map<std::string, std::string> shaders = {
{ "wave_noise_frag", "#version 330\n in INTERFACE {\n vec2 uv;\n float grad;\n } In ;\n uniform vec3 waveColor;\n uniform float waveOpacity;\n uniform sampler2D textureNoise;\n out vec4 fragColor;\n void main(){\n // Premultiplied alpha.\n vec2 uv = In.uv;\n float noise = texture(textureNoise, uv).r;\n fragColor = noise * waveOpacity * vec4(waveColor, 1.0) * In.grad * 4.0;\n }\n "},
{ "score_bars_vert", "#version 330\n layout(location = 0) in vec3 v;\n uniform vec2 baseOffset;\n uniform vec2 nextOffset;\n uniform vec2 scale;\n uniform bool horizontalMode;\n vec2 flipIfNeeded(vec2 inPos){\n return horizontalMode ? vec2(inPos.y, -inPos.x) : inPos;\n }\n out INTERFACE {\n float uv;\n } Out ;\n void main(){\n \n // We directly output the position.\n vec2 pos = v.xy * scale * 2.0f + float(gl_InstanceID) * nextOffset + baseOffset;\n gl_Position = vec4(flipIfNeeded(pos), 0.0, 1.0);\n // Output the UV coordinates computed from the positions.\n Out.uv = 2.0 * (scale.x > 0.99 ? v.y : v.x);\n }\n "},
{ "score_bars_frag", "#version 330\n in INTERFACE {\n float uv;\n } In ;\n uniform vec3 color;\n out vec4 fragColor;\n void main(){\n float uv = 1.0 - abs(In.uv);\n float gradU = fwidth(uv);\n float alpha = smoothstep(0.1 - gradU, 0.1 + gradU, uv);\n fragColor = vec4(color, alpha);\n }\n "},
{ "score_labels_vert", "#version 330\n layout(location = 0) in vec3 v;\n uniform vec2 baseOffset;\n uniform vec2 nextOffset;\n uniform vec2 scale;\n uniform bool horizontalMode;\n uniform int digitCount;\n uniform int firstMeasure;\n vec2 flipIfNeeded(vec2 inPos){\n return horizontalMode ? vec2(inPos.y, -inPos.x) : inPos;\n }\n out INTERFACE {\n vec2 uv;\n float id;\n } Out ;\n void main(){\n float fullID = float(firstMeasure + gl_InstanceID);\n float currentDigitCount = floor(log(max(1, fullID))/log(10.0)) + 1;\n vec2 size = vec2(currentDigitCount, 1.0);\n vec2 maxSize = vec2(float(digitCount), 1.0);\n vec2 finalScale = 2.f * scale * size;\n vec2 maxFinalScale = 2.f * scale * maxSize;\n // We directly output the position.\n vec2 fullOffset = float(gl_InstanceID) * nextOffset + baseOffset;// + 0.5 * finalScale;\n if(horizontalMode){\n // Nothing to do on Y (which will become X) (already centered)\n // just center on X (which becomes Y)\n //Cheat to avoid digit touching the edge of the screen with offset 0.\n fullOffset.x += 0.6 * maxFinalScale.y;\n } else {\n // We want to right align, so use the max scale.\n fullOffset.x += maxFinalScale.x - 0.5 * finalScale.x;\n // Nothing to do on the Y axis.\n }\n vec2 pos = v.xy * finalScale + flipIfNeeded(fullOffset);\n gl_Position = vec4(pos, 0.1, 1.0);\n // Output the UV coordinates computed from the positions.\n // We flip the UVs so that the integer part corresponds to a power of ten\n Out.uv = (-v.xy + 0.5) * size;\n Out.id = fullID;\n }\n "},
{ "score_labels_frag", "#version 330\n in INTERFACE {\n vec2 uv;\n float id;\n } In ;\n uniform sampler2D font;\n uniform vec3 color;\n out vec4 fragColor;\n void main(){\n vec2 globalUV = In.uv;\n int digitLoc = int(floor(globalUV.x));\n int measure = int(In.id);\n int powTen = 1;\n for(int i = 0; i < digitLoc; ++i){\n powTen *= 10;\n }\n int number = (measure / powTen) % 10;\n // Remap 0,1 to 0.0, 1.0-padding on X,\n const float paddingInTexture = 0.12;\n // Flip UVs back.\n vec2 localUV = (1.0-fract(globalUV)) * vec2(1.0-paddingInTexture, 1.0);\n vec2 pixelSize = 0.5 / vec2(200.0, 256.0);\n localUV = clamp(localUV, pixelSize, 1.0 - pixelSize);\n localUV += vec2(number % 5, 1 - (number / 5));\n localUV *= vec2(0.2, 0.5);\n vec2 distancesFont = textureLod(font, localUV, 0).rg;\n float sdfFont = distancesFont.r - distancesFont.g;\n // Clamp to a reasonable value here to avoid edge artifacts?\n float deltaStep = min(fwidth(sdfFont), 0.1);\n float alpha = 1.0 - smoothstep(0.01 - deltaStep, 0.01 + deltaStep, sdfFont);\n if(measure < 0){\n discard;\n }\n if((measure < powTen) && (digitLoc != 0)){\n discard;\n }\n \n fragColor = vec4(color, alpha);\n }\n "}
{ "score_labels_vert", "#version 330\n layout(location = 0) in vec3 v;\n uniform vec2 baseOffset;\n uniform vec2 nextOffset;\n uniform vec2 scale;\n uniform bool horizontalMode;\n uniform int maxDigitCount;\n uniform int firstMeasure;\n vec2 flipIfNeeded(vec2 inPos){\n return horizontalMode ? vec2(inPos.y, -inPos.x) : inPos;\n }\n out INTERFACE {\n vec2 uv;\n float id;\n } Out ;\n void main(){\n int fullID = firstMeasure + gl_InstanceID;\n // floor(log(fullId)/log(10)) + 1, but accuracy issues...\n int powTen = 1;\n int digitCount = 0;\n for( ; digitCount <= maxDigitCount; ++digitCount){\n if(powTen > fullID){\n break;\n }\n powTen *= 10;\n }\n float currentDigitCount = float(max(1, digitCount));\n vec2 size = vec2(currentDigitCount, 1.0);\n vec2 maxSize = vec2(float(maxDigitCount), 1.0);\n vec2 finalScale = 2.f * scale * size;\n vec2 maxFinalScale = 2.f * scale * maxSize;\n // We directly output the position.\n vec2 fullOffset = float(gl_InstanceID) * nextOffset + baseOffset;// + 0.5 * finalScale;\n if(horizontalMode){\n // Nothing to do on Y (which will become X) (already centered)\n // just center on X (which becomes Y)\n //Cheat to avoid digit touching the edge of the screen with offset 0.\n fullOffset.x += 0.6 * maxFinalScale.y;\n } else {\n // We want to right align, so use the max scale.\n fullOffset.x += maxFinalScale.x - 0.5 * finalScale.x;\n // Nothing to do on the Y axis.\n }\n vec2 pos = v.xy * finalScale + flipIfNeeded(fullOffset);\n gl_Position = vec4(pos, 0.1, 1.0);\n // Output the UV coordinates computed from the positions.\n // We flip the UVs so that the integer part corresponds to a power of ten\n Out.uv = (-v.xy + 0.5) * size;\n Out.id = float(fullID);\n }\n "},
{ "score_labels_frag", "#version 330\n in INTERFACE {\n vec2 uv;\n float id;\n } In ;\n uniform sampler2D font;\n uniform vec3 color;\n uniform int maxDigitCount;\n out vec4 fragColor;\n void main(){\n vec2 globalUV = In.uv;\n int digitLoc = int(floor(globalUV.x));\n int measure = int(floor(In.id));\n int powTen = 1;\n for(int i = 0; i <= maxDigitCount; ++i){\n if(i >= digitLoc ){\n continue;\n }\n powTen *= 10;\n }\n int number = (measure / powTen) % 10;\n // Remap 0,1 to 0.0, 1.0-padding on X,\n const float paddingInTexture = 0.12;\n // Flip UVs back.\n vec2 localUV = (1.0-fract(globalUV)) * vec2(1.0-paddingInTexture, 1.0);\n vec2 pixelSize = 0.5 / vec2(200.0, 256.0);\n localUV = clamp(localUV, pixelSize, 1.0 - pixelSize);\n localUV += vec2(number % 5, 1 - (number / 5));\n localUV *= vec2(0.2, 0.5);\n vec2 distancesFont = textureLod(font, localUV, 0).rg;\n float sdfFont = distancesFont.r - distancesFont.g;\n // Clamp to a reasonable value here to avoid edge artifacts?\n float deltaStep = min(fwidth(sdfFont), 0.1);\n float alpha = 1.0 - smoothstep(0.01 - deltaStep, 0.01 + deltaStep, sdfFont);\n if(measure < 0){\n discard;\n }\n if((measure < powTen) && (digitLoc != 0)){\n discard;\n }\n \n fragColor = vec4(color, alpha);\n }\n "}
};

0 comments on commit 77f83bb

Please sign in to comment.