If I had a Vertex Shader constant holding one float value, like:


Where: The first 3 numbers are actually red (255), next three are green (000), then the last three are blue (255).

... Could I separate those values and pass them to a vertex-variant register for the Fragment Shader? I'm thinking it would involve a combination of opcode operations such as: fractional, subtraction, and multiplications?

Perhaps there is a simpler way to pass all 3 color-channels in one register value and extract them back in separate channels (within a low-level language)?


Alright trying to clarify my question a bit. The flow of execution would be:

  • In Flash (in my case), pass the value 0xff00ff (Magenta) to a free Vertex Constant register of FLOAT_1 (so it only uses one field of that register).
  • In AGAL, the Vertex-Shader would decompile the field's value into 3 separate values (R, G, B, [A will be taken care of with another constant]).
  • Still in the Vertex-Shader, pass those 3 separate values to a Variant that will be used by the Fragment Shader (example: mov v0.rgb, vt0.rgb).
  • In the Fragment Shader, draw the interpolated color of the Variant.

Really, all I'm asking is happening in the Vertex-Shader. Then again, now that I know large numbers consisting of more than 7 digits won't work, a value of 0xFFFFFF won't fit! (16777215 = 8 digits = shit outta luck!).

Maybe it's just not worth the hassle. But if someone knows a work-around the limitation, that would be cool. (Heck... maybe it could be split into two fields instead?)

  • \$\begingroup\$ Floats are stored in a fundamentally different way than Integrals (int, long, byte...) and there is no reliable way to just move the bits from one to the other: cboard.cprogramming.com/c-programming/… You'll want to use math. \$\endgroup\$ – John McDonald Jan 19 '12 at 17:52
  • \$\begingroup\$ What are you trying to do that you need to do this? Perhaps there's a better way to achieve what you intend. \$\endgroup\$ – Nicol Bolas Jan 19 '12 at 18:17
  • 2
    \$\begingroup\$ @bigp: I recognize what you're asking to do. I'm asking why you're trying to do it. Do you have a specific issue where you've run out of "registers"? What are you using those registers for currently? Perhaps there's something else that can be done instead of this. \$\endgroup\$ – Nicol Bolas Jan 19 '12 at 18:39
  • 1
    \$\begingroup\$ You'd be better off encoding it as 16711935 (hex: FF00FF) than a float "255.000255". \$\endgroup\$ – Random832 Jan 19 '12 at 18:50
  • 2
    \$\begingroup\$ @bigp Why will numbers with more than 7 digits not work? Every register has 128 bits, that makes 32 bits per components. That allows for huge numbers, way beyond 7 digits. But quite honestly I think what you're trying to do is rather silly and not really of practical use. It will make your code harder to read/maintain etc. \$\endgroup\$ – bummzack Jan 19 '12 at 19:03

Usually shader languages come with special types that hold multiple values. For example GLSL has vec2, vec3, and vec4 types which hold 2, 3 or 4 float values... these types are ideal for something like RGB or RGBA values.

I don't know which shader language you use, but from your other question I'm guessing it's AGAL (Flash shader). There you use register and every register is 128bits wide. So it can hold 4 float values, which you can access like this:

register.r // first component (red)
register.g // second component (green)
register.b // third component (blue)
register.a // fourth component (alpha)

If that's not a possibility, you could probably just use an integer and bitwise operations to get the color values. Eg something like this

uint color = 0xff6633;
red = (color >> 16) & 0xff;
green = (color >> 8) & 0xff;
blue = color & 0xff;
  • \$\begingroup\$ Bingo on guessing I was using AGAL :) \$\endgroup\$ – bigp Jan 19 '12 at 18:10
  • \$\begingroup\$ Hmm, I understand how to split up an integer value in its color channels via the use of Bitwise Operations, but I'm not sure they are supported in AGAL. \$\endgroup\$ – bigp Jan 19 '12 at 18:12
  • \$\begingroup\$ @bigp it doesn't look like bitwise operations are supported in AGAL nor Pixel Bender. But maybe writing the shader in Pixel Bender would be simpler.. it's higher level and has a feature set and types comparable with other shader languages. \$\endgroup\$ – bummzack Jan 19 '12 at 18:52

No, you can't.

Floating-point numbers have a floating decimal point. So while you may write them as "255.000255", the float is stored exponentially: "2.55000255x102".

As you may know, 32-bit floats only store 6-7 decimal digits of precision. 2.55000255 has nine digits. So you can kiss the last 255 goodbye.

Now, you can store it as an integer. In DX10/OpenGL3.x-class hardware and better, you have sufficient bit manipulation capabilities to pack 3-4 floating-point values into a 32-bit unsigned integer, and then restore them in the fragment shader. However...

I'm going to assume that by "vertex-variant register for the Fragment Shader", you mean "pass a value from the vertex shader to the fragment shader, which will be interpolated across the primitive in question." Well, that's a problem. Because linearly interpolating that 32-bit unsigned integer does not give rise to a reasonable value. At least, it doesn't do a proper blend between colors.

So unless you want to pass an un-interpolated value (or pass 3 uninterpolated values and do the interpolation yourself per-fragment), this is not possible.

  • \$\begingroup\$ Ok but if the integer was then converted to an acceptable range (between 0.0 and 1.0) for each color channels in the register to be passed (interpolated as you mentioned) to the fragment shader, then it would be safe right? \$\endgroup\$ – bigp Jan 19 '12 at 18:09
  • \$\begingroup\$ @bigp: There is a difference between interpolating 3 values and interpolating one value that pretends to be three. You cannot interpolate 3 values if they're stored in one value; attempting to do so will yield garbage. Furthermore, this is all irrelevant, because you can just do what bummzack said and just use more than one value. Registers have fields, each of which is a float. Use those fields, just like everyone else. That's what they're for. \$\endgroup\$ – Nicol Bolas Jan 19 '12 at 18:15
  • \$\begingroup\$ What if you run out of registers / fields? And yeah I understand how three values piled up into one would create garbage interpolated results, but they wouldn't be at that point. I mean't to say one constant register field would have the 3-values-in-one, the vertex-shader would split it up, then it would pass the RGB value to the variant as @bummzack suggested. \$\endgroup\$ – bigp Jan 19 '12 at 18:27
  • \$\begingroup\$ @bigp: Then your question is incomplete and needs clarification. As I said, my answer assumes "vertex-variant register for the Fragment Shader" means "pass a value from the vertex shader to the fragment shader, which will be interpolated across the primitive in question." If that's not true, you need to fix your question to better describe what you're actually trying to do. \$\endgroup\$ – Nicol Bolas Jan 19 '12 at 18:37
  • \$\begingroup\$ Updated, hope it's a bit more clear. \$\endgroup\$ – bigp Jan 19 '12 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.