Ocean Modifier: allow spray maps to be baked

In comments made by a tester on rB17b89f6dacba007bf, it seems that baking
of the spray maps would be useful. This commit adds that capability. Both
the spray map and its inverse are baked out in this change, for maximum
convenience and to avoid assuming what the user wants.

Differential Revision: https://developer.blender.org/D8470
This commit is contained in:
Hans Goudey 2020-10-20 12:47:58 -05:00
parent de77aa337c
commit 3d78e98d52
Notes: blender-bot 2023-02-14 11:00:17 +01:00
Referenced by issue #81905, Keyframe Handle Select Assertion Fail
3 changed files with 90 additions and 2 deletions

View File

@ -44,6 +44,10 @@ typedef struct OceanCache {
struct ImBuf **ibufs_disp;
struct ImBuf **ibufs_foam;
struct ImBuf **ibufs_norm;
/* spray is Eplus */
struct ImBuf **ibufs_spray;
/* spray_inverse is Eminus */
struct ImBuf **ibufs_spray_inverse;
const char *bakepath;
const char *relbase;
@ -92,6 +96,7 @@ void BKE_ocean_init(struct Ocean *o,
float sharpen_peak_jonswap,
short do_height_field,
short do_chop,
short do_spray,
short do_normals,
short do_jacobian,
int seed);

View File

@ -773,12 +773,13 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution)
{
short do_heightfield, do_chop, do_normals, do_jacobian;
short do_heightfield, do_chop, do_normals, do_jacobian, do_spray;
do_heightfield = true;
do_chop = (omd->chop_amount > 0);
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
do_spray = do_jacobian && (omd->flag & MOD_OCEAN_GENERATE_SPRAY);
BKE_ocean_free_data(ocean);
@ -800,6 +801,7 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean,
omd->sharpen_peak_jonswap,
do_heightfield,
do_chop,
do_spray,
do_normals,
do_jacobian,
omd->seed);
@ -823,6 +825,7 @@ void BKE_ocean_init(struct Ocean *o,
float sharpen_peak_jonswap,
short do_height_field,
short do_chop,
short do_spray,
short do_normals,
short do_jacobian,
int seed)
@ -857,6 +860,7 @@ void BKE_ocean_init(struct Ocean *o,
o->_do_disp_y = do_height_field;
o->_do_normals = do_normals;
o->_do_spray = do_spray;
o->_do_chop = do_chop;
o->_do_jacobian = do_jacobian;
@ -1107,6 +1111,8 @@ void BKE_ocean_free(struct Ocean *oc)
# define CACHE_TYPE_DISPLACE 1
# define CACHE_TYPE_FOAM 2
# define CACHE_TYPE_NORMAL 3
# define CACHE_TYPE_SPRAY 4
# define CACHE_TYPE_SPRAY_INVERSE 5
static void cache_filename(
char *string, const char *path, const char *relbase, int frame, int type)
@ -1121,6 +1127,12 @@ static void cache_filename(
case CACHE_TYPE_NORMAL:
fname = "normal_";
break;
case CACHE_TYPE_SPRAY:
fname = "spray_";
break;
case CACHE_TYPE_SPRAY_INVERSE:
fname = "spray_inverse_";
break;
case CACHE_TYPE_DISPLACE:
default:
fname = "disp_";
@ -1175,6 +1187,24 @@ void BKE_ocean_free_cache(struct OceanCache *och)
MEM_freeN(och->ibufs_foam);
}
if (och->ibufs_spray) {
for (i = och->start, f = 0; i <= och->end; i++, f++) {
if (och->ibufs_spray[f]) {
IMB_freeImBuf(och->ibufs_spray[f]);
}
}
MEM_freeN(och->ibufs_spray);
}
if (och->ibufs_spray_inverse) {
for (i = och->start, f = 0; i <= och->end; i++, f++) {
if (och->ibufs_spray_inverse[f]) {
IMB_freeImBuf(och->ibufs_spray_inverse[f]);
}
}
MEM_freeN(och->ibufs_spray_inverse);
}
if (och->ibufs_norm) {
for (i = och->start, f = 0; i <= och->end; i++, f++) {
if (och->ibufs_norm[f]) {
@ -1217,6 +1247,17 @@ void BKE_ocean_cache_eval_uv(
ocr->foam = result[0];
}
if (och->ibufs_spray[f]) {
ibuf_sample(och->ibufs_spray[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
copy_v3_v3(ocr->Eplus, result);
}
if (och->ibufs_spray_inverse[f]) {
ibuf_sample(
och->ibufs_spray_inverse[f], u, v, (1.0f / (float)res_x), (1.0f / (float)res_y), result);
copy_v3_v3(ocr->Eminus, result);
}
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);
@ -1246,6 +1287,14 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, in
ocr->foam = och->ibufs_foam[f]->rect_float[4 * (res_x * j + i)];
}
if (och->ibufs_spray[f]) {
copy_v3_v3(ocr->Eplus, &och->ibufs_spray[f]->rect_float[4 * (res_x * j + i)]);
}
if (och->ibufs_spray_inverse[f]) {
copy_v3_v3(ocr->Eminus, &och->ibufs_spray_inverse[f]->rect_float[4 * (res_x * j + i)]);
}
if (och->ibufs_norm[f]) {
copy_v3_v3(ocr->normal, &och->ibufs_norm[f]->rect_float[4 * (res_x * j + i)]);
}
@ -1279,6 +1328,9 @@ struct OceanCache *BKE_ocean_init_cache(const char *bakepath,
och->ibufs_disp = MEM_callocN(sizeof(ImBuf *) * och->duration,
"displacement imbuf pointer array");
och->ibufs_foam = MEM_callocN(sizeof(ImBuf *) * och->duration, "foam imbuf pointer array");
och->ibufs_spray = MEM_callocN(sizeof(ImBuf *) * och->duration, "spray imbuf pointer array");
och->ibufs_spray_inverse = MEM_callocN(sizeof(ImBuf *) * och->duration,
"spray_inverse imbuf pointer array");
och->ibufs_norm = MEM_callocN(sizeof(ImBuf *) * och->duration, "normal imbuf pointer array");
och->time = NULL;
@ -1310,6 +1362,12 @@ void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY);
och->ibufs_spray[f] = IMB_loadiffname(string, 0, NULL);
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_SPRAY_INVERSE);
och->ibufs_spray_inverse[f] = IMB_loadiffname(string, 0, NULL);
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
}
@ -1329,7 +1387,7 @@ void BKE_ocean_bake(struct Ocean *o,
int f, i = 0, x, y, cancel = 0;
float progress;
ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal;
ImBuf *ibuf_foam, *ibuf_disp, *ibuf_normal, *ibuf_spray, *ibuf_spray_inverse;
float *prev_foam;
int res_x = och->resolution_x;
int res_y = och->resolution_y;
@ -1360,6 +1418,8 @@ void BKE_ocean_bake(struct Ocean *o,
ibuf_foam = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_spray = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_spray_inverse = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
BKE_ocean_simulate(o, och->time[i], och->wave_scale, och->chop_amount);
@ -1414,6 +1474,13 @@ void BKE_ocean_bake(struct Ocean *o,
/*foam_result = min_ff(foam_result, 1.0f); */
value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
/* spray map baking */
if (o->_do_spray) {
rgb_to_rgba_unit_alpha(&ibuf_spray->rect_float[4 * (res_x * y + x)], ocr.Eplus);
rgb_to_rgba_unit_alpha(&ibuf_spray_inverse->rect_float[4 * (res_x * y + x)],
ocr.Eminus);
}
}
if (o->_do_normals) {
@ -1433,6 +1500,18 @@ void BKE_ocean_bake(struct Ocean *o,
if (0 == BKE_imbuf_write(ibuf_foam, string, &imf)) {
printf("Cannot save Foam File Output to %s\n", string);
}
if (o->_do_spray) {
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY);
if (0 == BKE_imbuf_write(ibuf_spray, string, &imf)) {
printf("Cannot save Spray File Output to %s\n", string);
}
cache_filename(string, och->bakepath, och->relbase, f, CACHE_TYPE_SPRAY_INVERSE);
if (0 == BKE_imbuf_write(ibuf_spray_inverse, string, &imf)) {
printf("Cannot save Spray Inverse File Output to %s\n", string);
}
}
}
if (o->_do_normals) {
@ -1445,6 +1524,8 @@ void BKE_ocean_bake(struct Ocean *o,
IMB_freeImBuf(ibuf_disp);
IMB_freeImBuf(ibuf_foam);
IMB_freeImBuf(ibuf_normal);
IMB_freeImBuf(ibuf_spray);
IMB_freeImBuf(ibuf_spray_inverse);
progress = (f - och->start) / (float)och->duration;
@ -1541,6 +1622,7 @@ void BKE_ocean_init(struct Ocean *UNUSED(o),
float UNUSED(sharpen_peak_jonswap),
short UNUSED(do_height_field),
short UNUSED(do_chop),
short UNUSED(do_spray),
short UNUSED(do_normals),
short UNUSED(do_jacobian),
int UNUSED(seed))

View File

@ -57,6 +57,7 @@ typedef struct Ocean {
short _do_disp_y;
short _do_normals;
short _do_spray;
short _do_chop;
short _do_jacobian;