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.
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
Saturday, May 13, 2017
Volumetric rendering with custom volume shapes
It took me a week to figure out a problem with a vertex shader not able to interpolate a single float output.
I started with a multi-pass stage that produced a volume from a shape, then fed that volume to a volumetric pass and observed unexplainable artefacts. When flying through a scene and entering a volume the buffer that was clipped by a view frustum's near plane would mangle a default buffer value (set by glClear). Attempts to fix that by playing with glEnable(GL_DEPTH_CLAMP), glDepthRange(-1.0, 1.0) etc did not help.
What did work was switching from a float output to a whole vec3, and calculating depth in a fragment shader. Inefficient, and annoying.
Friday, April 14, 2017
Real-time atmospheric effects
This demonstrates a few atmospheric effects that I've added to a custom engine. It is real-time, using stages in shader pipeline, and very customizable (fog, lighting, composition etc).
In addition, the demo is showing Fourier transform to simulate ocean waves.
More to follow.
In addition, the demo is showing Fourier transform to simulate ocean waves.
More to follow.
Labels:
3D engine,
C++,
Crossplatform,
FFT,
OpenGL,
Simulation
Subscribe to:
Posts (Atom)