Кодирование половинных значений для глубины во фрагментном шейдере (WebGL 1.0)

В настоящее время у меня есть рабочая реализация, которая позволяет мне кодировать значение глубины в текстуру с плавающей точкой.

Вот функции кодирования / декодирования:

"vec4 EncodeFloatRGBA( float v ) {",
              "float remainder = v;",
              "vec4 res, r;",

              "res[0] = floor(remainder * 255.0) / 255.0;",
              "remainder -= res[0];",
              "res[1] = floor(remainder * 65535.0) / 65535.0;",
              "remainder -= res[1];",
              "res[2] = floor(remainder * 16777215.0) / 16777215.0;",
              "remainder -= res[2];",
              "res[3] = floor(remainder * 4294967295.0) / 4294967295.0;",

              "r[0] = clamp(floor((v) * 255.0),0.,255.);",
              "r[1] = clamp(floor((v - res[0]) * 65535.0),0.,255.);",
              "r[2] = clamp(floor((v - res[0] - res[1]) * 16777215.0),0.,255.);",
              "r[3] = clamp(floor((v - res[0] - res[1] - res[2]) * 4294967295.0),0.,255.);",

              "r[0] = r[0] / 255.0;",
              "r[1] = r[1] / 255.0;",
              "r[2] = r[2] / 255.0;",
              "r[3] = r[3] / 255.0;",
              "return r;",
  "}",
  
"float DecodeFloatRGBA( vec4 rgba ) {",
              "return dot( rgba, vec4(1.0, 0.003921568627450980392156862745098, 1.5259021896696421759365224689097e-5, 5.9604648328104515558750364705942e-8) );",
"}",

Вот как я их использую:

//Encoding in depth pass
"vec4 depth = EncodeFloatRGBA(1.0 - gl_FragCoord.z);",
"depth = floor(depth * 255.) * 0.003921568627450980392156862745098;",//simulate 32-bit encoding
"gl_FragColor = depth;",
  
  
//Decoding in color pass  
"loc = vec2(gl_FragCoord.x/canvas_size.x, gl_FragCoord.y/canvas_size.y);",
"float z = DecodeFloatRGBA(EncodeFloatRGBA(1.0 - gl_FragCoord.z));",//current fragment depth
"float z_tex = DecodeFloatRGBA(texture2D(DX2RT, loc));",//depth in texture
//...do some stuff using z and z_tex

Но когда дело доходит до использования половинных текстур с плавающей точкой (ipad, ipod), этот метод больше не работает, и я лучше вообще не использую кодирование. Но в последнем случае у меня все еще есть некоторая потеря точности.

Кто-нибудь имеет подобную технику для половинных текстур с плавающей точкой?

Заранее спасибо.

1 ответ

Для некоторых устройств я отключил кодирование глубины, для других я использовал следующие биты кода:

 "vec4 EncodeFloatRGBA( float v ) {",
    "float remainder = v;",
    "vec4 res, r;",

    "res[0] = floor(remainder * 127.0) / 127.0;",
    "remainder -= res[0];",
    "res[1] = floor(remainder * 16383.0) / 16383.0;",
    "remainder -= res[1];",
    "res[2] = floor(remainder * 2097151.0) / 2097151.0;",

    "r[0] = clamp(floor((v) * 127.0),0.,127.);",
    "r[1] = clamp(floor((v - res[0]) * 16383.0),0.,127.);",
    "r[2] = clamp(floor((v - res[0] - res[1]) * 2097151.0),0.,127.);",

    "r.r = r[0] / 127.0;",
    "r.g = r[1] / 127.0;",
    "r.b = r[2] / 127.0;",
    "r.a = 1.;",
    "return r;",
 "}",


 "float DecodeFloatRGBA( vec4 rgba ) {",
     "return rgba.r + rgba.g/127. + rgba.b/16383.;",
 "}"
Другие вопросы по тегам