Packing float into sampler2D

edited February 2017 in GLSL / Shaders

Hi everybody,

Was hoping anybody here could help me with this... For a project I want to pack data into a texture and use it in a fragment shader because it can potentially be a lot of data. Thing is... I need the data as floats in my shader code but I can't seem to get it right.

I wrote a little test case below which illustrates my problem. The goal of this sketch is to make the left half of the screen white and the right half of the screen black. That would be the case if the data passed via the texture would be interpreted correctly.

Tried a lot of methods to pack/unpack data, but I'm thinking I got it wrong on the processing side of things. I also noticed that when using println(pixels[0]), the value that gets printed is NOT the same as Float.floatToIntBits gives... so something get's changed.

Anyway, if anybody knows the correct way of passing float values to a shader via a texture and unpacking them from vec4 to float I would be really grateful. Thanks!

Processing sketch:

PShader shader;
PImage sampler;

void setup() {
  size(1280, 720, P2D);

  shader = loadShader("shader.glsl"); 
  shader.set("resolution",1280,720);

  // no texture interpolation
  ((PGraphicsOpenGL)g).textureSampling(3);

  sampler = createImage(2,1,ARGB);   
  sampler.loadPixels();
  sampler.pixels[0]=Float.floatToIntBits(5); // left half of screen < 1
  sampler.pixels[1]=Float.floatToIntBits(15); // right half of screen > 10
  sampler.updatePixels();

  shader.set("sampler",sampler);
}

void draw() {
  filter(shader);
}

Shader code:

                uniform sampler2D sampler;
                uniform vec2 resolution;

                const vec4 bitEnc = vec4(1.,255.,65025.,16581375.);
                const vec4 bitDec = 1./bitEnc;

                float DecodeFloatRGBA (vec4 v) {
                    return dot(v, bitDec);
                }

                void main(){
                  vec4 test = texture2D(sampler,gl_FragCoord.xy/resolution);
                  float testfloat = DecodeFloatRGBA(test);

                  if (testfloat<10){
                    gl_FragColor=vec4(0,0,0,1);
                  }
                  else{
                    gl_FragColor=vec4(1,1,1,1);
                  }
                }

Answers

  • that decoder is decoding by multiplying each of the 4 bytes by powers of 256. this suggests, to me, a fixed point floating point number

    but the encoder isn't encoding like that, it's a lot more complex

    https://docs.oracle.com/javase/7/docs/api/java/lang/Float.html#floatToIntBits(float)

    where did you get that decode method from?

  • What is a fixed point floating point number?

    Have to admit I took the decoding method from the web while searching on the subject. Tried a bunch of other ways too... I'm suspecting that my way of packing a float into pixels[] isn't correct indeed...

    Very little to be found on the subject, especially on the java/processing side of things... Thanks

  • Fixed point: you have, say, a 32 bit number and decide that the first 16 bits are the integer part and the second 16 bits are the fractional part, as if the 'decimal point' were in the middle.

    Decimal example, as that's clearer: 4 digits with the point fixed in the middle gets you from 00.00 to 99.99 in steps of 00.01

    I found one thread that used something like your code with the FP input defined to be between 0 and 1 (exclusive), so the point would be before the first bit, .0000 to .9999 in my example, this matches the code (I think)

  • @bradcoleman
    Have you tried passing your float's as an array rather than a texture?
    It might not be the answer you wan't though

  • Another fact is that the data type "vec4" is 4 floats, not a single one.

    The integer used in a single pixel in Processing has a byte for each color channel (including alpha). So the first value of the vec4 is the normalised version of the first byte, and so on. So the value of

    You say that -

    I also noticed that when using println(pixels[0]), the value that gets printed is NOT the same as Float.floatToIntBits gives... so something get's changed.

    That doesn't make sense. How could that happen?

  • I'm assuming that you mean to println(sampler.pixels[0]).

Sign In or Register to comment.