制作这个颜色查看器的目的 一直以来我都觉得调试GPU代码是一件很困难的事情,在屏幕上显示的颜色会被限制在0和1之间,所以我很希望能够有那么一个工具,能够让我切切实实的看到输出的数据。如果是写的CPU代码的话,又会对伽马空间的矫正之类的有一些担心,而且可复用程度不够高。因此我就希望能够在GPU传回的图像上直接显示颜色和其对应的数值。
碰巧之前在Shader Toy上看到了一些在GPU上输出文字的案例,研究了一下之后,就制作了这么一个颜色查看器。
GPU显示文字的原理 一种是将文字储存到一张贴图上,通过采样这张贴图来显示这些文字,可以通过SDF的方法,自由的调节文字的粗细,也不会有锯齿;另一种是将文字直接用01数据来储存,对应到屏幕上,0的区域显示黑色,1的区域显示白色,本文就采用了这种方式;当然Shader Toy上还有一种是将文字用曲线来储存的,应该是涉及到傅里叶变换。
本文的标准文字是8*12个像素大,每三行进行合并的话,就是一个24 * 4的01矩阵,这就能将一个文字使用uint4来储存,每个通道还多余8bit。具体可以看Shader Toy案例里的描述,我觉得写的十分直观了。
但是这个案例里面有一点我觉得不太好的地方,他对于每一个像素,都要计算每一个文字的颜色,也就是说文字越多计算的复杂度越大。我想的是最好能够使用StructuredBuffer的方式,先用一个pass计算要显示的文字,然后对于每一个像素,计算出要显示的文字的编号,再在Structured Buffer中找到对应的文字,最终显示出来。这样每个像素应该之多只需要做一次文字到颜色的计算,能够提高效率。
颜色查看器具体的操作 首先要先把需要显示的文字对应的uint4值计算出来,这一步之前的案例里已经有现成的数据了。最好是将这些数据组成一个数列,这样我们之后能够用其编号来访问文字对应的数据。 执行一个(1, 1, 1)的Compute Shader,获取要采样的像素点的颜色。对像素点的每一位,都将其转换成要输出的文字对应的编号,储存到_Append_CharacterIndexBuffer中。像本文中需要显示7这个数字的话,需要添加23这个编号到我们的输出数据中。同时,由于每一个像素点有rgba四个通道,但我们输出的是一个RWStructuredBuffer<int>的数据,我们还需要一个列表_RW_LengthBuffer(相当于指针),记录每一个通道对应的数据数列的区间。 对整个画面执行Compute Shader,根据每一个像素点的位置,判断是显示放大的图像、每个通道对应的文字或是原始的画面。如果要显示文字的话,根据需要显示的RGBA通道,找到对应的_RW_LengthBuffer获得编号区间,再找到_Struct_CharacterIndexBuffer中获得对应的编号,通过编号找到对应的文字。最后再根据像素的位置,求出在该文字中应当显示的颜色。 在Unity中我选择了用Volume和Renderer Feature的方法,对后处理之前的画面进行颜色查看的操作。 整体想法还是尽量的减少采样,减少文字到颜色的计算,以及减少分支判断。 Font.hlsl 就是案例中的8*12的文字对应的uint4表,这里将其用数列来保存。
#define character_spc characterSet[0] #define character_exc characterSet[1] #define character_quo characterSet[2] #define character_hsh characterSet[3] #define character_dol characterSet[4] #define character_pct characterSet[5] #define character_amp characterSet[6] #define character_apo characterSet[7] #define character_lbr characterSet[8] #define character_rbr characterSet[9] #define character_ast characterSet[10] #define character_crs characterSet[11] #define character_com characterSet[12] #define character_dsh characterSet[13] #define character_per characterSet[14] #define character_lsl characterSet[15] #define character_0 characterSet[16] #define character_1 characterSet[17] #define character_2 characterSet[18] #define character_3 characterSet[19] #define character_4 characterSet[20] #define character_5 characterSet[21] #define character_6 characterSet[22] #define character_7 characterSet[23] #define character_8 characterSet[24] #define character_9 characterSet[25] #define character_col characterSet[26] #define character_scl characterSet[27] #define character_les characterSet[28] #define character_equ characterSet[29] #define character_grt characterSet[30] #define character_que characterSet[31] #define character_ats characterSet[32] #define character_A characterSet[33] #define character_B characterSet[34] #define character_C characterSet[35] #define character_D characterSet[36] #define character_E characterSet[37] #define character_F characterSet[38] #define character_G characterSet[39] #define character_H characterSet[40] #define character_I characterSet[41] #define character_J characterSet[42] #define character_K characterSet[43] #define character_L characterSet[44] #define character_M characterSet[45] #define character_N characterSet[46] #define character_O characterSet[47] #define character_P characterSet[48] #define character_Q characterSet[49] #define character_R characterSet[50] #define character_S characterSet[51] #define character_T characterSet[52] #define character_U characterSet[53] #define character_V characterSet[54] #define character_W characterSet[55] #define character_X characterSet[56] #define character_Y characterSet[57] #define character_Z characterSet[58] #define character_lsb characterSet[59] #define character_rsl characterSet[60] #define character_rsb characterSet[61] #define character_pow characterSet[62] #define character_usc characterSet[63] #define character_a characterSet[64] #define character_b characterSet[65] #define character_c characterSet[66] #define character_d characterSet[67] #define character_e characterSet[68] #define character_f characterSet[69] #define character_g characterSet[70] #define character_h characterSet[71] #define character_i characterSet[72] #define character_j characterSet[73] #define character_k characterSet[74] #define character_l characterSet[75] #define character_m characterSet[76] #define character_n characterSet[77] #define character_o characterSet[78] #define character_p characterSet[79] #define character_q characterSet[80] #define character_r characterSet[81] #define character_s characterSet[82] #define character_t characterSet[83] #define character_u characterSet[84] #define character_v characterSet[85] #define character_w characterSet[86] #define character_x characterSet[87] #define character_y characterSet[88] #define character_z characterSet[89] #define character_lpa characterSet[90] #define character_bar characterSet[91] #define character_rpa characterSet[92] #define character_tid characterSet[93] #define character_lar characterSet[94] static int4 characterSet[] = { int4(0x000000,0x000000,0x000000,0x000000), int4(0x003078,0x787830,0x300030,0x300000), int4(0x006666,0x662400,0x000000,0x000000), int4(0x006C6C,0xFE6C6C,0x6CFE6C,0x6C0000), int4(0x30307C,0xC0C078,0x0C0CF8,0x303000), int4(0x000000,0xC4CC18,0x3060CC,0x8C0000), int4(0x0070D8,0xD870FA,0xDECCDC,0x760000), int4(0x003030,0x306000,0x000000,0x000000), int4(0x000C18,0x306060,0x603018,0x0C0000), int4(0x006030,0x180C0C,0x0C1830,0x600000), int4(0x000000,0x663CFF,0x3C6600,0x000000), int4(0x000000,0x18187E,0x181800,0x000000), int4(0x000000,0x000000,0x000038,0x386000), int4(0x000000,0x0000FE,0x000000,0x000000), int4(0x000000,0x000000,0x000038,0x380000), int4(0x000002,0x060C18,0x3060C0,0x800000), int4(0x007CC6,0xD6D6D6,0xD6D6C6,0x7C0000), int4(0x001030,0xF03030,0x303030,0xFC0000), int4(0x0078CC,0xCC0C18,0x3060CC,0xFC0000), int4(0x0078CC,0x0C0C38,0x0C0CCC,0x780000), int4(0x000C1C,0x3C6CCC,0xFE0C0C,0x1E0000), int4(0x00FCC0,0xC0C0F8,0x0C0CCC,0x780000), int4(0x003860,0xC0C0F8,0xCCCCCC,0x780000), int4(0x00FEC6,0xC6060C,0x183030,0x300000), int4(0x0078CC,0xCCEC78,0xDCCCCC,0x780000), int4(0x0078CC,0xCCCC7C,0x181830,0x700000), int4(0x000000,0x383800,0x003838,0x000000), int4(0x000000,0x383800,0x003838,0x183000), int4(0x000C18,0x3060C0,0x603018,0x0C0000), int4(0x000000,0x007E00,0x7E0000,0x000000), int4(0x006030,0x180C06,0x0C1830,0x600000), int4(0x0078CC,0x0C1830,0x300030,0x300000), int4(0x007CC6,0xC6DEDE,0xDEC0C0,0x7C0000), int4(0x003078,0xCCCCCC,0xFCCCCC,0xCC0000), int4(0x00FC66,0x66667C,0x666666,0xFC0000), int4(0x003C66,0xC6C0C0,0xC0C666,0x3C0000), int4(0x00F86C,0x666666,0x66666C,0xF80000), int4(0x00FE62,0x60647C,0x646062,0xFE0000), int4(0x00FE66,0x62647C,0x646060,0xF00000), int4(0x003C66,0xC6C0C0,0xCEC666,0x3E0000), int4(0x00CCCC,0xCCCCFC,0xCCCCCC,0xCC0000), int4(0x007830,0x303030,0x303030,0x780000), int4(0x001E0C,0x0C0C0C,0xCCCCCC,0x780000), int4(0x00E666,0x6C6C78,0x6C6C66,0xE60000), int4(0x00F060,0x606060,0x626666,0xFE0000), int4(0x00C6EE,0xFEFED6,0xC6C6C6,0xC60000), int4(0x00C6C6,0xE6F6FE,0xDECEC6,0xC60000), int4(0x00386C,0xC6C6C6,0xC6C66C,0x380000), int4(0x00FC66,0x66667C,0x606060,0xF00000), int4(0x00386C,0xC6C6C6,0xCEDE7C,0x0C1E00), int4(0x00FC66,0x66667C,0x6C6666,0xE60000), int4(0x0078CC,0xCCC070,0x18CCCC,0x780000), int4(0x00FCB4,0x303030,0x303030,0x780000), int4(0x00CCCC,0xCCCCCC,0xCCCCCC,0x780000), int4(0x00CCCC,0xCCCCCC,0xCCCC78,0x300000), int4(0x00C6C6,0xC6C6D6,0xD66C6C,0x6C0000), int4(0x00CCCC,0xCC7830,0x78CCCC,0xCC0000), int4(0x00CCCC,0xCCCC78,0x303030,0x780000), int4(0x00FECE,0x981830,0x6062C6,0xFE0000), int4(0x003C30,0x303030,0x303030,0x3C0000), int4(0x000080,0xC06030,0x180C06,0x020000), int4(0x003C0C,0x0C0C0C,0x0C0C0C,0x3C0000), int4(0x10386C,0xC60000,0x000000,0x000000), int4(0x000000,0x000000,0x000000,0x00FF00), int4(0x000000,0x00780C,0x7CCCCC,0x760000), int4(0x00E060,0x607C66,0x666666,0xDC0000), int4(0x000000,0x0078CC,0xC0C0CC,0x780000), int4(0x001C0C,0x0C7CCC,0xCCCCCC,0x760000), int4(0x000000,0x0078CC,0xFCC0CC,0x780000), int4(0x00386C,0x6060F8,0x606060,0xF00000), int4(0x000000,0x0076CC,0xCCCC7C,0x0CCC78), int4(0x00E060,0x606C76,0x666666,0xE60000), int4(0x001818,0x007818,0x181818,0x7E0000), int4(0x000C0C,0x003C0C,0x0C0C0C,0xCCCC78), int4(0x00E060,0x60666C,0x786C66,0xE60000), int4(0x007818,0x181818,0x181818,0x7E0000), int4(0x000000,0x00FCD6,0xD6D6D6,0xC60000), int4(0x000000,0x00F8CC,0xCCCCCC,0xCC0000), int4(0x000000,0x0078CC,0xCCCCCC,0x780000), int4(0x000000,0x00DC66,0x666666,0x7C60F0), int4(0x000000,0x0076CC,0xCCCCCC,0x7C0C1E), int4(0x000000,0x00EC6E,0x766060,0xF00000), int4(0x000000,0x0078CC,0x6018CC,0x780000), int4(0x000020,0x60FC60,0x60606C,0x380000), int4(0x000000,0x00CCCC,0xCCCCCC,0x760000), int4(0x000000,0x00CCCC,0xCCCC78,0x300000), int4(0x000000,0x00C6C6,0xD6D66C,0x6C0000), int4(0x000000,0x00C66C,0x38386C,0xC60000), int4(0x000000,0x006666,0x66663C,0x0C18F0), int4(0x000000,0x00FC8C,0x1860C4,0xFC0000), int4(0x001C30,0x3060C0,0x603030,0x1C0000), int4(0x001818,0x181800,0x181818,0x180000), int4(0x00E030,0x30180C,0x183030,0xE00000), int4(0x0073DA,0xCE0000,0x000000,0x000000), int4(0x000000,0x10386C,0xC6C6FE,0x000000), }; ColorInspector....