如何创建和使用非常大的调色板纹理以在 opengl 中使用?

2024-02-26

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

不确定是否将其发布在此处、Gamedev SE 或 Math SE 上。

编辑:我想我可能没有添加有关该问题的足够信息,因此这里有一些更多详细信息。

我目前对地图的想法是保留省份颜色的索引调色板,并在我的片段着色器中执行调色板交换操作(就像这个问题中概述的那样:使用 OpenGL 着色器模拟调色板交换(在 LibGDX 中) https://stackoverflow.com/questions/26132160/simulating-palette-swaps-with-opengl-shaders-in-libgdx)。我的着色器几乎完全是从链接的文章中复制的。

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

首先,我决定将调色板纹理配置为 (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 问题的接受答案的片段着色器传递给精灵。精灵将由大约 10 个独特的 RGB 值组成,但是无论使用什么系统都必须支持至少数千种不同的独特颜色。我没有稳定的互联网连接,否则我会上传我的测试纹理。


不确定我是否正确,假设整数通道<0,255> so:

id = r + 256*g + 65536*b

那会给你id = <0,16777215>。现在只需重新映射到您的xs*ys质地:

x = id%xs
y = id/xs

where xs,ys是纹理的分辨率。一旦您意识到可以使用 2 的幂来完成所有这些操作,您就可以使用位运算来代替。例如让xs=4096,ys=4096 ...

id = r + g<<8 + b<<16
x = id&4095
y = id>>12

[Edit1]

因此,如果我使用您链接的这张图像作为输入(txr_map):

并生成 4096x4096 纹理全部归档0x00404040灰色,除了:

((DWORD*)(scr.txrs.txr.txr))[0x4A3020]=0x00FF0000;
((DWORD*)(scr.txrs.txr.txr))[0x49247E]=0x0000FF00;
((DWORD*)(scr.txrs.txr.txr))[0xCB3EAD]=0x000000FF;
((DWORD*)(scr.txrs.txr.txr))[0xC78A4F]=0x0000FFFF;
((DWORD*)(scr.txrs.txr.txr))[0x593D4E]=0x00FF00FF;
((DWORD*)(scr.txrs.txr.txr))[0x4B3C7E]=0x00FFFF00;

where scr.txrs.txr.txr是线性分配的纹理数组,所以地址也是你的id...这选择了我用颜色选择器拾取的几个区域,并将它们设置为特定的颜色(红色,绿色,蓝色,...)。

不要忘记设置GL_LINEAR适用于最小和最大过滤器。然后应用这些着色器应该可以解决问题:

//---------------------------------------------------------------------------
// Vertex
//---------------------------------------------------------------------------
#version 120
varying vec2 pos;   // screen position <-1,+1>
varying vec2 txr;   // texture position <0,1>
void main()
    {
    pos=gl_Vertex.xy;
    txr=gl_MultiTexCoord0.st;
    gl_Position=gl_Vertex;
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Fragment
//---------------------------------------------------------------------------
#version 130
in vec2 pos;    // screen position <-1,+1>
in vec2 txr;    // texture position <0,1>
out vec4 col;
uniform sampler2D txr_map;
uniform sampler2D txr_pal;
//---------------------------------------------------------------------------
void main()
    {
    vec3 c;
    int id,x,y;

    c=texture2D(txr_map,txr).rgb;
    x=int(float(c.b*255.0f)); id =x;
    x=int(float(c.g*255.0f)); id|=x<<8;
    x=int(float(c.r*255.0f)); id|=x<<16;

    x= id     &4095;
    y=(id>>12)&4095;
    c.s=(float(x)+0.5f)/4096.0f;
    c.t=(float(y)+0.5f)/4096.0f;
    col=texture2D(txr_pal,c.st);
    }
//---------------------------------------------------------------------------

Sadly usampler2D在我的旧 API 引擎中不起作用(这就是我使用float这很可能是一些内部纹理格式问题)。我的CPU side GL代码如下所示:

//---------------------------------------------------------------------------
OpenGLscreen scr;   // my GL engine
GLSLprogram shd;    // shaders
GLint txr_map=-1;   // map
GLint txr_pal=-1;   // palette
//---------------------------------------------------------------------------
void TForm1::draw()
    {
    scr.cls();  // glClear

    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);
    shd.bind(); // use shader program
    int unit=0;
    scr.txrs.bind(txr_map,unit); shd.set1i("txr_map",unit); unit++; // bind textures and set uniforms
    scr.txrs.bind(txr_pal,unit); shd.set1i("txr_pal",unit); unit++;
    float a=5632.0/8192.0;  // handle texture power of 2 size correction

    glActiveTexture(GL_TEXTURE0);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0);
    glTexCoord2f(0.0,0.0); glVertex2f(-1.0,+1.0);
    glTexCoord2f( a ,0.0); glVertex2f(+1.0,+1.0);
    glTexCoord2f( a ,1.0); glVertex2f(+1.0,-1.0);
    glEnd();

    for (unit--;unit>=0;unit--) scr.txrs.unbind(unit);  // unbind textures
    shd.unbind();   // unbind shaders

    // just prints the GLSL logs for debug
    scr.text_init_pix(1.0);
    glColor4f(1.0,1.0,1.0,0.75);
    scr.text(0.0,0.0,shd.log);
    scr.text_exit_pixel();

    scr.exe();  // glFlush
    scr.rfs();  // swap buffers
    }
//---------------------------------------------------------------------------

结果如下:

当我将结果和输入纹理(用于目视检查)与以下内容混合时:

col=(0.9*texture2D(txr_pal,c.st))+(0.1*texture2D(txr_map,txr));

结果如下:

所以它显然按预期工作......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建和使用非常大的调色板纹理以在 opengl 中使用? 的相关文章

  • 无法解决:com.google.android.gms:在 IntelliJ Idea 中使用 gradle 播放服务

    我正在尝试将 google play 服务添加到 IntelliJ Idea 中的 libGDX 项目中 我已按照此处的设置指南进行操作 https developers google com android guides setup ht
  • 如何生成多个apk(使用gradle,libGDX)

    我试试这个 http tools android com tech docs new build system user guide apk splits 我想生成一些APK x86 armeabi v7a 为了减少Google Play中
  • GLSL 纹理立方体和纹理2D 在同一着色器中

    我似乎无法两者兼得texture2D and textureCube 在一个着色器中 当我这样做时 什么也没有显示 也没有错误 我用我自己的着色器加载器和 Apple GLSL 着色器生成器尝试了这一点 并且发生了同样的事情 即使我有也会发
  • 如何处理带有 Pixmap 纹理的 libGDX 图像的恢复

    我有一个从 Pixmap 构建的 com badlogic gdx scenes scene2d ui Image Pixmap 只有一个像素 因为我用它来构建一个图像 该图像充当可以淡入和淡出的背景 Pixmap pmap new Pix
  • OpenGL - 固定管线着色器默认值(使用着色器模仿固定管线)

    谁能给我提供类似于固定功能管道的着色器 我最需要默认的片段着色器 因为我在网上找到了类似的顶点着色器 但如果你有一双应该没问题 我想使用固定管道 但具有着色器的灵活性 因此我需要类似的着色器 以便我能够模仿固定管道的功能 非常感谢 我是新来
  • 您应该如何有效地批处理复杂的网格?

    渲染复杂网格的最佳方法是什么 我在下面写了不同的解决方案 想知道您对它们有何看法 让我们举个例子 如何渲染 Crytek Sponza 网格 PS 我不使用Ubershader 只使用单独的着色器 如果您通过以下链接下载网格 http gr
  • glDrawBuffer(GL_NONE) 与 glColorMask 设置为全部 GL_FALSE

    glDrawBuffer GL NONE 和 glColorMask GL FALSE GL FALSE GL FALSE GL FALSE 有什么区别 两者只是丢弃对颜色缓冲区的任何绘制的另一种方式吗 还是有一些差异 首先也是最重要的 g
  • Libgdx 模板和形状渲染器

    我正在尝试完成这样的事情 样本图像 https i stack imgur com CkdSO jpg 整个屏幕将是黑色的 然后三角形的内部是只会出现的部分 我尝试使用剪刀 但它是矩形的 原始图片来源 https www html5rock
  • 对数/线性 Z 缓冲区阴影贴图

    问题在于 伪影出现在距离很远的阴影中 我想尝试制作一个对数深度缓冲区 但我不明白应该在哪里完成以及如何完成 我对全向阴影贴图使用点光源方法 顶点着色器 version 460 core layout location 0 in vec3 a
  • 尝试在 Genymotion 上使用 libgdx 运行 Android 游戏

    有人对 libgdx 和 genymotion 有经验吗 我正在尝试让 libgdx 游戏在 genymotion Android 模拟器上运行 http www genymotion com http www genymotion com
  • 编写每个三角形/面具有纯色的 GLSL 片段着色器的方法

    我有顶点和三角形数据 其中包含每个数据的颜色triangle 面 不是每个顶点 即单个顶点由多个面共享 每个面可能具有不同的颜色 我应该如何在 GLSL 中解决这个问题以获得每个的纯色分配face正在渲染 通过平均顶点相邻多边形的颜色来计算
  • 实现移动运动体

    Project 我正在制作一个简单的项目 其中我希望能够制作一个运动体并将其从 x 点移动到 y 点 创建运动体 似乎没有太多直接内容 我一直在关注一些关于实现运动体的不同教程 因为我找不到指定如何正确执行此操作的教程 Problem 这似
  • 使用 libGDX 写入 Json

    我是 Json 和 libGDX 的新手 但我创建了一个简单的游戏 我想将玩家姓名及其分数存储在 Json 文件中 有没有办法做到这一点 我想创建一个 Json 文件Gdx files localStorage如果它不存在 如果存在 则向其
  • 即使在顶点着色器中使用,glGetUniformLocation()也会返回-1

    我正在尝试用法线渲染一个简单的立方体 我使用以下代码来初始化着色器 void initShader const char vertexShaderPath const char fragmentShaderPath cout lt lt I
  • LibGDX - 正确使用 Polygon 类

    我创造了Polygon包裹我的飞机的物体 飞机的大小TextureRegion是 256x74 但在游戏中这个尺寸是 70x20 所以 TextureRegion texRegsAirplane TextureRegion split te
  • GLSL 棋盘图案

    我想用跳棋来遮蔽四边形 f P 下限 Px 下限 Py mod2 我的四边形是 glBegin GL QUADS glVertex3f 0 0 0 0 glVertex3f 4 0 0 0 glVertex3f 4 4 0 0 glVert
  • 使用 libgdx 裁剪图像

    I need to crop image like this 我需要从中心绘制部分图像 我知道有一个带有很多参数的批处理的draw 方法 但是没有关于所有这些参数的良好文档 所以我不知道如何使用它 这是我实现的 public class T
  • WebGL - 如何传递无符号字节顶点属性颜色值?

    我的顶点由具有以下结构的数组组成 Position colour float float float byte byte byte byte 传递顶点位置没有问题 gl bindBuffer gl ARRAY BUFFER this vbo
  • LibGDX 非常奇怪的错误 - 对象消失了

    当我创建我的第一个平铺地图创建器时libGDX 我注意到一个非常奇怪的错误 我创建这样的对象网格 private static final int GRID WIDTH 2400 private static final int GRID
  • 将seaborn.palplot轴添加到现有图形中以可视化不同调色板

    将seaborn人物添加到子图中是usually https seaborn pydata org examples cubehelix palette html创建图形时通过传递 ax 来完成 例如 sns kdeplot x y cma

随机推荐

  • 如何矢量化(利用 pandas/numpy)而不是使用嵌套 for 循环

    我希望有效地使用pandas or numpy 而不是嵌套for循环与if解决特定问题的语句 这是一个玩具版本 假设我有以下两个 DataFrame import pandas as pd import numpy as np dict1
  • 无法读取架构文档'http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd

    我正在为大学编写一个简单的 Swing 应用程序 并使用 Hibernate 和 Oracle XE 我被这个错误困住了 29 06 2011 14 54 10 org hibernate cfg annotations Version
  • 放大图像映射的某个区域

    我目前正在尝试制作一个响应式图像地图 我们还可以在其中缩放特定区域 目前我有类似的东西 插图 例如 我有 3 个部分用于 3 个不同的区域 但现在我不想在用户单击特定区域时放大该区域 我已经尝试了一些 jquery 脚本 但问题是它会缩放所
  • 如何隐藏Android手机上的软键栏?

    当我的应用程序启动时 我想隐藏软键栏 红色矩形 以获得更大的屏幕 我怎样才能隐藏它 当应用程序退出时 我是否需要特意显示该栏 或者应用程序退出后它会自动恢复 Android 4 1 手机正面没有硬件按键 我知道已经晚了 但这是正确的答案 所
  • 如何在 Spring Tools Suite 上添加 Spring roo

    我已经安装了 sts 但创建的新 roo 项目不存在 我需要做什么才能添加 spring roo 在以前的版本中我可以创建它 但在 3 5 0 中不行 在 Spring 工具套件中 单击仪表板中的 扩展 链接 搜索 Spring Roo 并
  • “known_hosts”文件中的 ECDSA 条目由哪些部分组成?

    我正在尝试从我的文件中提取 ECDSA 公钥已知主机归档该文件ssh用于验证主机 我下面有一个例子 这是我的known hosts 文件中 127 0 0 1 ecdsa sha2 nistp256 的条目 AAAAE2VjZHNhLXNo
  • Express 应用程序 - 更改基本 url

    我正在构建一个问答应用程序本教程 http engineering paiza io entry 2016 03 10 115345一切顺利 但我需要更改更改通过配置文件提供应用程序的基本根的机会 现在 该应用程序在 localhost 8
  • 使用 jquery 将表单值传递到 iframe 的 src url

    我一直让自己发疯去尝试做看似简单的事情 我有一张表格 我可以在其中询问邮政编码 在您输入邮政编码后 我使用 colorbox 弹出带有 iframe 的灯箱 我需要将表单中的邮政编码值传递到 iframe 的源 URL 中 我的表单代码如下
  • 下拉框显示的高度[重复]

    这个问题在这里已经有答案了 可能的重复 调整下拉框中列表的高度 https stackoverflow com questions 5600646 adjust the height of the list in dropdown box
  • std::set 2D 点的自定义比较器

    我需要一个非重复的 2D 点列表 所以我使用std set具有自定义比较功能 我使用的函数在插入点后出现问题 因为有时std find找不到已经插入的点 const double tolerance 0 1 struct MyPoint2D
  • 从Optional<>转换为ArrayList<>

    我有以下情况 public ArrayList a getMethods return b c test 所以 我的问题是b c test 返回一个值Optional a 作为返回类型 但我需要返回一个ArrayList a 所以 我尝试将
  • 完整原型太大而无法保存,已清除变量

    我在渲染谷歌应用程序引擎代码时遇到此错误 有人知道这个错误吗 你在使用appstats吗 当 appstats 记录有关应用程序的状态时 尤其是在堆栈上存储大量数据时 可能会发生这种情况 它没有害处 但在 appstats 中检查调用时您将
  • 如果焦点是 edittext,则禁止滚动 recyclerview

    我有一个带有水平滚动的回收器视图 recyclerview 中的每个项目都有编辑文本 当我单击 edittext 时 recyclerview 滚动到末尾 我怎样才能禁止滚动 谢谢 您可以在 EditText 上设置焦点事件侦听器以禁用焦点
  • 黑莓 - 应用程序已在商店上架;我可以更改代码签名密钥吗

    不久前 我们为客户构建了一个应用程序 使用我们公司的密钥对其进行签名 并将其放在 BlackBerry App World 商店中 此后我们终止了与客户的合同 他们现在已经对该应用程序进行了进一步的 内部 开发 并要求我们提供签名密钥 以便
  • 如何从 Azure AD 获取用户列表?

    我正在使用 asp net core MVC 我想从 Azure AD 读取用户 我读了很多微软文档 我知道我必须使用 GraphAPI 来做到这一点 但我不知道如何做 现在一切都让我感到困惑 我不知道在哪里放置代码 我不知道在哪里获取 G
  • create-react-app eintegrity 错误窗口

    当我开始在 Windows 10 电脑中创建 React 应用程序时 出现了这些错误 请帮我解决这个问题 PS F gt npm install g create react app C Users Harshit Singh AppDat
  • R:调整圈图中的标签

    我有下面的代码 我试图使用令人惊叹的包 circlize 制作一个圆形图 我读过这个小插图并承认其中一些内容有点超出了我的理解范围 我想知道是否有一种快速方法可以删除图表上的所有标签 包括刻度线 然后按照与扇区相同的角度以浅灰色重新添加奥迪
  • 是否可以在 GDB 中命名断点?

    有没有办法在 GDB 中标记 命名断点 以便更容易地识别它们 例如 info b 如果是这样 怎么办 不 没有办法做到这一点 http users ece utexas edu adnan gdb refcard pdf http user
  • 删除 Spark 中不遵循架构的行

    目前 我的表的架构是 root product id integer nullable true product name string nullable true aisle id string nullable true departm
  • 如何创建和使用非常大的调色板纹理以在 opengl 中使用?

    详细信息 我有一个带有统一纹理的 glsl 片段着色器 u MapTexture 上面有几千种颜色 最多大约 10k 15k 唯一的 rgb 值 我还有一个统一的调色板纹理 u paletteTexture 大小为 16384 1 我想用它