Libgdx 如何创建和使用opengl中使用的超大调色板纹理?

Libgdx 如何创建和使用opengl中使用的超大调色板纹理?,libgdx,glsl,fragment-shader,palette,color-palette,Libgdx,Glsl,Fragment Shader,Palette,Color Palette,详细信息:我有一个glsl片段着色器,具有统一的纹理,“u_MapTexture”,上面有几千种颜色(最大约10k-15k的唯一rgb值)。我还有一个统一的调色板纹理(“u_paletteTexture”),它是16384×1,我想用来索引u_MapTexture上的颜色。我的问题是,无论我在数学上做了什么尝试,我似乎都无法使用传递颜色的RGB值正确地将颜色从第一个纹理索引到调色板纹理。艾米对我如何做到这一点有什么想法 我不确定是在Gamedev SE上发布,还是在Math SE上发布 编辑:我

详细信息:我有一个glsl片段着色器,具有统一的纹理,“u_MapTexture”,上面有几千种颜色(最大约10k-15k的唯一rgb值)。我还有一个统一的调色板纹理(“u_paletteTexture”),它是16384×1,我想用来索引u_MapTexture上的颜色。我的问题是,无论我在数学上做了什么尝试,我似乎都无法使用传递颜色的RGB值正确地将颜色从第一个纹理索引到调色板纹理。艾米对我如何做到这一点有什么想法

我不确定是在Gamedev SE上发布,还是在Math SE上发布

编辑:我想我可能没有在中添加足够的有关问题的信息,所以这里有一些更详细的信息

我目前对地图的想法是保留一个省颜色的索引调色板,并在片段着色器中执行调色板交换操作(就像这个问题中概述的那样:)。我的着色器几乎完全是从链接文章中复制的

我的问题是:找到唯一索引省地图(原始纹理)->省颜色(索引调色板纹理)的方法

首先,我决定将调色板纹理配置为(255+255)×(255+255)纹理。这将使最大数量的国家有足够数量的国家可供选择,而这在实践中是永远无法实现的

我想你可以通过在纹理中获得一个国家的颜色调色板纹理的适当索引:每个国家的索引应该位于该调色板纹理的(x,y)->(r+g),(g+b)

我通过这个简单的等式运行了一些示例颜色,遇到了一个令人不安的场景:

RGB (0, 0, 0) -> (0, 0);
RGB (1, 0, 1) -> (1, 1); ?
RGB (1, 3, 2) -> (4, 5);
RGB (0, 1, 0) -> (1, 1); ?
RGB (2, 5, 10) -> (7, 15);
RGB (255, 255, 255) -> (510, 510);
问号是通过算法中的“重复”颜色来表示的,这意味着它们将错误地映射到同一个国家索引

然后我想添加额外的参数,并将纹理缩小为一维数组

例如,调色板纹理的大小应该是(r+g+b),(r,g,b)

使用此选项,可以使用相同的纹理点:

RGB(0, 0, 0) -> (0);
RGB(1, 0, 1) -> (2); ?
RGB(0, 1, 1) -> (2); ?
RGB(1, 3, 2) -> (6); ?
RGB(3, 2, 1) -> (6); ?
RGB(0, 1, 0) -> (1);
RGB(2, 5, 10) -> (17);
RGB(255, 255, 255) -> (1020);
复发问题加剧了。我在脑子里做了一些快速的计算(并对其进行了更深入的思考),我意识到无论我以多少种方式添加/乘以颜色rgb变量,由于数学定律,同样的问题也会发生。这导致了一个实际问题:如何在调色板纹理中唯一地、按程序地索引国家颜色,并通过着色器访问它们?这似乎是最有效的方法,但它的实现却让我难以捉摸

另外,作为记录,我知道UV坐标和颜色值是浮动的,但我使用标准的0-255格式来逻辑解决问题

TL;DR我需要从每个RGB值中提取一个唯一的索引,而基于我的测试集,这似乎是不可能的


基本上,MCVE将创建一个2D精灵,并将链接SO问题的可接受答案的片段着色器传递给精灵。sprite将由大约10个独特的RGB值组成,但是无论使用什么系统,都必须支持至少几千种不同的独特颜色。我没有稳定的互联网连接,或者我会上传我的测试纹理。

我不确定我是否完全理解你想要做什么

首先,将所有8位RGB颜色唯一映射到索引的唯一方法是使用256^3个索引。您可以将这些位混洗以获得非标识映射(如),但仍然需要那么多的目标索引

如果只使用所有颜色的一个子集,并且您想要的目标索引少于256^3(正如您所描述的),则需要设置一些机制以避免冲突。除非在源颜色中有一些特殊的属性可以通过数学方法加以利用,否则这种机制将需要某种形式的存储(如另一种纹理或SSBO)


现在我不明白的是你想映射到什么索引。是否要将所有可能的颜色映射到唯一索引?是否所有与贴图相关的操作都必须仅在着色器内完成?您提到了国家和省份,但我不太清楚它们与您想要的映射的确切关系。

不确定我是否正确,让我们假设整数通道
,因此:

id = r + 256*g + 65536*b
这将为您提供
id=
。现在只需重新映射到您的
xs*ys
纹理:

x = id%xs
y = id/xs
其中
xs,ys
是纹理的分辨率。一旦你意识到你可以用2的幂来完成所有这些,你可以用位运算来代替。例如,让
xs=4096,ys=4096

id = r + g<<8 + b<<16
x = id&4095
y = id>>12
其中,
scr.txrs.txr.txr
是线性分配的纹理数组,所以地址也是您的
id
。。。这将选择我用颜色选择器拾取的几个区域,并将它们设置为特定的颜色(红色、绿色、蓝色……)

不要忘记为最小和最大过滤器设置
GL\u线性
。然后应用这些着色器应该可以实现以下目的:

//---------------------------------------------------------------------------
//顶点
//---------------------------------------------------------------------------
#版本120
可变vec2位置;//屏幕位置
可变vec2 txr;//纹理位置
void main()
{
pos=gl_顶点.xy;
txr=gl_MultiTexCoord0.st;
gl_位置=gl_顶点;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//碎片
//---------------------------------------------------------------------------
#版本130
在vec2位置中;//屏幕位置
在vec2 txr中;//纹理位置
输出vec4列;
均匀采样二维txr_图;
均匀取样器2D txr\U pal;
//---------------------------------------------------------------------------
void main()
{
vec3c;
int-id,x,y;
c=纹理2d(txr_-map,txr).rgb;
x=int(fl