Merge pull request #3889 from akohlmey/image-anti-alias

Implement anti-aliasing for dump image (and dump movie)
This commit is contained in:
Axel Kohlmeyer
2023-08-18 15:52:01 -04:00
committed by GitHub
9 changed files with 119 additions and 26 deletions

BIN
doc/src/JPG/image.both.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
doc/src/JPG/image.fsaa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
doc/src/JPG/image.ssao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -24,7 +24,7 @@ Syntax
* color = atom attribute that determines color of each atom
* diameter = atom attribute that determines size of each atom
* zero or more keyword/value pairs may be appended
* keyword = *atom* or *adiam* or *bond* or *grid* or *line* or *tri* or *body* or *fix* or *size* or *view* or *center* or *up* or *zoom* or *box* or *axes* or *subbox* or *shiny* or *ssao*
* keyword = *atom* or *adiam* or *bond* or *grid* or *line* or *tri* or *body* or *fix* or *size* or *view* or *center* or *up* or *zoom* or *box* or *axes* or *subbox* or *shiny* or *fsaa* or *ssao*
.. parsed-literal::
@ -85,6 +85,8 @@ Syntax
diam = diameter of subdomain lines as fraction of shortest box length
*shiny* value = sfactor = shinyness of spheres and cylinders
sfactor = shinyness of spheres and cylinders from 0.0 to 1.0
*fsaa* arg = yes/no
yes/no = do or do not apply anti-aliasing
*ssao* value = shading seed dfactor = SSAO depth shading
shading = *yes* or *no* = turn depth shading on/off
seed = random # seed (positive integer)
@ -227,7 +229,7 @@ details have to be looked up in the `FFmpeg documentation
described below.
To write out JPEG and PNG format files, you must build LAMMPS with
support for the corresponding JPEG or PNG library. To convert images
support for the corresponding JPEG or PNG library. To convert images
into movies, LAMMPS has to be compiled with the -DLAMMPS_FFMPEG
flag. See the :doc:`Build settings <Build_settings>` page for
details.
@ -597,13 +599,47 @@ image will appear. The *sfactor* value must be a value 0.0 <=
*sfactor* <= 1.0, where *sfactor* = 1 is a highly reflective surface
and *sfactor* = 0 is a rough non-shiny surface.
The *ssao* keyword turns on/off a screen space ambient occlusion
(SSAO) model for depth shading. If *yes* is set, then atoms further
away from the viewer are darkened via a randomized process, which is
perceived as depth. The calculation of this effect can increase the
cost of computing the image by roughly 2x. The strength of the effect
can be scaled by the *dfactor* parameter. If *no* is set, no depth
shading is performed.
.. versionadded:: TBD
The *fsaa* keyword can be used with the dump image command to improve
the image quality by enabling full scene anti-aliasing. Internally the
image is rendered at twice the width and height and then scaled down by
computing the average of each 2x2 block of pixels to produce a single
pixel in the final image at the original size. This produces images with
smoother, less ragged edges. The application of this algorithm can
increase the cost of computing the image by about 3x or more.
The *ssao* keyword turns on/off a screen space ambient occlusion (SSAO)
model for depth shading. If *yes* is set, then atoms further away from
the viewer are darkened via a randomized process, which is perceived as
depth. The strength of the effect can be scaled by the *dfactor*
parameter. If *no* is set, no depth shading is performed. The
calculation of this effect can increase the cost of computing the image
substantially by 5x or more, especially with larger images. When used
in combination with the *fsaa* keyword the computational cost of depth
shading is particularly large.
----------
Image Quality Settings
""""""""""""""""""""""
The two keywords *fsaa* and *ssao* can be used to improve the image
quality at the expense of additional computational cost to render the
images. The images below show from left to right the same render with
default settings, with *fsaa* added, with *ssao* added, and with both
keywords added.
.. |imagequality1| image:: JPG/image.default.png
:width: 24%
.. |imagequality2| image:: JPG/image.fsaa.png
:width: 24%
.. |imagequality3| image:: JPG/image.ssao.png
:width: 24%
.. |imagequality4| image:: JPG/image.both.png
:width: 24%
|imagequality1| |imagequality2| |imagequality3| |imagequality4|
----------
@ -1051,6 +1087,7 @@ The defaults for the dump_modify keywords specific to dump image and dump movie
* boxcolor = yellow
* color = 140 color names are pre-defined as listed below
* framerate = 24
* fsaa = no
* gmap = min max cf 0.0 2 min blue max red
----------

View File

@ -1195,6 +1195,7 @@ Freitas
Frenkel
Friedrichs
fs
fsaa
fsh
fstyle
fsw

View File

@ -248,10 +248,14 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
int width = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
int height = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
if (width <= 0 || height <= 0)
error->all(FLERR,"Illegal dump image command");
image->width = width;
image->height = height;
if (width <= 0 || height <= 0) error->all(FLERR,"Illegal dump image command");
if (image->fsaa) {
image->width = width*2;
image->height = height*2;
} else {
image->width = width;
image->height = height;
}
iarg += 3;
} else if (strcmp(arg[iarg],"view") == 0) {
@ -345,6 +349,23 @@ DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
image->shiny = shiny;
iarg += 2;
} else if (strcmp(arg[iarg],"fsaa") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
int aa = utils::logical(FLERR, arg[iarg+1], false, lmp);
if (aa) {
if (!image->fsaa) {
image->width = image->width*2;
image->height = image->height*2;
}
} else {
if (image->fsaa) {
image->width = image->width/2;
image->height = image->height/2;
}
}
image->fsaa = aa;
iarg += 2;
} else if (strcmp(arg[iarg],"ssao") == 0) {
if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
image->ssao = utils::logical(FLERR,arg[iarg+1],false,lmp);

View File

@ -55,7 +55,9 @@ enum{NO,YES};
/* ---------------------------------------------------------------------- */
Image::Image(LAMMPS *lmp, int nmap_caller) : Pointers(lmp)
Image::Image(LAMMPS *lmp, int nmap_caller) :
Pointers(lmp), depthBuffer(nullptr), surfaceBuffer(nullptr), depthcopy(nullptr),
surfacecopy(nullptr), imageBuffer(nullptr), rgbcopy(nullptr), writeBuffer(nullptr)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
@ -69,6 +71,7 @@ Image::Image(LAMMPS *lmp, int nmap_caller) : Pointers(lmp)
persp = 0.0;
shiny = 1.0;
ssao = NO;
fsaa = NO;
up[0] = 0.0;
up[1] = 0.0;
@ -154,6 +157,13 @@ Image::~Image()
void Image::buffers()
{
memory->destroy(depthBuffer);
memory->destroy(surfaceBuffer);
memory->destroy(imageBuffer);
memory->destroy(depthcopy);
memory->destroy(surfacecopy);
memory->destroy(rgbcopy);
npixels = width * height;
memory->create(depthBuffer,npixels,"image:depthBuffer");
memory->create(surfaceBuffer,2*npixels,"image:surfaceBuffer");
@ -380,6 +390,26 @@ void Image::merge()
} else {
writeBuffer = imageBuffer;
}
// scale down image for antialiasing. can be done in place with simple averaging
if (fsaa) {
for (int h=0; h < height; h += 2) {
for (int w=0; w < width; w +=2) {
int idx1 = 3*height*h + 3*w;
int idx2 = 3*height*h + 3*(w+1);
int idx3 = 3*height*(h+1) + 3*w;
int idx4 = 3*height*(h+1) + 3*(w+1);
int out = 3*(height/2)*(h/2) + 3*(w/2);
for (int i=0; i < 3; ++i) {
writeBuffer[out+i] = (unsigned char) (0.25*((int)writeBuffer[idx1+i]
+(int)writeBuffer[idx2+i]
+(int)writeBuffer[idx3+i]
+(int)writeBuffer[idx4+i]));
}
}
}
}
}
/* ----------------------------------------------------------------------
@ -1037,6 +1067,7 @@ void Image::compute_SSAO()
void Image::write_JPG(FILE *fp)
{
#ifdef LAMMPS_JPEG
int aafactor = fsaa ? 2 : 1;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer;
@ -1044,8 +1075,8 @@ void Image::write_JPG(FILE *fp)
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo,fp);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.image_width = width/aafactor;
cinfo.image_height = height/aafactor;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
@ -1055,7 +1086,7 @@ void Image::write_JPG(FILE *fp)
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer = (JSAMPROW)
&writeBuffer[(cinfo.image_height - 1 - cinfo.next_scanline) * 3 * width];
&writeBuffer[(cinfo.image_height - 1 - cinfo.next_scanline) * 3 * (width/aafactor)];
jpeg_write_scanlines(&cinfo,&row_pointer,1);
}
@ -1071,6 +1102,7 @@ void Image::write_JPG(FILE *fp)
void Image::write_PNG(FILE *fp)
{
#ifdef LAMMPS_PNG
int aafactor = fsaa ? 2 : 1;
png_structp png_ptr;
png_infop info_ptr;
@ -1090,8 +1122,8 @@ void Image::write_PNG(FILE *fp)
}
png_init_io(png_ptr, fp);
png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
png_set_IHDR(png_ptr,info_ptr,width,height,8,PNG_COLOR_TYPE_RGB,
png_set_compression_level(png_ptr,Z_BEST_SPEED);
png_set_IHDR(png_ptr,info_ptr,width/aafactor,height/aafactor,8,PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
png_text text_ptr[2];
@ -1111,9 +1143,9 @@ void Image::write_PNG(FILE *fp)
png_set_text(png_ptr,info_ptr,text_ptr,1);
png_write_info(png_ptr,info_ptr);
auto row_pointers = new png_bytep[height];
for (int i=0; i < height; ++i)
row_pointers[i] = (png_bytep) &writeBuffer[(height-i-1)*3*width];
auto row_pointers = new png_bytep[height/aafactor];
for (int i=0; i < height/aafactor; ++i)
row_pointers[i] = (png_bytep) &writeBuffer[((height/aafactor)-i-1)*3*(width/aafactor)];
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, info_ptr);
@ -1129,11 +1161,12 @@ void Image::write_PNG(FILE *fp)
void Image::write_PPM(FILE *fp)
{
fprintf(fp,"P6\n%d %d\n255\n",width,height);
int aafactor = fsaa ? 2 : 1;
fprintf(fp,"P6\n%d %d\n255\n",width/aafactor,height/aafactor);
int y;
for (y = height-1; y >= 0; y--)
fwrite(&writeBuffer[y*width*3],3,width,fp);
for (y = (height/aafactor)-1; y >= 0; y--)
fwrite(&writeBuffer[y*(width/aafactor)*3],3,width/aafactor,fp);
}
/* ----------------------------------------------------------------------

View File

@ -28,13 +28,14 @@ class Image : protected Pointers {
double zoom; // zoom factor
double persp; // perspective factor
double shiny; // shininess of objects
int fsaa; // antialiasing on or off
int ssao; // SSAO on or off
int seed; // RN seed for SSAO
double ssaoint; // strength of shading from 0 to 1
double *boxcolor; // color to draw box outline with
int background[3]; // RGB values of background
double ambientColor[3]; // light color settings (adjustable by caller)
double ambientColor[3]; // light color settings (adjustable by caller)
double keyLightColor[3];
double fillLightColor[3];
double backLightColor[3];