Starfield shader pipeline

Started by
10 comments, last by mmixLinus 7 years, 2 months ago

:) Hi folks, first post here :)

I am a seasoned C++ coder working on a "starfield visualizer" (called "Galaxy Navigator 3D" by the way) and I need some help understanding my alternatives regarding shaders.

An early version of the program is up on youtube, but frankly, starfields aren't best friends with video compression :D (Try viewing in full HD). Or you can download it here.

The navigator currently displays a "point list" of more than 2 million points (stars). Each point has an associated 3d position, and a "brightness" (aka Magnitude in astronomy). As you move around in space, the brightness of all stars is recalculated (in my vertex shader) so as you move closer to the stars they become brighter, all according to standard magnitude calculations used in astronomy.

I am using Ogre3D 2.1 as render library, with Direct3D11, HLSL (but I intend on making this cross-platform in due time..).

It currently uses rather simple Vertex, Pixel and Geometry shaders that I have written. It's all simple and "sequential", because I'm still pretty new to this :D

Goals:

1) Really close stars need to be "even brighter" than a point (pixel) at colour (1.0, 1.0, 1.0), which I suppose should be accomplished by issuing textured quads for the closest points.

2) Interactivity: The user should be able to select a point (with a mouse) for some interaction, and also interact by simply hovering with the mouse pointer.

Problem1: I already easily detect which stars are the closest (I change their colour for indication), but I don't know how to emit quads from my Geometry Shader. I understand a GS can emit to several streams, but that seems to require Shader Model 5. Preferably, I would like to solve this without putting too many requirements on hardware, so currently using SM4. Is this a bad choice?. Can I get my GS to emit most of the points to the rasterizer, and a handful to a buffer containing quads? Maybe this requires a second pass? or another GS instance. I don't how this works : (

Problem2: Because of the number of points (which is going to grow), and because of the "ease", I think mouse picking would be best done in the GPU. Currently, I send the mouse position to the vertex shader, so it can identify which stars are "close enough". This works. I change the colour of the points closest to the mouse pointer. How do I get these points back to the CPU? The actual information sent to the CPU isn't defined yet, but it might by a 32-bit integer ID of sorts. Or maybe some floats. Say a maximum of 100 points, but typically no more than 10. Some sort of staging buffer? I don't know how this works either. Does the method of choice depend much on shader model?

All help appreciated!

/mmixLinus;

Some of my 3D stuff http://mmix.me/

Advertisement

I should mention that I've googled a fair amount, read articles etc on msdn and others, but I think I need more concrete examples to understand how the bits fit together. Or pseudo examples :)

Some of my 3D stuff http://mmix.me/

Found this, within Gamedev, suggesting instancing to create my quads (not using the geometry shader). Interesting!

Some of my 3D stuff http://mmix.me/

Goals: 1) Really close stars need to be "even brighter" than a point (pixel) at colour (1.0, 1.0, 1.0), which I suppose should be accomplished by issuing textured quads for the closest points.

Problem1: I already easily detect which stars are the closest (I change their colour for indication), but I don't know how to emit quads from my Geometry Shader.

I don't really see how textured quads will help with what seems to be a lighting issue.

Reguardless, the solution is easy, learn how to program the geometry shader. Then you can emit quads. But i'm not sure that's the best solution. Sounds more like a HDR or bloom kind of thing to me. Have you tried over-saturating ?

How do I get these points back to the CPU?

Have to ask someone with more shader experience. I suppose render to target/texture might be an option. render to texture, then lock and read the texture to get the results. but i'm just guessing here.

did you try googling "returning values from a shader to CPU" ?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Reguardless, the solution is easy, learn how to program the geometry shader. Then you can emit quads.


And then promptly forget that as the geometry shader stage is terrible and should basically never be used.

Thanks Norm & phantom for your replies!

I did a little experiment with my geometry shader: Emitting one quad (non-textured) for each point that it receives. This sort of confirms my suspicion.. that it is too heavy for millions of points. It works but is too slow.

If you look at photos of star skies you can see that most stars are faint, and these stars could probably be represented by a simple one-pixel point all the way up to MaxWhite. But even brighter stars are "large" in the photos, ie., they cover an area (many pixels). This is largely due to interstellar gasses, and lens effects. To emulate this "behaviour" I was thinking of showing a quad for only the brightest stars. How do I accomplish this selective choice of "pass-thru or NULL geometry shader" for most stars, or rasterize a quad for "a handful" of stars?". (I don't want to do this on CPU side :) )

Some of my 3D stuff http://mmix.me/

Honestly, splitting things in to a couple of draw calls using the CPU is probably the best way to go about this; you pretty much need two types of drawing (points vs quads/triangles) and trying to make the choice on the GPU might not be optimal.

About the only other way to do it would be to run a compute shader over the 'star data' and have that build up point and triangle buffers and then use an indirect draw call to consume that buffer to render.

You'd still end up issuing at least 3 dispatch/draw calls (1 for compute, 2 for draw) but you wouldn't have to sort any data as they would be issued back to back.

i was thinking two passes as well, points and quads, but then you get into maintaining two sets of vb's and ib's as the camera moves, don't you?

when the camera moves, you sort your list of stars into two vb's: points, and quads. dynamic buffers? slow?

i don't see a way around telling the shader on a per star basis whats near vs far each time the camera changes. and you need a different number of verts...

i have an idea...

how about:

make a vb of quads for all the stars - IE each star gets a quad.

add the star's center to each quad's vertex.

in the vertex shader, transform the star's center along with each vertex

test the z depth of the transformed center

if z is far, move the vertex to the center. IE: out.pos = transformed_center;

this will collapse far stars to degenerate quads - IE: a point ! <g>

think it'll work...

then you can have different size quads with different textures using different light wavelengths for different types of objects in the sky. those textures can include haze and flare if desired.

one thing to watch for, if you draw a degenerate quad, it may do something like sample the upper left corner of a texture which is transparent, resulting in an invisible point.

to counter this, you can add a star color to each vertex, and pass transformed_center (or just z, or a boolean: is_point) to the pixel shader, which then uses z or the boolean to determine whether to do a texture lookup or just use the star_color.

but i'm new to HLSL, this is just based on general graphics programming theory.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

TBH I'd do it using a raytrace in the pixel shader. Ray/sphere intersections are fast. You could group the stars in a BVH with the volumes being sphere's. You could handle a massive number of stars if the BVH is static.

You could handle a massive number of stars if the BVH is static.

that's a good point. its a static scene. you can pre-process the h*ll out of it.

EDIT: But thinking about it further, how do you go from BVH to "i should draw a quad" or "i should draw a pixel" for some star? maybe i'm just tired.... been at it all day.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement