Skip to main content
gamedev.net
🔒 Locked

render 1 pixel?

Started by scope 13 replies 3.1k views
Original Post
scope
scope
Hi,

I want to render only one pixel of the screen (or whatever is the smallest render target size), the one below the mouse cursor (for picking).

Unfortunately i'm not sure how to set this up correctly.

Setting up the render target is no problem ;-) How about view matrix, view port etc.?

Anyone know off the top of the head?

edit: maybe i could abuse one of my fullscreen render targets for this, but how can i transfer only single pixel from the render target to the cpu?
SiS-Shadowman
SiS-Shadowman
You could create a quad in screen space coordinates and make it the size of one pixel. Then render it without applying the view-projection matrix to it.
scope
scope
Hi SiS-Shadowman, thanks for the reply.

I'm not sure if i got that right. The quad would have to be textured with the scene buffer (position, uv's or whatever i want to pick)?

Another method came to my mind:

- use stretch rect to transfer the pixel to small buffer.

But that would require to render to a fullscreen target as well.
Erik Rufelt
Erik Rufelt
What API/language are you using? D3D9/10/11?
Will this be used during game-play so that performance is critical, or is it for an editor?
And what do you wish to accomplish with this?
Do you only want the color of the pixel under the cursor?
SiS-Shadowman
SiS-Shadowman
That depends. If you want to render one pixel in any given color (and not affect the rest of the screen) then create a quad with vertex coordinates that only covers one pixel of your screen.

Screen coordinates are within [-1, 1]. In order to cover one pixel, you will need to figure out how much that is in screen coordinates:
// Mouse position in pixel coordinatesint pos_x;int pos_y;// The 2 comes from the fact that screen space is 2 units wide and highfloat width = 2 / screen_width_in_pixels;float height = 2 / screen_height_in_pixels;// Those are the coordinates for your quadVector3 topLeft(pos_x * width, pos_y * height, 0);Vector3 topRight((pos_x + 1) * width, pos_y * height, 0);Vector3 botLeft(pos_x * width, (pos_y + 1) * height, 0);Vector3 botRight((pos_x + 1) * width, (pos_y + 1) * height, 0);


If you're using DirectX9 you must compensate for half a pixel.
scope
scope
The API is DX9.

Yes, it's used during editing only.

I want to run the scene through a pixel shader and read back the color under the mouse cursor.

It's used for mesh picking but also texture painting.

It's not really performance critical, but consumes an entire fullscreen buffer (which is created on mouse down and released on mouse up). I guess i could re-use my normal buffer or something but that feels kind of wrong since i might need it at a later point. I was looking for some lightweight solution.
Evil Steve
Evil Steve
Sounds like a job for the Scissor Test followed by GetRenderTargetData().

EDIT: Actually, that might not be so great, since the pixel shader will be run for all the culled pixels too...
scope
scope
Quote:
Original post by SiS-Shadowman
That depends. If you want to render one pixel in any given color (and not affect the rest of the screen) then create a quad with vertex coordinates that only covers one pixel of your screen.



Oh, i see, we have a little Mißverständnis here ;-)

I actually want to read back a pixel from the screen to the cpu in opposite of drawing one to the screen. The pixel i want to read back would be the result from a pixel shader which is executed on the geometry.
Erik Rufelt
Erik Rufelt
To read back the color to CPU you don't need a pixel-shader. You can create your device with the D3DPRESENTFLAG_LOCKABLE_BACKBUFFER flag, then use the device-method GetBackBuffer and LockRect on the back-buffer. It allows you to specify a rectangle to lock, which you set to 1x1 pixels on the cursor-position, and you get a pointer to exactly that pixel. Just store the value pointed to by that address, and then call UnlockRect.
I hope I didn't misunderstand what you want to do. If you need the color under the cursor in the pixel-shader, you could either use the render-target as a texture as you discussed earlier, or first read back the color and then set it as a shader-constant for the pixel-shader.
SiS-Shadowman
SiS-Shadowman
Quote:
Original post by scope
Quote:
Original post by SiS-Shadowman
That depends. If you want to render one pixel in any given color (and not affect the rest of the screen) then create a quad with vertex coordinates that only covers one pixel of your screen.



Oh, i see, we have a little Mißverständnis here ;-)

I actually want to read back a pixel from the screen to the cpu in opposite of drawing one to the screen. The pixel i want to read back would be the result from a pixel shader which is executed on the geometry.


Yeah, we did :)
If it's not that performance critical, how about setting a texture as your primary render target. You could then lock the texture and read back individual values. But this might be slow, depending on the texture size.
scope
scope
Quote:
Original post by Evil Steve
EDIT: Actually, that might not be so great, since the pixel shader will be run for all the culled pixels too...


This is no problem since i only have to re-render the geometry when the camera changes (which is not too often during painting and picking). But i was wondering how i can use a 1x1 render target (or whatever is possible) and draw only that specific area under the cursor to it.
scope
scope
post edited away by accident, browser tab chaos.

[Edited by - scope on September 23, 2010 11:13:37 AM]
Erik Rufelt
Erik Rufelt
Quote:
Original post by scope
Quote:
Original post by Erik Rufelt
To read back the color to CPU you don't need a pixel-shader. You can create your device with the D3DPRESENTFLAG_LOCKABLE_BACKBUFFER flag, then use the device-method GetBackBuffer and LockRect on the back-buffer.


This would be a good solution for a pure editor but my game thing is editable and paintable during runtime.


I don't think you will have any performance problems from this whatsoever, if you're rendering everything every frame anyway. It's probably faster than trying to change render-targets etc.
If you only need to re-render when the camera changes, so you want to keep the whole render-target for picking unchanged in memory in between, while still rendering to the back-buffer, then you can still use the same method, but lock that render-target instead of the back-buffer.
scope
scope
Woops, seems like i mixed up my browser tabs on the previous post.

Ok seems like reusing another buffer is the way to go. I just wanted to avoid this for coordination and encapsulation reasons etc.

Thanks for your insights :)

If anyone has another cool idea, i'm eager to hear it.
Burnt_Fyr
Burnt_Fyr
Quote:
Original post by SiS-Shadowman
That depends. If you want to render one pixel in any given color (and not affect the rest of the screen) then create a quad with vertex coordinates that only covers one pixel of your screen.

Screen coordinates are within [-1, 1]. In order to cover one pixel, you will need to figure out how much that is in screen coordinates:
*** Source Snippet Removed ***

If you're using DirectX9 you must compensate for half a pixel.


SCREEN space is by definition mapped from [0, width][0, height]. NDC, or normalized device coordinates are mapped from [-1,1]...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.