1
\$\begingroup\$

Is it possible to output a pixel processed by my pixel shader to a different position?

For example if SV_POSITION of the pixel is 14,26, can I change it to 14,27?

I see there are only two possible output semantics, COLOR and DEPTH, so I am guessing the answer is not directly.

But are there alternative techniques, workarounds for achieving this?

\$\endgroup\$
1
  • \$\begingroup\$ Workarounds are often easier to find if we know the end goal this is serving. If you're still looking for ideas here, please consider adding more detail about why you want to displace pixels, using what kind of rule, and what ultimate effect it's serving. \$\endgroup\$
    – DMGregory
    Sep 6, 2017 at 12:26

4 Answers 4

1
\$\begingroup\$

In DirectX 11, you can write to unordered access views from pixel shaders. You can create unordered access views for textures.

But this way you have to perform some sort of synchronization to ensure that no more than one thread is attempting to write to the same location at a given time. The easiest way would be to use a RasterizerOrderedTexture2D in the shader which makes this ensurance for you transparently. But this feature may not be supported by some of the older GPU drivers.

\$\endgroup\$
0
\$\begingroup\$

If you use a buffer with a color depth of 16 or more bits per channel, then you can output the color such as the first 8 bits of each channel contain the actual RGB color, and you can use the rest of the bits to store the intended position of the pixel.

For example with 16 bits per channel, you have 4*8 bits to use to store the x and y coordinates, which allows you to store positions up to 65536 on each axis.

The red channel would look something like this:

Position  Color
10011101|11011101

Then you can run a postprocesser on the texture and move everything to it's intended location.

This has the obvious drawback, that some elements with different intended positions can't occupy the same original position.

\$\endgroup\$
5
  • \$\begingroup\$ Good idea, unfortunately I am using D2D which seems to limit to float4 channels. I could sacrifice color dept for position info nontheless I guess.. \$\endgroup\$
    – markmnl
    Jun 19, 2017 at 3:46
  • \$\begingroup\$ Hmmm... how would this work? The "intended position of the pixel" - how would you then (in a post process) move a pixel to it's intended location? \$\endgroup\$
    – Stormwind
    Jun 19, 2017 at 8:01
  • \$\begingroup\$ @markmnl you can get around both limitations by using multiple textures though \$\endgroup\$
    – Bálint
    Jun 19, 2017 at 10:15
  • \$\begingroup\$ @Stormwind You'd have to either sample the area the pixels for a specific coordinate could be in (if the pixels don't move too much) or by doing it on the CPU (it's better at managin multiple pixels at once) by creatong a texture. \$\endgroup\$
    – Bálint
    Jun 19, 2017 at 10:20
  • \$\begingroup\$ Such a seeking op could ofc work offline... not to recommend for runtime - very loopy. Irregularly/random-accessedly setting pixels from the CPU is also painfully slow. But it remains a secret what the Q writer wants to do... :-) \$\endgroup\$
    – Stormwind
    Jun 19, 2017 at 14:44
0
\$\begingroup\$

(My most sincere apologies if i am wrong in my guess below, the intention is of course only to clarify)

I think you may have misunderstood how a shader works? My guess is that you think in the wrong direction.

You do NOT "re-position" a pixel, into a different location on the target (may it be a surface or the monitor) while you process it. You (kind of) do NOT process in a forward direction in a shader. You can NOT "place a pixel" just anywhere you like.

Instead, the system (hardware + driver + 3Dware) determines which pixels are visible and thus need to be painted. You can indeed affect this in advance, as a whole, eg. by painting only a part of the screen. But once the draw command is executed, the system concludes which pixels are involved and need to be painted, and this is non-negotiable and automatic.

Instead, your job is to provide content for that (and the other) pixels. The system kind of asks you (= the shader, your code) to "give something". This is where the re-positioning happens, as you can of course "give" anything you like. You can fetch it from anywhere, calculate it with code, or say clip() in which case you "give" nothing and the target pixel is left unpainted.

Example: You have a 8192x8192 px map that you what to paint onto a full 1920x1080 screen, with a 1:1px scale, by using a shader. Apparently, only part of the huge map fits the screen.

You do NOT first focus on a/any pixel, say for example (100,100), in the big 8192x8192 map and decide that you "throw it" into pixel (500,500) on screen. And you can not then focus on pixel (101,101) and decide that you "throw it" into say pixel (211,972) on screen.

Instead, the system will walk through all screen (target) pixels in parallel (in an order that you do not know in advance and will never know). All pixels are independent and unaware of each other - each pixel thinks it is the only pixel in the world but all pixels will be taken care of. The system WILL invoke your shader for each pixel.

At some point, the system will process screen pixel (500,500) - this is guaranteed and happens without your own active effort. Your job is now to provide content for this pixel. So in the shader, you say "yes, lets grab pixel (100,100) from the big source map this time". Equally well you could say "yes, lets grab pixel (99,100) from the big source map this time". And next frame (98, 100), then (97,100) etc., in fact that way producing a scrolling output for the user who views the result.

In the end, you will achieve exactly what you are considering with your question. You just need to think from the final result backwards into the source pixel - and not think from the source pixel forwards into the final result pixel.

\$\endgroup\$
3
  • \$\begingroup\$ Yeah i know I am trying to use a pixel shader for something its not typically used for, im hacking it for another purpose :) \$\endgroup\$
    – markmnl
    Jun 19, 2017 at 3:40
  • 1
    \$\begingroup\$ Thanks anyway, I am learning and your answer helped me clarify some things.. \$\endgroup\$
    – markmnl
    Jun 19, 2017 at 3:47
  • 1
    \$\begingroup\$ "Using for something its not typically used for" - excellent, that's creativity! And if you by any chance are using it for math calculation or logical steering, you'll get more help with a more specific question. \$\endgroup\$
    – Stormwind
    Jun 19, 2017 at 8:05
0
\$\begingroup\$

You're thinking about it in the intuitive natural way, which unfortunately isn't actually the best way. It's much easier if you think about it a little backwards. Don't move the output of a pixel, move its input instead. Essentially, moving the vector that says where your pixel is is equivalent to moving the pixel itself.

To illustrate what I mean, your SV_POSITION says (14, 26), but you want it to render at (14, 27) right? Rather than rendering it at (14, 26) and then moving the pixel, just take your SV_POSITION and subtract one from it, so that (14, 27) thinks it's actually (14, 26) and renders everything at (14, 26) right where you need it to be.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .