Fix #72011: Visible artifacts after baking normals with bevel shader
Pull Request: https://projects.blender.org/blender/blender/pulls/106988
This commit is contained in:
committed by
Lukas Stockner
parent
c502d3ac53
commit
c431b69a8a
@@ -169,6 +169,39 @@ static void bake_update_image(ScrArea *area, Image *image)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Bias almost-flat normals in tangent space to be flat to avoid artifacts in byte textures.
|
||||
* For some types of normal baking, especially bevels, you can end up with a small amount
|
||||
* of noise in the result. Since the border between pixel value 127 and 128 is exactly 0.5,
|
||||
* the tiniest amount of deviation will flip between those two, and increasing samples won't
|
||||
* help - you always end up with visible "dents" in the resulting normal map.
|
||||
* Therefore, this function snaps values that are less than half a quantization level away
|
||||
* from 0.5 to 0.5, so that they consistently become pixel value 128.
|
||||
* This only makes sense for byte textures of course, and is not used when baking to float
|
||||
* textures (which includes 16-bit formats). Also, it's only applied to the first two channels,
|
||||
* since on flat surfaces the Z channel will be close enough to 1.0 to reliably end up on 255.
|
||||
*/
|
||||
void bias_tangent_normal_pixels(float *rect,
|
||||
int channels,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
BLI_assert(channels >= 3);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
float *pixels = rect + ((size_t)stride) * y * channels;
|
||||
for (int x = 0; x < width; x++, pixels += channels) {
|
||||
if (fabsf(pixels[0] - 0.5f) < 1.0f / 255.0f) {
|
||||
pixels[0] = 0.5f + 1e-5f;
|
||||
}
|
||||
if (fabsf(pixels[1] - 0.5f) < 1.0f / 255.0f) {
|
||||
pixels[1] = 0.5f + 1e-5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool write_internal_bake_pixels(Image *image,
|
||||
const int image_tile_number,
|
||||
BakePixel pixel_array[],
|
||||
@@ -179,6 +212,7 @@ static bool write_internal_bake_pixels(Image *image,
|
||||
const char margin_type,
|
||||
const bool is_clear,
|
||||
const bool is_noncolor,
|
||||
const bool is_tangent_normal,
|
||||
Mesh const *mesh_eval,
|
||||
char const *uv_layer,
|
||||
const float uv_offset[2])
|
||||
@@ -224,6 +258,10 @@ static bool write_internal_bake_pixels(Image *image,
|
||||
buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
|
||||
}
|
||||
}
|
||||
else if (!is_float && is_tangent_normal) {
|
||||
/* bias neutral values when converting tangent-space normal maps to byte textures */
|
||||
bias_tangent_normal_pixels(buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x);
|
||||
}
|
||||
|
||||
/* populates the ImBuf */
|
||||
if (is_clear) {
|
||||
@@ -328,6 +366,7 @@ static bool write_external_bake_pixels(const char *filepath,
|
||||
const int margin_type,
|
||||
ImageFormatData const *im_format,
|
||||
const bool is_noncolor,
|
||||
const bool is_tangent_normal,
|
||||
Mesh const *mesh_eval,
|
||||
char const *uv_layer,
|
||||
const float uv_offset[2])
|
||||
@@ -366,6 +405,10 @@ static bool write_external_bake_pixels(const char *filepath,
|
||||
IMB_colormanagement_transform(
|
||||
buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
|
||||
}
|
||||
else if (is_tangent_normal) {
|
||||
/* bias neutral values when converting tangent-space normal maps to byte textures */
|
||||
bias_tangent_normal_pixels(buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x);
|
||||
}
|
||||
|
||||
IMB_buffer_byte_from_float((uchar *)ibuf->rect,
|
||||
buffer,
|
||||
@@ -789,6 +832,7 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr,
|
||||
Mesh *mesh_eval)
|
||||
{
|
||||
bool all_ok = true;
|
||||
const bool is_tangent_normal = (bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT);
|
||||
|
||||
for (int i = 0; i < targets->images_num; i++) {
|
||||
BakeImage *bk_image = &targets->images[i];
|
||||
@@ -803,6 +847,7 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr,
|
||||
bkr->margin_type,
|
||||
bkr->is_clear,
|
||||
targets->is_noncolor,
|
||||
is_tangent_normal,
|
||||
mesh_eval,
|
||||
bkr->uv_layer,
|
||||
bk_image->uv_offset);
|
||||
@@ -869,6 +914,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
|
||||
ReportList *reports)
|
||||
{
|
||||
bool all_ok = true;
|
||||
const bool is_tangent_normal = (bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT);
|
||||
|
||||
for (int i = 0; i < targets->images_num; i++) {
|
||||
BakeImage *bk_image = &targets->images[i];
|
||||
@@ -922,6 +968,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
|
||||
bkr->margin_type,
|
||||
&bake->im_format,
|
||||
targets->is_noncolor,
|
||||
is_tangent_normal,
|
||||
mesh_eval,
|
||||
bkr->uv_layer,
|
||||
bk_image->uv_offset);
|
||||
|
||||
Reference in New Issue
Block a user