12
\$\begingroup\$

Both graphics APIs (OpenGL and DirectX) devise a well defined pipeline in which several stages are programmable. These programmable stages require to take a fixed minimum amount of data and are supposed to do a well defined range of operations on it, and output some defined minimum output, so that data can be passed on to the next stage correctly. It seems as if these pipelines are designed to work with only a limited amount of types of geometric data, which in the case of both D3D and OGL are vertex data and texture co-ordinates.

But, if given a case when the application I plan to make doesn't use vertices ( or even voxels ) to represent its geometric data and does not exactly do transformations or projections or rasterisation or interpolation or anything like that, such limitations of the APIs or the pipeline make things difficult.

So, is there a way in which we can change graphics pipeline in a way so that the functionality of what each stage does to the data and the type of data that is outputted in each stage is changed to my advantage? If not, then is there a way by which I can use the 'raw' API functions to construct my own pipeline? If not, then please mention why it isn't possible.

EDIT : My Application uses density functions to represent geometry. The function has a value at each point in space. I divide the frustum of the camera into a 3d grid, each block can be projected as a pixel. On each block, I integrate the density function and check if its value is more than a required value. If yes, then its is assumed that something exists in that block and that pixel corresponding to that block is rendered. so, now in my renderer, I want to pass the function ( which i represent with a string ) to the graphics hardware instead of vertex data in vertex buffers. this also implies that the vertex shader won't have vertices to transform into homogeniouse clip space and the fragment shader doesn't get pixel info. instead, now most of the looking up and evaluation happens per pixel.

\$\endgroup\$
  • \$\begingroup\$ Is 'function density function' a tautology? \$\endgroup\$ – Pharap Aug 3 '14 at 4:17
  • \$\begingroup\$ @Pharap, that was a typo. its simply "desity functon" which represents the presence of "matter" in the space. \$\endgroup\$ – The Light Spark Aug 3 '14 at 6:40
  • 2
    \$\begingroup\$ It sounds like you just want to build an isosurface, which is a well studied problem. Have you seen http.developer.nvidia.com/GPUGems3/gpugems3_ch07.html or searched on Metaballs, point cloud visualization, isosurface extraction, or volume rendering? Also, what kind of performance do you require, that will make a huge difference on the choice of technique you search for when combined with the complexity of your calculations. I think that you'll also find that per-pixel will cause shimmering when the camera moves, and sub-pixel will be required. \$\endgroup\$ – Patrick Hughes Aug 3 '14 at 19:19
18
\$\begingroup\$

You can absolutely use the GPU to render volumetric data.

Since you want to evaluate a set of functions per pixel on the screen, a simple approach is to render a full-screen triangle. This is just a single triangle that covers the entire screen (actually, it covers more than the screen, since the screen isn't triangular, but the parts off-screen are discarded by the GPU). You can then use the pixel shader (which receives the screen coordinates of the pixel it's shading) to construct a ray through your volume, evaluate functions, whatever you need to do.

(In contrast to the other answers, I don't recommend a compute shader because it sounds like you want to do per-pixel operations, and a full-screen triangle + pixel shader is generally more efficient for that than a compute shader—although compute shaders will certainly also work.)

The full-screen triangle method is very common in real-time graphics for postprocessing operations, so you can probably find all the information you need on it with a bit of googling.

BTW, it may interest you to read Rendering Worlds with Two Triangles by Iñigo Quílez, a talk which describes how to render 3D scenes composed using mathematical functions (specifically, distance fields) using the full-screen pixel shader technique.

\$\endgroup\$
  • \$\begingroup\$ So does the pixel shader take in arbitrary inputs (like strings or other types of user defined objects) so i can pass in my functions? \$\endgroup\$ – The Light Spark Aug 3 '14 at 15:24
  • \$\begingroup\$ I doubt that you would want to try running a parser and/or language on arbitrary function strings on GPU, that would be awkward since GPUs are not really general purpose. Most likely you would want to create the shader itself dynamically in your main code, then let the graphics system compile and run the resulting shader. \$\endgroup\$ – Patrick Hughes Aug 3 '14 at 17:59
  • \$\begingroup\$ @TheLightSpark Right, you wouldn't pass strings to the shader (shading languages don't even have a string type), you'd want to generate and compile shader code for your desired functions. That can be done at runtime if necessary. \$\endgroup\$ – Nathan Reed Aug 3 '14 at 19:09
  • \$\begingroup\$ Started reading your answer, I imagined a triangle shaped monitor ;) Does it have an advantage to use only a single triangle instead of two which cover the screen without discarding pixels? \$\endgroup\$ – danijar Aug 22 '14 at 19:16
  • \$\begingroup\$ @danijar Yes, it has a slight advantage over using a quad because some pixels along the diagonal will be shaded twice if you use a full-screen quad. On the other hand, discarding off-screen pixels is free since the rasterizer will not generate those pixels to begin with. \$\endgroup\$ – Nathan Reed Aug 23 '14 at 0:50
6
\$\begingroup\$

Ray tracing and other techniques are commonly done with Compute Shaders, which Direct3D has supported since the release of D3D11 and OpenGL has supported since 4.3 (and longer via the use of OpenCL and some contortions).

\$\endgroup\$
5
\$\begingroup\$

It sounds very much like you want to use a GPU compute shader, or utilize a "Shader Storage Buffer" object to help augment the pipeline to fit your needs. Mathematicians, scientists, and other people who look to the GPU for computation on things that don't exactly translate into standard graphics use this kind of thing.

Although the contemporary graphics pipeline is very flexible, developers still tend to stumble on some restrictions. The compute shaders feature, however, makes life easier for us to not think about pipeline stages as we are used to thinking about vertex and fragment. We are no longer restricted by the inputs and outputs of certain pipeline stages. The Shader Storage Buffer Object (SSBO) feature for instance has been introduced along with compute shaders and that gives additional possibilities for exchanging data between pipeline stages, as well as being flexible input and output for compute shaders.

http://community.arm.com/groups/arm-mali-graphics/blog/2014/04/17/get-started-with-compute-shaders

If this does not point you in the right direction, would you mind expanding the concept of yours that doesn't fit the vertex/fragment paradigm?

\$\endgroup\$
  • \$\begingroup\$ I edited my answer to include what i am doing. compute shader seem to be the answers, but just tell me if there is something else that i may do. \$\endgroup\$ – The Light Spark Aug 3 '14 at 3:09

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.