Now a fully interactive volumetric sand storm, probably somewhere on Mars.
This marks an intermediate milestone following months of research into volume rendering. It uses finite differences solver for a fluid dynamics equation, some additional research into graphics pipeline on a Mac and iOS.
Note the shadows, they depend on volume density, and also note the unbounded nature of volumes. Other methods would produce visible banding artifacts.
Showing posts with label Volumetric. Show all posts
Showing posts with label Volumetric. Show all posts
Sunday, June 25, 2017
Martian sandstorm
Labels:
3D engine,
C++,
CFD,
Mac,
OpenGL,
Simulation,
Volumetric
Saturday, June 17, 2017
Unexpected volumetric clouds
I was playing with code that I am testing to produce fluid dynamic effects, and I came across a weird cloud generating setup.
The advection part is failing at some point here and causes gas density to freeze in some regions of the map. It remains static and appears as a cloud, and I think this can be further improved to produce realistic looking real cloud. What's missing is a better phase function, and shading based on anisotropic scattering of different wavelenths.
The advection part is failing at some point here and causes gas density to freeze in some regions of the map. It remains static and appears as a cloud, and I think this can be further improved to produce realistic looking real cloud. What's missing is a better phase function, and shading based on anisotropic scattering of different wavelenths.
Labels:
3D engine,
C++,
CFD,
Mac,
OpenGL,
Simulation,
Volumetric
Monday, May 29, 2017
Fun with self-shadowing volumetrics
As a preparation to a full-fledged interactive volume rendering, here is the first functional volumetric composition. It uses a few techniques to achieve a self-shadowing appearance, as you would expect from a real-life volume of transparent matter.
Labels:
3D engine,
C++,
CFD,
Mac,
OpenGL,
Simulation,
Volumetric
Wednesday, May 24, 2017
Volumetric hints.
A few volume rendering hints.
1. Cannot discard writing into render-targets selectively in an MRT frame-buffer. This arises, for example, when two targets are used to store two custom denormalized depth buffers. A frame-buffer has a depth attachment as well, but it is used in a regular sense of a depth buffer.
2. Volume rendering can use analytic volume buffer or a set of depth textures. To limit volume to a custom 3D shape requires preliminary step to render that shape into two depth attachments, one with inverted normals and inverted depth test:
3. In a fragment shader calculate the distance to a rasterized point. Do it in fragment instead of in a vertex, hoping for speedup due to hardware interpolation. If two vertices spread out evenly in a view space, their depths will be equal and much bigger than the distance to a front clipping plane. This results in artifacts when moving towards a volume and crossing it.
4. A depth buffer attachment can now be shared between with other frame-buffers. It works for simple convex shapes as volumes that can be rendered from inside and outside. The real work is to be done elsewhere to modulate this shape with other detail, i.e. noise.
1. Cannot discard writing into render-targets selectively in an MRT frame-buffer. This arises, for example, when two targets are used to store two custom denormalized depth buffers. A frame-buffer has a depth attachment as well, but it is used in a regular sense of a depth buffer.
2. Volume rendering can use analytic volume buffer or a set of depth textures. To limit volume to a custom 3D shape requires preliminary step to render that shape into two depth attachments, one with inverted normals and inverted depth test:
// Enable depth test, inverted, front to back. glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GREATER); // Render only back faces. glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); // Clear the buffers. // Note that the most distant shape will overwrite all others. glClearDepth(0.0); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //... Render the shape of the volume, i.e. a cloud. // Enable depth test, back to front. glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // Render only front faces. glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // Clear the buffers. glClearDepth(1.0); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //... Render the same shape of the volume.
3. In a fragment shader calculate the distance to a rasterized point. Do it in fragment instead of in a vertex, hoping for speedup due to hardware interpolation. If two vertices spread out evenly in a view space, their depths will be equal and much bigger than the distance to a front clipping plane. This results in artifacts when moving towards a volume and crossing it.
4. A depth buffer attachment can now be shared between with other frame-buffers. It works for simple convex shapes as volumes that can be rendered from inside and outside. The real work is to be done elsewhere to modulate this shape with other detail, i.e. noise.
Labels:
3D engine,
C++,
CFD,
Mac,
OpenGL,
Simulation,
Volumetric
Subscribe to:
Posts (Atom)



