void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v) { int res_x = och->resolution_x; int res_y = och->resolution_y; float result[4]; u = fmod(u, 1.0); v = fmod(v, 1.0); if (u < 0) u += 1.0f; if (v < 0) v += 1.0f; if (och->ibufs_disp[f]) { ibuf_sample(och->ibufs_disp[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result); copy_v3_v3(ocr->disp, result); } if (och->ibufs_foam[f]) { ibuf_sample(och->ibufs_foam[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result); ocr->foam = result[0]; } if (och->ibufs_norm[f]) { ibuf_sample(och->ibufs_norm[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result); copy_v3_v3(ocr->normal, result); } }
/* stackbuf should be zeroed */ static void do_mapuv(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *uvbuf, float threshold) { ImBuf *ibuf; float *out= stackbuf->rect, *uv, *uvnext, *uvprev; float dx, dy, alpha; int x, y, sx, sy, row= 3*stackbuf->x; /* ibuf needed for sampling */ ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); ibuf->rect_float= cbuf->rect; /* vars for efficient looping */ uv= uvbuf->rect; uvnext= uv+row; uvprev= uv-row; sx= stackbuf->x; sy= stackbuf->y; for(y=0; y<sy; y++) { for(x=0; x<sx; x++, out+=4, uv+=3, uvnext+=3, uvprev+=3) { if(x>0 && x<sx-1 && y>0 && y<sy-1) { if(uv[2]!=0.0f) { float uv_l, uv_r; /* adaptive sampling, red (U) channel */ /* prevent alpha zero UVs to be used */ uv_l= uv[-1]!=0.0f? fabs(uv[0]-uv[-3]) : 0.0f; uv_r= uv[ 5]!=0.0f? fabs(uv[0]-uv[ 3]) : 0.0f; //dx= 0.5f*(fabs(uv[0]-uv[-3]) + fabs(uv[0]-uv[3])); dx= 0.5f*(uv_l + uv_r); uv_l= uvprev[-1]!=0.0f? fabs(uv[0]-uvprev[-3]) : 0.0f; uv_r= uvnext[-1]!=0.0f? fabs(uv[0]-uvnext[-3]) : 0.0f; //dx+= 0.25f*(fabs(uv[0]-uvprev[-3]) + fabs(uv[0]-uvnext[-3])); dx+= 0.25f*(uv_l + uv_r); uv_l= uvprev[ 5]!=0.0f? fabs(uv[0]-uvprev[+3]) : 0.0f; uv_r= uvnext[ 5]!=0.0f? fabs(uv[0]-uvnext[+3]) : 0.0f; //dx+= 0.25f*(fabs(uv[0]-uvprev[+3]) + fabs(uv[0]-uvnext[+3])); dx+= 0.25f*(uv_l + uv_r); /* adaptive sampling, green (V) channel */ uv_l= uv[-row+2]!=0.0f? fabs(uv[1]-uv[-row+1]) : 0.0f; uv_r= uv[ row+2]!=0.0f? fabs(uv[1]-uv[ row+1]) : 0.0f; //dy= 0.5f*(fabs(uv[1]-uv[-row+1]) + fabs(uv[1]-uv[row+1])); dy= 0.5f*(uv_l + uv_r); uv_l= uvprev[-1]!=0.0f? fabs(uv[1]-uvprev[+1-3]) : 0.0f; uv_r= uvnext[-1]!=0.0f? fabs(uv[1]-uvnext[+1-3]) : 0.0f; //dy+= 0.25f*(fabs(uv[1]-uvprev[+1-3]) + fabs(uv[1]-uvnext[+1-3])); dy+= 0.25f*(uv_l + uv_r); uv_l= uvprev[ 5]!=0.0f? fabs(uv[1]-uvprev[+1+3]) : 0.0f; uv_r= uvnext[ 5]!=0.0f? fabs(uv[1]-uvnext[+1+3]) : 0.0f; //dy+= 0.25f*(fabs(uv[1]-uvprev[+1+3]) + fabs(uv[1]-uvnext[+1+3])); dy+= 0.25f*(uv_l + uv_r); /* UV to alpha threshold */ alpha= 1.0f - threshold*(dx+dy); if(alpha<0.0f) alpha= 0.0f; else alpha*= uv[2]; /* should use mipmap */ if(dx > 0.20f) dx= 0.20f; if(dy > 0.20f) dy= 0.20f; ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out); /* premul */ if(alpha<1.0f) { out[0]*= alpha; out[1]*= alpha; out[2]*= alpha; out[3]*= alpha; } } } } } IMB_freeImBuf(ibuf); }
static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf, CompBuf *ybuf, float *xscale, float *yscale) { ImBuf *ibuf; int x, y; float p_dx, p_dy; /* main displacement in pixel space */ float d_dx, d_dy; float dxt, dyt; float u, v; float xs, ys; float vec[3], vecdx[3], vecdy[3]; float col[3]; ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); ibuf->rect_float= cbuf->rect; for(y=0; y < stackbuf->y; y++) { for(x=0; x < stackbuf->x; x++) { /* calc pixel coordinates */ qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec); if (xbuf) qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs); else xs = xscale[0]; if (ybuf) qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys); else ys = yscale[0]; p_dx = vec[0] * xs; p_dy = vec[1] * ys; /* if no displacement, then just copy this pixel */ if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) { qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col); qd_setPixel(stackbuf, x, y, col); continue; } /* displaced pixel in uv coords, for image sampling */ u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x; v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y; /* calc derivatives */ qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx); qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy); d_dx = vecdx[0] * xs; d_dy = vecdy[0] * ys; /* clamp derivatives to minimum displacement distance in UV space */ dxt = p_dx - d_dx; dyt = p_dy - d_dy; dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x; dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y; ibuf_sample(ibuf, u, v, dxt, dyt, col); qd_setPixel(stackbuf, x, y, col); } } IMB_freeImBuf(ibuf); /* simple method for reference, linear interpolation */ /* int x, y; float dx, dy; float u, v; float vec[3]; float col[3]; for(y=0; y < stackbuf->y; y++) { for(x=0; x < stackbuf->x; x++) { qd_getPixel(vecbuf, x, y, vec); dx = vec[0] * (xscale[0]); dy = vec[1] * (yscale[0]); u = (x - dx + 0.5f) / (float)stackbuf->x; v = (y - dy + 0.5f) / (float)stackbuf->y; qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col); qd_setPixel(stackbuf, x, y, col); } } */ }