void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool, int thread, bool convert_to_linear, struct ColorSpace *colorspace) { float co[3] = {u, v, 0.0f}; int hasrgb; float intensity; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; rgba[2] = intensity; rgba[3] = 1.0f; } if (convert_to_linear) IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace); linearrgb_to_srgb_v3_v3(rgba, rgba); CLAMP(rgba[0], 0.0f, 1.0f); CLAMP(rgba[1], 0.0f, 1.0f); CLAMP(rgba[2], 0.0f, 1.0f); CLAMP(rgba[3], 0.0f, 1.0f); }
/* Brush Sampling */ void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) { MTex *mtex= &brush->mtex; if (mtex && mtex->tex) { float co[3], tin, tr, tg, tb, ta; int hasrgb; const int radius= brush_size(brush); co[0]= xy[0]/radius; co[1]= xy[1]/radius; co[2]= 0.0f; hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); if (hasrgb) { rgba[0]= tr; rgba[1]= tg; rgba[2]= tb; rgba[3]= ta; } else { rgba[0]= tin; rgba[1]= tin; rgba[2]= tin; rgba[3]= 1.0f; } } else if (rgba) rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f; }
/* Brush Sampling */ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) { MTex *mtex = &brush->mtex; if (mtex && mtex->tex) { float co[3], tin, tr, tg, tb, ta; int hasrgb; const int radius = BKE_brush_size_get(scene, brush); co[0] = xy[0] / radius; co[1] = xy[1] / radius; co[2] = 0.0f; hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); if (hasrgb) { rgba[0] = tr; rgba[1] = tg; rgba[2] = tb; rgba[3] = ta; } else { rgba[0] = tin; rgba[1] = tin; rgba[2] = tin; rgba[3] = 1.0f; } } else { rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; } }
/* TODO: should probably be unified with BrushPainter stuff? */ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_secondary) { unsigned int *texcache = NULL; MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex; float intensity; float rgba[4]; int ix, iy; int side = half_side * 2; if (mtex->tex) { float x, y, step = 2.0 / side, co[3]; texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); /* do normalized canonical view coords for texture */ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { co[0] = x; co[1] = y; co[2] = 0.0f; /* This is copied from displace modifier code */ /* TODO(sergey): brush are always caching with CM enabled for now. */ externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); ((char *)texcache)[(iy * side + ix) * 4] = ((char *)texcache)[(iy * side + ix) * 4 + 1] = ((char *)texcache)[(iy * side + ix) * 4 + 2] = (( char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(intensity * 255.0f); } } } return texcache; }
float paint_get_tex_pixel(MTex *mtex, float u, float v, struct ImagePool *pool, int thread) { float intensity, rgba[4]; float co[3] = {u, v, 0.0f}; externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); return intensity; }
void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool) { float co[3] = {u, v, 0.0f}; int hasrgb; float intensity; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool); if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; rgba[2] = intensity; rgba[3] = 1.0f; } CLAMP(rgba[0], 0.0f, 1.0f); CLAMP(rgba[1], 0.0f, 1.0f); CLAMP(rgba[2], 0.0f, 1.0f); CLAMP(rgba[3], 0.0f, 1.0f); }
float BKE_brush_sample_masktex(const Scene *scene, Brush *br, const float point[2], const int thread, struct ImagePool *pool) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &br->mask_mtex; float rgba[4], intensity; if (!mtex->tex) { return 1.0f; } if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x, y; float co[3]; x = point_2d[0] - br->mask_stencil_pos[0]; y = point_2d[1] - br->mask_stencil_pos[1]; if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) { zero_v4(rgba); return 0.0f; } x /= (br->mask_stencil_dimension[0]); y /= (br->mask_stencil_dimension[1]); co[0] = x; co[1] = y; co[2] = 0.0f; externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x = 0.0f, y = 0.0f; /* Quite warnings */ float invradius = 1.0f; /* Quite warnings */ float co[3]; if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { /* keep coordinates relative to mouse */ rotation += ups->brush_rotation_sec; x = point_2d[0] - ups->mask_tex_mouse[0]; y = point_2d[1] - ups->mask_tex_mouse[1]; /* use pressure adjusted size for fixed mode */ invradius = 1.0f / ups->pixel_radius; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { /* leave the coordinates relative to the screen */ /* use unadjusted size for tiled mode */ invradius = 1.0f / BKE_brush_size_get(scene, br); x = point_2d[0]; y = point_2d[1]; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { rotation += ups->brush_rotation_sec; /* these contain a random coordinate */ x = point_2d[0] - ups->mask_tex_mouse[0]; y = point_2d[1] - ups->mask_tex_mouse[1]; invradius = 1.0f / ups->pixel_radius; } x *= invradius; y *= invradius; /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to * atan2, sqrtf, sin, and cos. */ if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } co[0] = x; co[1] = y; co[2] = 0.0f; externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } CLAMP(intensity, 0.0f, 1.0f); switch (br->mask_pressure) { case BRUSH_MASK_PRESSURE_CUTOFF: intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f; break; case BRUSH_MASK_PRESSURE_RAMP: intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value); break; default: break; } return intensity; }
/* Generic texture sampler for 3D painting systems. point has to be either in * region space mouse coordinates, or 3d world coordinates for 3D mapping. * * rgba outputs straight alpha. */ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, const float point[3], float rgba[4], const int thread, struct ImagePool *pool) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &br->mtex; float intensity = 1.0; bool hasrgb = false; if (!mtex->tex) { intensity = 1; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { /* Get strength by feeding the vertex * location directly into a texture */ hasrgb = externtex(mtex, point, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x, y; float co[3]; x = point_2d[0] - br->stencil_pos[0]; y = point_2d[1] - br->stencil_pos[1]; if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) { zero_v4(rgba); return 0.0f; } x /= (br->stencil_dimension[0]); y /= (br->stencil_dimension[1]); co[0] = x; co[1] = y; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x = 0.0f, y = 0.0f; /* Quite warnings */ float invradius = 1.0f; /* Quite warnings */ float co[3]; if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { /* keep coordinates relative to mouse */ rotation += ups->brush_rotation; x = point_2d[0] - ups->tex_mouse[0]; y = point_2d[1] - ups->tex_mouse[1]; /* use pressure adjusted size for fixed mode */ invradius = 1.0f / ups->pixel_radius; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { /* leave the coordinates relative to the screen */ /* use unadjusted size for tiled mode */ invradius = 1.0f / BKE_brush_size_get(scene, br); x = point_2d[0]; y = point_2d[1]; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { rotation += ups->brush_rotation; /* these contain a random coordinate */ x = point_2d[0] - ups->tex_mouse[0]; y = point_2d[1] - ups->tex_mouse[1]; invradius = 1.0f / ups->pixel_radius; } x *= invradius; y *= invradius; /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to * atan2, sqrtf, sin, and cos. */ if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } co[0] = x; co[1] = y; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } intensity += br->texture_sample_bias; if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; rgba[2] = intensity; rgba[3] = 1.0f; } /* For consistency, sampling always returns color in linear space */ else if (ups->do_linear_conversion) { IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, ups->colorspace); } return intensity; }
HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], const float *orco, float hasize, float vectsize, int seed) { const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; HaloRen *har; MTex *mtex; float tin, tr, tg, tb, ta; float xn, yn, zn, texvec[3], hoco[4], hoco1[4]; if (hasize==0.0f) return NULL; projectverto(vec, re->winmat, hoco); if (hoco[3]==0.0f) return NULL; if (vec1) { projectverto(vec1, re->winmat, hoco1); if (hoco1[3]==0.0f) return NULL; } har= RE_findOrAddHalo(obr, obr->tothalo++); copy_v3_v3(har->co, vec); har->hasize= hasize; /* actual projectvert is done in function project_renderdata() because of parts/border/pano */ /* we do it here for sorting of halos */ zn= hoco[3]; har->xs= 0.5f*re->winx*(hoco[0]/zn); har->ys= 0.5f*re->winy*(hoco[1]/zn); har->zs= 0x7FFFFF*(hoco[2]/zn); har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); /* halovect */ if (vec1) { har->type |= HA_VECT; xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f; else zn = atan2f(yn, xn); har->sin = sinf(zn); har->cos = cosf(zn); zn= len_v3v3(vec1, vec); har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; sub_v3_v3v3(har->no, vec, vec1); normalize_v3(har->no); } if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; har->alfa= ma->alpha; har->r= ma->r; har->g= ma->g; har->b= ma->b; har->add= (255.0f*ma->add); har->mat= ma; har->hard= ma->har; har->seed= seed % 256; if (ma->mode & MA_STAR) har->starpoints= ma->starc; if (ma->mode & MA_HALO_LINES) har->linec= ma->linec; if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; if (ma->mtex[0]) { if (ma->mode & MA_HALOTEX) { har->tex = 1; } else if (har->mat->septex & (1 << 0)) { /* only 1 level textures */ } else { mtex= ma->mtex[0]; copy_v3_v3(texvec, vec); if (mtex->texco & TEXCO_NORM) { ; } else if (mtex->texco & TEXCO_OBJECT) { /* texvec[0]+= imatbase->ivec[0]; */ /* texvec[1]+= imatbase->ivec[1]; */ /* texvec[2]+= imatbase->ivec[2]; */ /* mul_m3_v3(imatbase->imat, texvec); */ } else { if (orco) { copy_v3_v3(texvec, orco); } } externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image); yn= tin*mtex->colfac; //zn= tin*mtex->alphafac; if (mtex->mapto & MAP_COL) { zn= 1.0f-yn; har->r= (yn*tr+ zn*ma->r); har->g= (yn*tg+ zn*ma->g); har->b= (yn*tb+ zn*ma->b); } if (mtex->texco & TEXCO_UV) { har->alfa= tin; } if (mtex->mapto & MAP_ALPHA) har->alfa= tin; } } har->pool = re->pool; har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; return har; }
HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, const float vec[3], const float vec1[3], const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3]) { const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; HaloRen *har; MTex *mtex; float tin, tr, tg, tb, ta; float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3]; int i, hasrgb; if (hasize==0.0f) return NULL; projectverto(vec, re->winmat, hoco); if (hoco[3]==0.0f) return NULL; if (vec1) { projectverto(vec1, re->winmat, hoco1); if (hoco1[3]==0.0f) return NULL; } har= RE_findOrAddHalo(obr, obr->tothalo++); copy_v3_v3(har->co, vec); har->hasize= hasize; /* actual projectvert is done in function project_renderdata() because of parts/border/pano */ /* we do it here for sorting of halos */ zn= hoco[3]; har->xs= 0.5f*re->winx*(hoco[0]/zn); har->ys= 0.5f*re->winy*(hoco[1]/zn); har->zs= 0x7FFFFF*(hoco[2]/zn); har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); /* halovect */ if (vec1) { har->type |= HA_VECT; xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0; else zn = atan2f(yn, xn); har->sin = sinf(zn); har->cos = cosf(zn); zn= len_v3v3(vec1, vec)*0.5f; har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; sub_v3_v3v3(har->no, vec, vec1); normalize_v3(har->no); } if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; har->alfa= ma->alpha; har->r= ma->r; har->g= ma->g; har->b= ma->b; har->add= (255.0f*ma->add); har->mat= ma; har->hard= ma->har; har->seed= seed % 256; if (ma->mode & MA_STAR) har->starpoints= ma->starc; if (ma->mode & MA_HALO_LINES) har->linec= ma->linec; if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; if ((ma->mode & MA_HALOTEX) && ma->mtex[0]) har->tex= 1; for (i=0; i<MAX_MTEX; i++) if (ma->mtex[i] && (ma->septex & (1<<i))==0) { mtex= ma->mtex[i]; copy_v3_v3(texvec, vec); if (mtex->texco & TEXCO_NORM) { ; } else if (mtex->texco & TEXCO_OBJECT) { if (mtex->object) mul_m4_v3(mtex->object->imat_ren, texvec); } else if (mtex->texco & TEXCO_GLOB) { copy_v3_v3(texvec, vec); } else if (mtex->texco & TEXCO_UV && uvco) { int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname); if (uv_index<0) uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE); uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE); texvec[0]=2.0f*uvco[2*uv_index]-1.0f; texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f; texvec[2]=0.0f; } else if (mtex->texco & TEXCO_PARTICLE) { /* particle coordinates in range [0, 1] */ texvec[0] = 2.f * pa_co[0] - 1.f; texvec[1] = 2.f * pa_co[1] - 1.f; texvec[2] = pa_co[2]; } else if (orco) { copy_v3_v3(texvec, orco); } hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image); //yn= tin*mtex->colfac; //zn= tin*mtex->alphafac; if (mtex->mapto & MAP_COL) { tex[0]=tr; tex[1]=tg; tex[2]=tb; out[0]=har->r; out[1]=har->g; out[2]=har->b; texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype); // zn= 1.0-yn; //har->r= (yn*tr+ zn*ma->r); //har->g= (yn*tg+ zn*ma->g); //har->b= (yn*tb+ zn*ma->b); har->r= in[0]; har->g= in[1]; har->b= in[2]; } /* alpha returned, so let's use it instead of intensity */ if (hasrgb) tin = ta; if (mtex->mapto & MAP_ALPHA) har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype); if (mtex->mapto & MAP_HAR) har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype); if (mtex->mapto & MAP_RAYMIRR) har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype); if (mtex->mapto & MAP_TRANSLU) { float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype); CLAMP(add, 0.f, 1.f); har->add = 255.0f*add; } /* now what on earth is this good for?? */ //if (mtex->texco & 16) { // har->alfa= tin; //} } har->pool = re->pool; har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; return har; }