Video input fallback
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 3m7s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
Aiden
2026-05-12 18:53:46 +10:00
parent 957c0be05a
commit 2c5e925b97
2 changed files with 166 additions and 24 deletions

View File

@@ -38,6 +38,98 @@ void main()
fragColor = texture(uInputTexture, clamp(vTexCoord, vec2(0.0), vec2(1.0)));
}
)GLSL";
const char* kPatternFragmentShader = R"GLSL(
#version 430 core
uniform vec2 uResolution;
uniform float uFrameIndex;
in vec2 vTexCoord;
out vec4 fragColor;
vec3 hexColor(float r, float g, float b)
{
return vec3(r, g, b) / 255.0;
}
vec3 smpteTop(float x)
{
if (x < 240.0) return hexColor(102.0, 102.0, 102.0);
if (x < 445.0) return hexColor(191.0, 191.0, 191.0);
if (x < 651.0) return hexColor(191.0, 191.0, 0.0);
if (x < 857.0) return hexColor(0.0, 191.0, 191.0);
if (x < 1063.0) return hexColor(0.0, 191.0, 0.0);
if (x < 1269.0) return hexColor(191.0, 0.0, 191.0);
if (x < 1475.0) return hexColor(191.0, 0.0, 0.0);
if (x < 1680.0) return hexColor(0.0, 0.0, 191.0);
return hexColor(102.0, 102.0, 102.0);
}
vec3 smpteMiddleA(float x)
{
if (x < 240.0) return hexColor(0.0, 255.0, 255.0);
if (x < 445.0) return hexColor(0.0, 63.0, 105.0);
if (x < 1680.0) return hexColor(191.0, 191.0, 191.0);
return hexColor(0.0, 0.0, 255.0);
}
vec3 smpteMiddleB(float x)
{
if (x < 240.0) return hexColor(255.0, 255.0, 0.0);
if (x < 445.0) return hexColor(65.0, 0.0, 119.0);
if (x < 1475.0)
{
float ramp = clamp((x - 445.0) / (1475.0 - 445.0), 0.0, 1.0);
return vec3(ramp);
}
if (x < 1680.0) return vec3(1.0);
return hexColor(255.0, 0.0, 0.0);
}
vec3 smpteBottom(float x)
{
if (x < 240.0) return hexColor(38.0, 38.0, 38.0);
if (x < 549.0) return vec3(0.0);
if (x < 960.0) return vec3(1.0);
if (x < 1268.0) return vec3(0.0);
if (x < 1337.0) return hexColor(5.0, 5.0, 5.0);
if (x < 1405.0) return vec3(0.0);
if (x < 1474.0) return hexColor(10.0, 10.0, 10.0);
if (x < 1680.0) return vec3(0.0);
return hexColor(38.0, 38.0, 38.0);
}
vec3 smpteColor(vec2 uv)
{
vec2 pixel = vec2(clamp(uv.x, 0.0, 1.0), 1.0 - clamp(uv.y, 0.0, 1.0)) * vec2(1920.0, 1080.0);
if (pixel.y < 630.0) return smpteTop(pixel.x);
if (pixel.y < 720.0) return smpteMiddleA(pixel.x);
if (pixel.y < 810.0) return smpteMiddleB(pixel.x);
return smpteBottom(pixel.x);
}
void main()
{
vec2 uv = clamp(vTexCoord, vec2(0.0), vec2(1.0));
vec3 color = smpteColor(uv);
float t = uFrameIndex / 60.0;
vec2 cubeSize = vec2(0.16, 0.20);
vec2 cubeMin = vec2(
(0.5 + 0.5 * sin(t * 1.7)) * (1.0 - cubeSize.x),
(0.5 + 0.5 * sin(t * 1.1 + 0.8)) * (1.0 - cubeSize.y));
vec2 cubeMax = cubeMin + cubeSize;
bool insideCube = uv.x >= cubeMin.x && uv.x <= cubeMax.x && uv.y >= cubeMin.y && uv.y <= cubeMax.y;
if (insideCube)
{
vec2 local = (uv - cubeMin) / cubeSize;
vec3 cubeColor = vec3(1.0, 0.74 + 0.18 * sin(t * 2.1), 0.08);
float edge = step(local.x, 0.04) + step(local.y, 0.04) + step(0.96, local.x) + step(0.96, local.y);
color = edge > 0.0 ? vec3(1.0) : cubeColor;
}
fragColor = vec4(color, 1.0);
}
)GLSL";
}
bool SimpleMotionRenderer::InitializeGl(unsigned width, unsigned height)
@@ -49,33 +141,30 @@ bool SimpleMotionRenderer::InitializeGl(unsigned width, unsigned height)
void SimpleMotionRenderer::RenderFrame(uint64_t frameIndex)
{
const float t = static_cast<float>(frameIndex) / 60.0f;
const float red = 0.1f + 0.4f * (0.5f + 0.5f * std::sin(t));
const float green = 0.1f + 0.4f * (0.5f + 0.5f * std::sin(t * 0.73f + 1.0f));
const float blue = 0.15f + 0.3f * (0.5f + 0.5f * std::sin(t * 0.41f + 2.0f));
if (!EnsurePatternProgram())
{
glViewport(0, 0, static_cast<GLsizei>(mWidth), static_cast<GLsizei>(mHeight));
glDisable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
return;
}
glViewport(0, 0, static_cast<GLsizei>(mWidth), static_cast<GLsizei>(mHeight));
glDisable(GL_SCISSOR_TEST);
glClearColor(red, green, blue, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
const int boxWidth = (std::max)(1, static_cast<int>(mWidth / 6));
const int boxHeight = (std::max)(1, static_cast<int>(mHeight / 5));
const float phase = 0.5f + 0.5f * std::sin(t * 1.7f);
const int x = static_cast<int>(phase * static_cast<float>(mWidth - static_cast<unsigned>(boxWidth)));
const int y = static_cast<int>((0.5f + 0.5f * std::sin(t * 1.1f + 0.8f)) * static_cast<float>(mHeight - static_cast<unsigned>(boxHeight)));
glEnable(GL_SCISSOR_TEST);
glScissor(x, y, boxWidth, boxHeight);
glClearColor(1.0f - red, 0.85f, 0.15f + blue, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
const int stripeWidth = (std::max)(1, static_cast<int>(mWidth / 80));
const int stripeX = static_cast<int>((frameIndex % 120) * (mWidth - static_cast<unsigned>(stripeWidth)) / 119);
glScissor(stripeX, 0, stripeWidth, static_cast<GLsizei>(mHeight));
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glUseProgram(mPatternProgram);
const GLint resolutionLocation = glGetUniformLocation(mPatternProgram, "uResolution");
if (resolutionLocation >= 0)
glUniform2f(resolutionLocation, static_cast<float>(mWidth), static_cast<float>(mHeight));
const GLint frameIndexLocation = glGetUniformLocation(mPatternProgram, "uFrameIndex");
if (frameIndexLocation >= 0)
glUniform1f(frameIndexLocation, static_cast<float>(frameIndex));
glBindVertexArray(mPatternVertexArray);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
}
void SimpleMotionRenderer::RenderTexture(GLuint texture)
@@ -103,11 +192,42 @@ void SimpleMotionRenderer::RenderTexture(GLuint texture)
void SimpleMotionRenderer::ShutdownGl()
{
DestroyPatternProgram();
DestroyTextureProgram();
mWidth = 0;
mHeight = 0;
}
bool SimpleMotionRenderer::EnsurePatternProgram()
{
if (mPatternProgram != 0)
return true;
if (!CompileShader(GL_VERTEX_SHADER, kTextureVertexShader, mPatternVertexShader))
return false;
if (!CompileShader(GL_FRAGMENT_SHADER, kPatternFragmentShader, mPatternFragmentShader))
{
DestroyPatternProgram();
return false;
}
mPatternProgram = glCreateProgram();
glAttachShader(mPatternProgram, mPatternVertexShader);
glAttachShader(mPatternProgram, mPatternFragmentShader);
glLinkProgram(mPatternProgram);
GLint linkResult = GL_FALSE;
glGetProgramiv(mPatternProgram, GL_LINK_STATUS, &linkResult);
if (linkResult == GL_FALSE)
{
DestroyPatternProgram();
return false;
}
glGenVertexArrays(1, &mPatternVertexArray);
return mPatternVertexArray != 0;
}
bool SimpleMotionRenderer::EnsureTextureProgram()
{
if (mTextureProgram != 0)
@@ -160,6 +280,22 @@ void SimpleMotionRenderer::DestroyTextureProgram()
mTextureVertexArray = 0;
}
void SimpleMotionRenderer::DestroyPatternProgram()
{
if (mPatternProgram != 0)
glDeleteProgram(mPatternProgram);
if (mPatternVertexShader != 0)
glDeleteShader(mPatternVertexShader);
if (mPatternFragmentShader != 0)
glDeleteShader(mPatternFragmentShader);
if (mPatternVertexArray != 0)
glDeleteVertexArrays(1, &mPatternVertexArray);
mPatternProgram = 0;
mPatternVertexShader = 0;
mPatternFragmentShader = 0;
mPatternVertexArray = 0;
}
bool SimpleMotionRenderer::CompileShader(GLenum shaderType, const char* source, GLuint& shader)
{
shader = glCreateShader(shaderType);