Merge pull request #2613 from lammps/ssao_bugfix
Fix bug in dump image SSAO depth shading
This commit is contained in:
218
src/image.cpp
218
src/image.cpp
@ -113,6 +113,11 @@ Image::Image(LAMMPS *lmp, int nmap_caller) : Pointers(lmp)
|
|||||||
backLightColor[2] = 0.9;
|
backLightColor[2] = 0.9;
|
||||||
|
|
||||||
random = nullptr;
|
random = nullptr;
|
||||||
|
|
||||||
|
// MPI_Gatherv vectors
|
||||||
|
|
||||||
|
recvcounts = nullptr;
|
||||||
|
displs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
@ -134,6 +139,9 @@ Image::~Image()
|
|||||||
memory->destroy(rgbcopy);
|
memory->destroy(rgbcopy);
|
||||||
|
|
||||||
if (random) delete random;
|
if (random) delete random;
|
||||||
|
|
||||||
|
memory->destroy(recvcounts);
|
||||||
|
memory->destroy(displs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -334,16 +342,37 @@ void Image::merge()
|
|||||||
// extra SSAO enhancement
|
// extra SSAO enhancement
|
||||||
// bcast full image to all procs
|
// bcast full image to all procs
|
||||||
// each works on subset of pixels
|
// each works on subset of pixels
|
||||||
// gather result back to proc 0
|
// MPI_Gather() result back to proc 0
|
||||||
|
// use Gatherv() if subset of pixels is not the same size on every proc
|
||||||
|
|
||||||
if (ssao) {
|
if (ssao) {
|
||||||
MPI_Bcast(imageBuffer,npixels*3,MPI_BYTE,0,world);
|
MPI_Bcast(imageBuffer,npixels*3,MPI_BYTE,0,world);
|
||||||
MPI_Bcast(surfaceBuffer,npixels*2,MPI_DOUBLE,0,world);
|
MPI_Bcast(surfaceBuffer,npixels*2,MPI_DOUBLE,0,world);
|
||||||
MPI_Bcast(depthBuffer,npixels,MPI_DOUBLE,0,world);
|
MPI_Bcast(depthBuffer,npixels,MPI_DOUBLE,0,world);
|
||||||
compute_SSAO();
|
compute_SSAO();
|
||||||
int pixelPart = height/nprocs * width*3;
|
|
||||||
MPI_Gather(imageBuffer+me*pixelPart,pixelPart,MPI_BYTE,
|
int pixelstart = 3 * static_cast<int> (1.0*me/nprocs * npixels);
|
||||||
rgbcopy,pixelPart,MPI_BYTE,0,world);
|
int pixelstop = 3 * static_cast<int> (1.0*(me+1)/nprocs * npixels);
|
||||||
|
int mypixels = pixelstop - pixelstart;
|
||||||
|
|
||||||
|
if (npixels % nprocs == 0) {
|
||||||
|
MPI_Gather(imageBuffer+pixelstart,mypixels,MPI_BYTE,
|
||||||
|
rgbcopy,mypixels,MPI_BYTE,0,world);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (recvcounts == nullptr) {
|
||||||
|
memory->create(recvcounts,nprocs,"image:recvcounts");
|
||||||
|
memory->create(displs,nprocs,"image:displs");
|
||||||
|
MPI_Allgather(&mypixels,1,MPI_INT,recvcounts,1,MPI_INT,world);
|
||||||
|
displs[0] = 0;
|
||||||
|
for (int i = 1; i < nprocs; i++)
|
||||||
|
displs[i] = displs[i-1] + recvcounts[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Gatherv(imageBuffer+pixelstart,mypixels,MPI_BYTE,
|
||||||
|
rgbcopy,recvcounts,displs,MPI_BYTE,0,world);
|
||||||
|
}
|
||||||
|
|
||||||
writeBuffer = rgbcopy;
|
writeBuffer = rgbcopy;
|
||||||
} else {
|
} else {
|
||||||
writeBuffer = imageBuffer;
|
writeBuffer = imageBuffer;
|
||||||
@ -880,110 +909,117 @@ void Image::compute_SSAO()
|
|||||||
-tanPerPixel / zoom;
|
-tanPerPixel / zoom;
|
||||||
int pixelRadius = (int) trunc (SSAORadius / pixelWidth + 0.5);
|
int pixelRadius = (int) trunc (SSAORadius / pixelWidth + 0.5);
|
||||||
|
|
||||||
int x,y,s;
|
// each proc is assigned a subset of contiguous pixels from the full image
|
||||||
int hPart = height / nprocs;
|
// pixels are contiguous in x (columns within a row), then by row
|
||||||
int index = me * hPart * width;
|
// index = pixels from 0 to npixel-1
|
||||||
for (y = me * hPart; y < (me + 1) * hPart; y ++) {
|
// x = column # from 0 to width-1
|
||||||
for (x = 0; x < width; x ++, index ++) {
|
// y = row # from 0 to height-1
|
||||||
double cdepth = depthBuffer[index];
|
|
||||||
if (cdepth < 0) { continue; }
|
|
||||||
|
|
||||||
double sx = surfaceBuffer[index * 2 + 0];
|
int pixelstart = static_cast<int> (1.0*me/nprocs * npixels);
|
||||||
double sy = surfaceBuffer[index * 2 + 1];
|
int pixelstop = static_cast<int> (1.0*(me+1)/nprocs * npixels);
|
||||||
double sin_t = -sqrt(sx*sx + sy*sy);
|
|
||||||
|
|
||||||
double mytheta = random->uniform() * SSAOJitter;
|
for (int index = pixelstart; index < pixelstop; index++) {
|
||||||
double ao = 0.0;
|
int x = index % width;
|
||||||
|
int y = index / width;
|
||||||
|
|
||||||
for (s = 0; s < SSAOSamples; s ++) {
|
double cdepth = depthBuffer[index];
|
||||||
double hx = cos(mytheta);
|
if (cdepth < 0) { continue; }
|
||||||
double hy = sin(mytheta);
|
|
||||||
mytheta += delTheta;
|
|
||||||
|
|
||||||
// multiply by z cross surface tangent
|
double sx = surfaceBuffer[index * 2 + 0];
|
||||||
// so that dot (aka cos) works here
|
double sy = surfaceBuffer[index * 2 + 1];
|
||||||
|
double sin_t = -sqrt(sx*sx + sy*sy);
|
||||||
|
|
||||||
double scaled_sin_t = sin_t * (hx*sy + hy*sx);
|
double mytheta = random->uniform() * SSAOJitter;
|
||||||
|
double ao = 0.0;
|
||||||
|
|
||||||
// Bresenham's line algorithm to march over depthBuffer
|
for (int s = 0; s < SSAOSamples; s ++) {
|
||||||
|
double hx = cos(mytheta);
|
||||||
|
double hy = sin(mytheta);
|
||||||
|
mytheta += delTheta;
|
||||||
|
|
||||||
int dx = static_cast<int> (hx * pixelRadius);
|
// multiply by z cross surface tangent
|
||||||
int dy = static_cast<int> (hy * pixelRadius);
|
// so that dot (aka cos) works here
|
||||||
int ex = x + dx;
|
|
||||||
if (ex < 0) { ex = 0; } if (ex >= width) { ex = width - 1; }
|
double scaled_sin_t = sin_t * (hx*sy + hy*sx);
|
||||||
int ey = y + dy;
|
|
||||||
if (ey < 0) { ey = 0; } if (ey >= height) { ey = height - 1; }
|
// Bresenham's line algorithm to march over depthBuffer
|
||||||
double delta;
|
|
||||||
int small, large;
|
int dx = static_cast<int> (hx * pixelRadius);
|
||||||
double lenIncr;
|
int dy = static_cast<int> (hy * pixelRadius);
|
||||||
if (fabs(hx) > fabs(hy)) {
|
int ex = x + dx;
|
||||||
small = (hx > 0) ? 1 : -1;
|
if (ex < 0) { ex = 0; } if (ex >= width) { ex = width - 1; }
|
||||||
large = (hy > 0) ? width : -width;
|
int ey = y + dy;
|
||||||
delta = fabs(hy / hx);
|
if (ey < 0) { ey = 0; } if (ey >= height) { ey = height - 1; }
|
||||||
} else {
|
double delta;
|
||||||
small = (hy > 0) ? width : -width;
|
int small, large;
|
||||||
large = (hx > 0) ? 1 : -1;
|
double lenIncr;
|
||||||
delta = fabs(hx / hy);
|
if (fabs(hx) > fabs(hy)) {
|
||||||
|
small = (hx > 0) ? 1 : -1;
|
||||||
|
large = (hy > 0) ? width : -width;
|
||||||
|
delta = fabs(hy / hx);
|
||||||
|
} else {
|
||||||
|
small = (hy > 0) ? width : -width;
|
||||||
|
large = (hx > 0) ? 1 : -1;
|
||||||
|
delta = fabs(hx / hy);
|
||||||
|
}
|
||||||
|
lenIncr = sqrt (1 + delta * delta) * pixelWidth;
|
||||||
|
|
||||||
|
// initialize with one step
|
||||||
|
// because the center point doesn't need testing
|
||||||
|
|
||||||
|
int end = ex + ey * width;
|
||||||
|
int ind = index + small;
|
||||||
|
double len = lenIncr;
|
||||||
|
double err = delta;
|
||||||
|
if (err >= 1.0) {
|
||||||
|
ind += large;
|
||||||
|
err -= 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double minPeak = -1;
|
||||||
|
double peakLen = 0.0;
|
||||||
|
int stepsTaken = 1;
|
||||||
|
while ((small > 0 && ind <= end) || (small < 0 && ind >= end)) {
|
||||||
|
if (ind < 0 || ind >= (width*height)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
lenIncr = sqrt (1 + delta * delta) * pixelWidth;
|
|
||||||
|
|
||||||
// initialize with one step
|
// cdepth - depthBuffer B/C we want it in the negative z direction
|
||||||
// because the center point doesn't need testing
|
|
||||||
|
|
||||||
int end = ex + ey * width;
|
if (minPeak < 0 || (depthBuffer[ind] >= 0 &&
|
||||||
int ind = index + small;
|
depthBuffer[ind] < minPeak)) {
|
||||||
double len = lenIncr;
|
minPeak = depthBuffer[ind];
|
||||||
double err = delta;
|
peakLen = len;
|
||||||
|
}
|
||||||
|
ind += small;
|
||||||
|
len += lenIncr;
|
||||||
|
err += delta;
|
||||||
if (err >= 1.0) {
|
if (err >= 1.0) {
|
||||||
ind += large;
|
ind += large;
|
||||||
err -= 1.0;
|
err -= 1.0;
|
||||||
}
|
}
|
||||||
|
stepsTaken ++;
|
||||||
double minPeak = -1;
|
|
||||||
double peakLen = 0.0;
|
|
||||||
int stepsTaken = 1;
|
|
||||||
while ((small > 0 && ind <= end) || (small < 0 && ind >= end)) {
|
|
||||||
if (ind < 0 || ind >= (width*height)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cdepth - depthBuffer B/C we want it in the negative z direction
|
|
||||||
|
|
||||||
if (minPeak < 0 || (depthBuffer[ind] >= 0 &&
|
|
||||||
depthBuffer[ind] < minPeak)) {
|
|
||||||
minPeak = depthBuffer[ind];
|
|
||||||
peakLen = len;
|
|
||||||
}
|
|
||||||
ind += small;
|
|
||||||
len += lenIncr;
|
|
||||||
err += delta;
|
|
||||||
if (err >= 1.0) {
|
|
||||||
ind += large;
|
|
||||||
err -= 1.0;
|
|
||||||
}
|
|
||||||
stepsTaken ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (peakLen > 0) {
|
|
||||||
double h = atan ((cdepth - minPeak) / peakLen);
|
|
||||||
ao += saturate(sin (h) - scaled_sin_t);
|
|
||||||
} else {
|
|
||||||
ao += saturate(-scaled_sin_t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ao /= (double)SSAOSamples;
|
|
||||||
|
|
||||||
double c[3];
|
if (peakLen > 0) {
|
||||||
c[0] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 0]);
|
double h = atan ((cdepth - minPeak) / peakLen);
|
||||||
c[1] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 1]);
|
ao += saturate(sin (h) - scaled_sin_t);
|
||||||
c[2] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 2]);
|
} else {
|
||||||
c[0] *= (1.0 - ao);
|
ao += saturate(-scaled_sin_t);
|
||||||
c[1] *= (1.0 - ao);
|
}
|
||||||
c[2] *= (1.0 - ao);
|
|
||||||
imageBuffer[index * 3 + 0] = (int) c[0];
|
|
||||||
imageBuffer[index * 3 + 1] = (int) c[1];
|
|
||||||
imageBuffer[index * 3 + 2] = (int) c[2];
|
|
||||||
}
|
}
|
||||||
|
ao /= (double)SSAOSamples;
|
||||||
|
|
||||||
|
double c[3];
|
||||||
|
c[0] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 0]);
|
||||||
|
c[1] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 1]);
|
||||||
|
c[2] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 2]);
|
||||||
|
c[0] *= (1.0 - ao);
|
||||||
|
c[1] *= (1.0 - ao);
|
||||||
|
c[2] *= (1.0 - ao);
|
||||||
|
imageBuffer[index * 3 + 0] = (int) c[0];
|
||||||
|
imageBuffer[index * 3 + 1] = (int) c[1];
|
||||||
|
imageBuffer[index * 3 + 2] = (int) c[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,6 +73,10 @@ class Image : protected Pointers {
|
|||||||
double *depthcopy,*surfacecopy;
|
double *depthcopy,*surfacecopy;
|
||||||
unsigned char *imageBuffer,*rgbcopy,*writeBuffer;
|
unsigned char *imageBuffer,*rgbcopy,*writeBuffer;
|
||||||
|
|
||||||
|
// MPI_Gatherv
|
||||||
|
|
||||||
|
int *recvcounts,*displs;
|
||||||
|
|
||||||
// constant view params
|
// constant view params
|
||||||
|
|
||||||
double FOV;
|
double FOV;
|
||||||
|
|||||||
Reference in New Issue
Block a user