Changeset View
Changeset View
Standalone View
Standalone View
source/blender/render/intern/source/bake_api.c
| Show First 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
| /* local include */ | /* local include */ | ||||
| #include "render_types.h" | #include "render_types.h" | ||||
| #include "zbuf.h" | #include "zbuf.h" | ||||
| typedef struct BakeDataZSpan { | typedef struct BakeDataZSpan { | ||||
| BakePixel *pixel_array; | BakePixel *pixel_array; | ||||
| int primitive_id; | int primitive_id; | ||||
| BakeImage *bk_image; | const BakeImage *bk_image; | ||||
| ZSpan *zspan; | ZSpan zspan; | ||||
| float du_dx, du_dy; | float du_dx, du_dy; | ||||
| float dv_dx, dv_dy; | float dv_dx, dv_dy; | ||||
| } BakeDataZSpan; | } BakeDataZSpan; | ||||
| /** | /** | ||||
| * struct wrapping up tangent space data | * struct wrapping up tangent space data | ||||
| */ | */ | ||||
| typedef struct TSpace { | typedef struct TSpace { | ||||
| Show All 10 Lines | |||||
| } TriTessFace; | } TriTessFace; | ||||
| static void store_bake_pixel(void *handle, int x, int y, float u, float v) | static void store_bake_pixel(void *handle, int x, int y, float u, float v) | ||||
| { | { | ||||
| BakeDataZSpan *bd = (BakeDataZSpan *)handle; | BakeDataZSpan *bd = (BakeDataZSpan *)handle; | ||||
| BakePixel *pixel; | BakePixel *pixel; | ||||
| const int width = bd->bk_image->width; | const int width = bd->bk_image->width; | ||||
| const size_t offset = bd->bk_image->offset; | const int i = y * width + x; | ||||
| const int i = offset + y * width + x; | |||||
| pixel = &bd->pixel_array[i]; | pixel = &bd->pixel_array[i]; | ||||
| pixel->primitive_id = bd->primitive_id; | pixel->primitive_id = bd->primitive_id; | ||||
| /* At this point object_id is always 0, since this function runs for the | /* At this point object_id is always 0, since this function runs for the | ||||
| * low-poly mesh only. The object_id lookup indices are set afterwards. */ | * low-poly mesh only. The object_id lookup indices are set afterwards. */ | ||||
| copy_v2_fl2(pixel->uv, u, v); | copy_v2_fl2(pixel->uv, u, v); | ||||
| Show All 15 Lines | void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask) | ||||
| /* only extend to pixels outside the mask area */ | /* only extend to pixels outside the mask area */ | ||||
| for (i = 0; i < num_pixels; i++) { | for (i = 0; i < num_pixels; i++) { | ||||
| if (pixel_array[i].primitive_id != -1) { | if (pixel_array[i].primitive_id != -1) { | ||||
| mask[i] = FILTER_MASK_USED; | mask[i] = FILTER_MASK_USED; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void RE_bake_margin(ImBuf *ibuf, char *mask, const int margin) | void RE_bake_margin(ImBuf *ibuf, char *mask, const int margin, bool preserve_existing) | ||||
| { | { | ||||
| /* margin */ | /* margin */ | ||||
| IMB_filter_extend(ibuf, mask, margin); | IMB_filter_extend(ibuf, mask, margin, preserve_existing); | ||||
| if (ibuf->planes != R_IMF_PLANES_RGBA) { | if (ibuf->planes != R_IMF_PLANES_RGBA) { | ||||
| /* clear alpha added by filtering */ | /* clear alpha added by filtering */ | ||||
| IMB_rectfill_alpha(ibuf, 1.0f); | IMB_rectfill_alpha(ibuf, 1.0f); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| ▲ Show 20 Lines • Show All 512 Lines • ▼ Show 20 Lines | else { | ||||
| bd->du_dx = bd->du_dy = 0.0f; | bd->du_dx = bd->du_dy = 0.0f; | ||||
| bd->dv_dx = bd->dv_dy = 0.0f; | bd->dv_dx = bd->dv_dy = 0.0f; | ||||
| } | } | ||||
| } | } | ||||
| void RE_bake_pixels_populate(Mesh *me, | void RE_bake_pixels_populate(Mesh *me, | ||||
| BakePixel pixel_array[], | BakePixel pixel_array[], | ||||
| const size_t num_pixels, | const size_t num_pixels, | ||||
| const BakeImages *bake_images, | const BakeImage *bake_image, | ||||
| const char *uv_layer) | const char *uv_layer) | ||||
| { | { | ||||
| BakeDataZSpan bd; | BakeDataZSpan bd = {0}; | ||||
| size_t i; | size_t i; | ||||
| int a, p_id; | |||||
| /* initialize all pixel arrays so we know which ones are 'blank' */ | |||||
| for (i = 0; i < num_pixels; i++) { | |||||
| pixel_array[i].primitive_id = -1; | |||||
| pixel_array[i].object_id = 0; | |||||
| } | |||||
| const MLoopUV *mloopuv; | const MLoopUV *mloopuv; | ||||
| const int tottri = poly_to_tri_count(me->totpoly, me->totloop); | const int tottri = poly_to_tri_count(me->totpoly, me->totloop); | ||||
| MLoopTri *looptri; | MLoopTri *looptri; | ||||
| if ((uv_layer == NULL) || (uv_layer[0] == '\0')) { | if ((uv_layer == NULL) || (uv_layer[0] == '\0')) { | ||||
| mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); | mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| else { | else { | ||||
| int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer); | mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, uv_layer); | ||||
| mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, uv_id); | |||||
| } | } | ||||
| if (mloopuv == NULL) { | if (mloopuv == NULL) { | ||||
| BLI_assert(false); | |||||
| return; | return; | ||||
| } | } | ||||
| bd.pixel_array = pixel_array; | bd.pixel_array = pixel_array; | ||||
| bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan"); | |||||
| /* initialize all pixel arrays so we know which ones are 'blank' */ | |||||
| for (i = 0; i < num_pixels; i++) { | |||||
| pixel_array[i].primitive_id = -1; | |||||
| pixel_array[i].object_id = 0; | |||||
| } | |||||
| for (i = 0; i < bake_images->size; i++) { | zbuf_alloc_span(&bd.zspan, bake_image->width, bake_image->height); | ||||
| zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height); | |||||
| } | |||||
| looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); | looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); | ||||
| BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); | BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); | ||||
| p_id = -1; | |||||
| for (i = 0; i < tottri; i++) { | for (i = 0; i < tottri; i++) { | ||||
| const MLoopTri *lt = &looptri[i]; | const MLoopTri *lt = &looptri[i]; | ||||
| const MPoly *mp = &me->mpoly[lt->poly]; | const MPoly *mp = &me->mpoly[lt->poly]; | ||||
| float vec[3][2]; | float vec[3][2]; | ||||
| int mat_nr = mp->mat_nr; | int mat_nr = mp->mat_nr; | ||||
| int image_id = bake_images->lookup[mat_nr]; | |||||
| if (image_id < 0) { | if (mat_nr < bake_image->mat_mask_length && !bake_image->mat_mask[mat_nr]) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| bd.bk_image = &bake_images->data[image_id]; | bd.bk_image = bake_image; | ||||
| bd.primitive_id = ++p_id; | bd.primitive_id = i; | ||||
| for (a = 0; a < 3; a++) { | for (int a = 0; a < 3; a++) { | ||||
| const float *uv = mloopuv[lt->tri[a]].uv; | const float *uv = mloopuv[lt->tri[a]].uv; | ||||
| /* Note, workaround for pixel aligned UVs which are common and can screw up our | /* Note, workaround for pixel aligned UVs which are common and can screw up our | ||||
| * intersection tests where a pixel gets in between 2 faces or the middle of a quad, | * intersection tests where a pixel gets in between 2 faces or the middle of a quad, | ||||
| * camera aligned quads also have this problem but they are less common. | * camera aligned quads also have this problem but they are less common. | ||||
| * Add a small offset to the UVs, fixes bug #18685 - Campbell */ | * Add a small offset to the UVs, fixes bug #18685 - Campbell */ | ||||
| vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f); | vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f); | ||||
| vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f); | vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f); | ||||
| } | } | ||||
| bake_differentials(&bd, vec[0], vec[1], vec[2]); | bake_differentials(&bd, vec[0], vec[1], vec[2]); | ||||
| zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel); | zspan_scanconvert(&bd.zspan, (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel); | ||||
| } | } | ||||
| for (i = 0; i < bake_images->size; i++) { | zbuf_free_span(&bd.zspan); | ||||
| zbuf_free_span(&bd.zspan[i]); | |||||
| } | |||||
| MEM_freeN(looptri); | MEM_freeN(looptri); | ||||
| MEM_freeN(bd.zspan); | |||||
| } | } | ||||
| /* ******************** NORMALS ************************ */ | /* ******************** NORMALS ************************ */ | ||||
| /** | /** | ||||
| * convert a normalized normal to the -1.0 1.0 range | * convert a normalized normal to the -1.0 1.0 range | ||||
| * the input is expected to be POS_X, POS_Y, POS_Z | * the input is expected to be POS_X, POS_Y, POS_Z | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | for (i = 0; i < num_pixels; i++) { | ||||
| offset = i * depth; | offset = i * depth; | ||||
| normal_uncompress(nor, &result[offset]); | normal_uncompress(nor, &result[offset]); | ||||
| /* save back the values */ | /* save back the values */ | ||||
| normal_compress(&result[offset], nor, normal_swizzle); | normal_compress(&result[offset], nor, normal_swizzle); | ||||
| } | } | ||||
| } | } | ||||
| void RE_bake_ibuf_clear(Image *image, const bool is_tangent) | void RE_bake_ibuf_clear(Image *image, const float clear_color[3]) | ||||
| { | { | ||||
| ImBuf *ibuf; | ImBuf *ibuf; | ||||
| void *lock; | void *lock; | ||||
| const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f}; | float col[4]; | ||||
| const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f}; | copy_v3_v3(col, clear_color); | ||||
| const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f}; | |||||
| const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f}; | |||||
| ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); | ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); | ||||
| BLI_assert(ibuf); | BLI_assert(ibuf); | ||||
| if (is_tangent) { | col[3] = (ibuf->planes == R_IMF_PLANES_RGBA) ? 1.0f : 0.0f; | ||||
| IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); | |||||
| } | |||||
| else { | |||||
| IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); | |||||
| } | |||||
| BKE_image_release_ibuf(image, ibuf, lock); | |||||
| } | |||||
| /* ************************************************************* */ | IMB_rectfill(ibuf, col); | ||||
| int RE_pass_depth(const eScenePassType pass_type) | BKE_image_release_ibuf(image, ibuf, lock); | ||||
| { | |||||
| /* IMB_buffer_byte_from_float assumes 4 channels | |||||
| * making it work for now - XXX */ | |||||
| return 4; | |||||
| switch (pass_type) { | |||||
| case SCE_PASS_Z: | |||||
| case SCE_PASS_AO: | |||||
| case SCE_PASS_MIST: { | |||||
| return 1; | |||||
| } | |||||
| case SCE_PASS_UV: { | |||||
| return 2; | |||||
| } | |||||
| case SCE_PASS_COMBINED: | |||||
| case SCE_PASS_SHADOW: | |||||
| case SCE_PASS_NORMAL: | |||||
| case SCE_PASS_VECTOR: | |||||
| case SCE_PASS_INDEXOB: /* XXX double check */ | |||||
| case SCE_PASS_RAYHITS: /* XXX double check */ | |||||
| case SCE_PASS_EMIT: | |||||
| case SCE_PASS_ENVIRONMENT: | |||||
| case SCE_PASS_INDEXMA: | |||||
| case SCE_PASS_DIFFUSE_DIRECT: | |||||
| case SCE_PASS_DIFFUSE_INDIRECT: | |||||
| case SCE_PASS_DIFFUSE_COLOR: | |||||
| case SCE_PASS_GLOSSY_DIRECT: | |||||
| case SCE_PASS_GLOSSY_INDIRECT: | |||||
| case SCE_PASS_GLOSSY_COLOR: | |||||
| case SCE_PASS_TRANSM_DIRECT: | |||||
| case SCE_PASS_TRANSM_INDIRECT: | |||||
| case SCE_PASS_TRANSM_COLOR: | |||||
| case SCE_PASS_SUBSURFACE_DIRECT: | |||||
| case SCE_PASS_SUBSURFACE_INDIRECT: | |||||
| case SCE_PASS_SUBSURFACE_COLOR: | |||||
| default: { | |||||
| return 3; | |||||
| } | |||||
| } | |||||
| } | } | ||||