normal quantization
2023-03-27
opengl 에서 gpu로의 데이타 전송을 최소화 하는것이 성능상 이점이 있음.
특히 표면 노말의 경우는 x, y, z 3개의 float을 넘겨주는데.. 총 12바이트를 소요함.
이를 하나의 signed int (10.10.10.2) 로 표현하면 4바이트로 줄어듬.
비록 약간의 데이타 손실은 있지만 opengl에서 normal 로 표면을 표한할때는 차이가 거의 없음.
아래와 같이 약간의 손실을 감수하면서 opengl의 성능을 올릴때 사용하면 좋을것임.
노말말고 다른데 적용할부분이 어디가 있을까..
#include <stdio.h> #include <stdlib.h> #include <stdint.h> static inline uint8_t encode8_unorm(float x) { return uint8_t( int (x * 255.f + 0.5f) ); } static inline float decode8_unorm(uint8_t x) { return x / 255.f; } static inline uint8_t encode8_snorm(float x) { return uint8_t( int (x * 127.f + (x > 0 ? 0.5f : -0.5f)) ); } static inline float decode8_snorm(uint8_t x) { float f = x / 127.f; return f <= -1 ? -1.f : (f >= 1 ? 1.f : f); } static inline uint8_t encode8_snorm_gl2(float x) { return uint8_t( int (x * 127.5f + (x >= 0.f ? 0.f : -1.f)) ); } static inline float decode8_snorm_gl2(uint8_t x) { return (2*x + 1) / 255.f; } static inline uint16_t encode10_unorm(float x) { return uint16_t( int (x * 1023.f + 0.5f) ); } static inline float decode10_unorm(uint16_t x) { return x / 1023.f; } static inline uint16_t encode10_snorm(float x) { return encode10_unorm( ( x + 1 ) * 0.5f ); } static inline float decode10_snorm(uint16_t x) { return ( decode10_unorm( x ) * 2 ) - 1 ; } int main() { float x, y, z; x = 0.001; y = -0.002; z = 0.005; int16_t xx = encode10_snorm(x); int16_t yy = encode10_snorm(y); int16_t zz = encode10_snorm(z); uint32_t v = uint32_t( (2<<30) | (encode10_snorm(x)<<20) | (encode10_snorm(y)<<10) | (encode10_snorm(z)<<0)); float nx = decode10_snorm( ( v >> 20 ) & 0x3FF ); float ny = decode10_snorm( ( v >> 10 ) & 0x3FF ); float nz = decode10_snorm( ( v >> 0 ) & 0x3FF ); printf("%f %f %f\n", x, y, z); printf("%f %f %f\n", nx, ny, nz); printf("%d %d\n", sizeof(float)*3, sizeof(uint32_t)); }
0.001000 -0.002000 0.005000 0.000978 -0.002933 0.004888 12 4