Discussion:
Analysing images using HLSL
(too old to reply)
Pomnico
2008-06-28 08:36:00 UTC
Permalink
Hi,

Recently while implementing my GFX engine (D3D9, PS 3.0, VS 3.0) I came to
the point where I'm stuck and can not figure out what to do.

I wanted to perform picking 2D / 3D objects by 2D space coordinates using
the GPU (both picking by point or by a rectangular area).

At first my idea was to render each element that has not been discarded by
simple CPU calculations to the original render target (the one that is tested
for picking / hit) with clipping rectangle set to pint or input area of
picking.

The pixel shader used to this operation was to check if output pixel color's
alpha value is non-zero (to discard situations where someone is hitting a
point on a transparent area of 2D surface - to handle properly tests for 2D
buttons with irregular shapes for example) and write some information to
parameters (so they can be retrieved later) about:
- if hit has succeeded
- distance from eye-point (for 3D tests)
- position of hit in object space)

Next, after rendering is performed, I wanted to read this data and based on
it decide if further search has to be done, or not, but that doesn't matter
right now.

I though that this is ideal solution - pixel shader will not be run for
elements outside the clip plane (and even if I could clamp them inside the
pixel shader), I could use the same pixel shader for testing single point
picking and area picking.

Unfortunately, I've discovered, that there is no way to retrieve data
calculated inside the pixel shader other than by target render target.

Is there any way to perform above operations inside the GPU, or should I
give up this idea and use CPU only. I would like to use the GPU however, as
even if counting hit by single point can be easy performed inside the CPU,
performing this for whole area will be devastating for performance.

Maybe there is a way to perform such operation and write result to some
buffer treated as render target? I'd really apreciate any comment on this,
even saying that it is not possible.
Pomnico
2008-06-28 09:08:01 UTC
Permalink
Actually I was thinking about modifying this scenario to two parts:
- rendering objects (if 3D objects are used)
- analyzing the resulting image

Is it possible to gather some statistic informations using the pixel shader,
so the input is some area of the image / texture, and the output would be
necessary informations like maximum alpha value?
Wyck
2008-07-31 14:43:09 UTC
Permalink
Post by Pomnico
- rendering objects (if 3D objects are used)
- analyzing the resulting image
Is it possible to gather some statistic informations using the pixel shader,
so the input is some area of the image / texture, and the output would be
necessary informations like maximum alpha value?
The most flexible tool is probably the occlusion query. You render a
polygon with a shader that either culls the pixel or not depending on a
condition. The data returned from the query is the number of pixels that
were not culled. By using your rendered image as a texture and re-rendering
it to another render target, you can count pixels that met your condition,
entirely on the GPU, with only the count being read back to the system. You
can even disable buffer writes when rendering because the culling mechanism
happens before the render target buffer write. But you need enough pixels in
your target that the rasterizer will consider every pixel of your source, and
you need a depth/stencil buffer attached to your render target too for some
strange reason...occlusion queries don't seem to work without them.

Look at IDirect3DDevice9::CreateQuery, D3DQUERYTYPE_OCCLUSION,
IDirect3DQuery9.

But getting the maximum alpha value based on a count of pixels that passed a
query, while keeping the number of pixels low (keeping the performance high)
will be a test of your mathematical ingenuity!

Getting back to your hit testing issue, depending on the geometry of your
scene, you may want to consider a different approach to hit-testing.

If you can quickly render all your polygons with a different shader then
consider rendering your scene using a shader that write the "id" of the
object as its unique colour, and use a z-buffer. Read-back the one pixel of
the hit test (or use a query to test it) and the colour will be the id of the
object.

Another tried and true technique is to do a ray-cast and compute which
object/polygon was hit on the CPU. You can optimize your scene's geometry to
make the ray-cast computation very fast. (use bounding boxes, etc.) But the
right hit-testing algorithm is VERY dependent on the complexity of your
scene's geometry.

- Wyck

Loading...