58 lines
2.0 KiB
Plaintext
58 lines
2.0 KiB
Plaintext
|
shader_type canvas_item;
|
||
|
render_mode blend_premul_alpha;
|
||
|
const float TEX_SIZE = 4096.0;
|
||
|
const float UV_QUANTIZE = TEX_SIZE;
|
||
|
// I feel like these magic numbers are a bit more intuitive in hex
|
||
|
const float x00FF = float(0x00FF); // 255.0
|
||
|
const float x0100 = float(0x0100); // 256.0
|
||
|
const float x7FFF = float(0x7FFF); // 32767.0
|
||
|
const float x8000 = float(0x8000); // 32768.0
|
||
|
const float xFF00 = float(0xFF00); // 65280.0
|
||
|
const float xFFFF = float(0xFFFF); // 65535.0
|
||
|
const float x10000 = float(0x10000); // 65536.0
|
||
|
|
||
|
const vec2 INT16_DOT_BE = vec2(xFF00, x00FF);
|
||
|
const vec2 INT16_DOT_LE = vec2(x00FF, xFF00);
|
||
|
uniform sampler2D tex : hint_normal;
|
||
|
|
||
|
float unpack_int16(vec2 int16) {
|
||
|
// Convert packed 2byte integer, sampled as two [0.0, 1.0] range floats,
|
||
|
// to the original int value [-32768, 32767] or [0, 65535] but in float32
|
||
|
float unsigned = dot(int16, INT16_DOT_LE);
|
||
|
return unsigned - (unsigned < x7FFF ? 0.0 : x10000);
|
||
|
}
|
||
|
|
||
|
float rescale_int16(float int16) {
|
||
|
// Rescale from [-32768, 32767] to [-1.0, 1.0)
|
||
|
return int16 / x8000;
|
||
|
}
|
||
|
|
||
|
vec2 pack_float_to_int16(float value) {
|
||
|
// Convert a float in range [-1.0, 1.0) to a signed 2byte integer [-32768, 32767] packed into two [0.0, 1.0] floats
|
||
|
float scaled = value * x8000;
|
||
|
float unsigned = scaled + (scaled < 0.0 ? x10000 : 0.0);
|
||
|
float unsigned_div_256 = unsigned / x0100;
|
||
|
float MSB = trunc(unsigned_div_256) / x00FF;
|
||
|
float LSB = fract(unsigned_div_256) * x0100 / x00FF;
|
||
|
return vec2(LSB, MSB);
|
||
|
}
|
||
|
|
||
|
vec4 test_writeback(vec2 uv) {
|
||
|
// Test importing and exporting the samples,
|
||
|
// and exporting a value derived from the UV
|
||
|
vec4 output;
|
||
|
float sample_1 = rescale_int16(unpack_int16(texture(tex, uv).xw));
|
||
|
float sample_2 = rescale_int16(dot(trunc(uv*TEX_SIZE), vec2(1.0, TEX_SIZE)));
|
||
|
output.xy = pack_float_to_int16(sample_1);
|
||
|
output.zw = pack_float_to_int16(sample_2);
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
void fragment() {
|
||
|
// GLES2
|
||
|
vec2 uv = vec2(UV.x, 1.0-UV.y);
|
||
|
uv = (trunc(uv*UV_QUANTIZE)+0.5)/UV_QUANTIZE;
|
||
|
|
||
|
COLOR.xyzw = test_writeback(uv);
|
||
|
}
|