kotlin - 将音频频谱作为 libGDX 中的纹理传递给着色器

标签 kotlin libgdx glsl shader

我正在使用 libGDX 开发音频可视化工具。

我想将音频频谱数据(包含音频样本的 FFT 的数组)传递到我从 Shadertoy 获取的着色器:https://www.shadertoy.com/view/ttfGzH .

在 GLSL 代码中,我期望一个包含数据作为纹理的制服:

均匀采样器2D iChannel0;

问题是我无法弄清楚如何将任意数组作为纹理传递给 libGDX 中的着色器。

我已经在 SO 和 libGDX 论坛中进行了搜索,但我的问题没有令人满意的答案。

这是我的 Kotlin 代码(显然不起作用 xD):

val p = Pixmap(512, 1, Pixmap.Format.Alpha)
val t = Texture(p)
val map = p.pixels
map.putFloat(....) // fill the map with FFT data
[...]
t.bind(0)
shader.setUniformi("iChannel0", 0)

最佳答案

您可以简单地使用drawPixel方法并将数据存储在每个像素的第一个 channel 中,就像在shadertoy示例中一样(它们使用红色 channel )。

float[] fftData = // your data

Color tmpColor = new Color();
Pixmap pixmap = new Pixmap(fftData.length, 1, Pixmap.Format.RGBA8888);
for(int i = 0; i < fftData.length i++)
{
    tmpColor.set(fftData[i], 0, 0, 0); // using only 1 channel per pixel
    pixmap.drawPixel(i, 0, Color.rgba8888(tmpColor));
}
// then create your texture and bind it to the shader

为了提高效率并减少 4 倍的内存需求(并且可能需要更少的样本,具体取决于着色器),您可以通过将数据拆分为 r、g、b 和 a channel ​​,为每个像素使用 4 个 channel 。但是,这会使着色器变得有点复杂。

您提供的着色器示例中传递的数据不是任意的,它的精度非常有限,范围在 0 到 1 之间。如果您想提高精度,您可能需要跨多个 channel 存储浮点(尽管着色器中的 IEEE 重组可能很痛苦)或传递要缩小的整数(定点)。如果您需要 -inf 和 inf 之间的数据,您可以使用 sigmoid 和 anti sigmoig 函数,但代价是再次大幅降低精度。我相信这种技术适用于您的示例,因为它们似乎只需要 0 到 1 之间的值,并且精度并不是非常重要,因为结果是平滑的。

关于kotlin - 将音频频谱作为 libGDX 中的纹理传递给着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59557460/

相关文章:

glsl - 片段着色器 glsl 中的世界位置到屏幕位置

gradle - 使用 Kotlin Sync 配置 Clean LibGDX 项目失败,类型代码无效 :82

c++ - 让纹理在 OpenGL 3.2 中工作

kotlin - "overloading"中的 "operator overloading"只是语义吗?

database - Ktor与Gradle从环境变量运行配置 “Could not resolve substitution to a value”

java - 你如何在没有教程的情况下学习框架

java - Libgdx 用纹理重构一个类

opengl - 统一点数组和管理片段着色器坐标系

gradle - 生成 jar 文件以使用 gradle 将 kotlin lib 上传到 bintray

android - Google的Firebase身份验证