diff options
Diffstat (limited to 'source/blender/render/intern/source/render_texture.c')
-rw-r--r-- | source/blender/render/intern/source/render_texture.c | 2510 |
1 files changed, 18 insertions, 2492 deletions
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 929fc3cc9c3..79d13ecab5b 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -65,23 +65,11 @@ #include "MEM_guardedalloc.h" -#include "envmap.h" -#include "pointdensity.h" -#include "voxeldata.h" #include "render_types.h" -#include "shading.h" #include "texture.h" -#include "texture_ocean.h" - -#include "renderdatabase.h" /* needed for UV */ #include "RE_render_ext.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include "RE_shader_ext.h" static RNG_THREAD_ARRAY *random_tex_array; @@ -97,63 +85,6 @@ void RE_texture_rng_exit(void) } -static void init_render_texture(Render *re, Tex *tex) -{ - /* imap test */ - if (tex->ima && BKE_image_is_animated(tex->ima)) { - BKE_image_user_frame_calc(&tex->iuser, re ? re->r.cfra : 0, re ? re->flag & R_SEC_FIELD:0); - } - - else if (tex->type==TEX_ENVMAP) { - /* just in case */ - tex->imaflag |= TEX_INTERPOL | TEX_MIPMAP; - tex->extend= TEX_CLIP; - - if (tex->env) { - if (tex->env->type==ENV_PLANE) - tex->extend= TEX_EXTEND; - - /* only free envmap when rendermode was set to render envmaps, for previewrender */ - if (G.is_rendering && re) { - if (re->r.mode & R_ENVMAP) - if (tex->env->stype==ENV_ANIM) - BKE_texture_envmap_free_data(tex->env); - } - } - } - - if (tex->nodetree && tex->use_nodes) { - ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */ - } -} - -/* ------------------------------------------------------------------------- */ - -void init_render_textures(Render *re) -{ - Tex *tex; - - tex= re->main->tex.first; - while (tex) { - if (tex->id.us) init_render_texture(re, tex); - tex= tex->id.next; - } -} - -static void end_render_texture(Tex *tex) -{ - if (tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata) - ntreeTexEndExecTree(tex->nodetree->execdata); -} - -void end_render_textures(Render *re) -{ - Tex *tex; - for (tex= re->main->tex.first; tex; tex= tex->id.next) - if (tex->id.us) - end_render_texture(tex); -} - /* ------------------------------------------------------------------------- */ @@ -755,7 +686,6 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1 else { copy_v3_v3(nor, n); } - mul_mat3_m4_v3(R.viewinv, nor); x1 = fabsf(nor[0]); y1 = fabsf(nor[1]); @@ -781,115 +711,20 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1 /* ------------------------------------------------------------------------- */ -/* mtex argument only for projection switches */ -static int cubemap( - const MTex *mtex, VlakRen *vlr, const float n[3], float x, float y, float z, float *adr1, float *adr2) -{ - int proj[4]={0, ME_PROJXY, ME_PROJXZ, ME_PROJYZ}, ret= 0; - - if (vlr) { - int index; - - /* Mesh vertices have such flags, for others we calculate it once based on orco */ - if ((vlr->puno & (ME_PROJXY|ME_PROJXZ|ME_PROJYZ))==0) { - /* test for v1, vlr can be faked for baking */ - if (vlr->v1 && vlr->v1->orco) { - float nor[3]; - normal_tri_v3(nor, vlr->v1->orco, vlr->v2->orco, vlr->v3->orco); - - if (fabsf(nor[0]) < fabsf(nor[2]) && fabsf(nor[1]) < fabsf(nor[2])) vlr->puno |= ME_PROJXY; - else if (fabsf(nor[0]) < fabsf(nor[1]) && fabsf(nor[2]) < fabsf(nor[1])) vlr->puno |= ME_PROJXZ; - else vlr->puno |= ME_PROJYZ; - } - else return cubemap_glob(n, x, y, z, adr1, adr2); - } - - if (mtex) { - /* the mtex->proj{xyz} have type char. maybe this should be wider? */ - /* casting to int ensures that the index type is right. */ - index = (int) mtex->projx; - proj[index]= ME_PROJXY; - - index = (int) mtex->projy; - proj[index]= ME_PROJXZ; - - index = (int) mtex->projz; - proj[index]= ME_PROJYZ; - } - - if (vlr->puno & proj[1]) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (y + 1.0f) / 2.0f; - } - else if (vlr->puno & proj[2]) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 1; - } - else { - *adr1 = (y + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 2; - } - } - else { - return cubemap_glob(n, x, y, z, adr1, adr2); - } - - return ret; -} - -/* ------------------------------------------------------------------------- */ - -static int cubemap_ob(Object *ob, const float n[3], float x, float y, float z, float *adr1, float *adr2) -{ - float x1, y1, z1, nor[3]; - int ret; - - if (n==NULL) return 0; - - copy_v3_v3(nor, n); - if (ob) mul_mat3_m4_v3(ob->imat, nor); - - x1 = fabsf(nor[0]); - y1 = fabsf(nor[1]); - z1 = fabsf(nor[2]); - - if (z1>=x1 && z1>=y1) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (y + 1.0f) / 2.0f; - ret= 0; - } - else if (y1>=x1 && y1>=z1) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 1; - } - else { - *adr1 = (y + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 2; - } - return ret; -} - /* ------------------------------------------------------------------------- */ static void do_2d_mapping( - const MTex *mtex, float texvec[3], VlakRen *vlr, const float n[3], float dxt[3], float dyt[3]) + const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3]) { Tex *tex; - Object *ob= NULL; float fx, fy, fac1, area[8]; - int ok, proj, areaflag= 0, wrap, texco; + int ok, proj, areaflag= 0, wrap; /* mtex variables localized, only cubemap doesn't cooperate yet... */ wrap= mtex->mapping; tex= mtex->tex; - ob= mtex->object; - texco= mtex->texco; - if (R.osa==0) { + if (!(dxt && dyt)) { if (wrap==MTEX_FLAT) { fx = (texvec[0] + 1.0f) / 2.0f; @@ -898,9 +733,7 @@ static void do_2d_mapping( else if (wrap == MTEX_TUBE) map_to_tube( &fx, &fy, texvec[0], texvec[1], texvec[2]); else if (wrap == MTEX_SPHERE) map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]); else { - if (texco == TEXCO_OBJECT) cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else if (texco == TEXCO_GLOB) cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); } /* repeat */ @@ -996,9 +829,7 @@ static void do_2d_mapping( } else { - if (texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else proj = cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); if (proj==1) { SWAP(float, dxt[1], dxt[2]); @@ -1124,8 +955,9 @@ static int multitex(Tex *tex, texres->talpha = false; /* is set when image texture returns alpha (considered premul) */ if (use_nodes && tex->use_nodes && tex->nodetree) { + const float cfra = 1.0f; /* This was only set for Blender Internal render before. */ retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread, - tex, which_output, R.r.cfra, texnode_preview, NULL, NULL); + tex, which_output, cfra, texnode_preview, NULL); } else { switch (tex->type) { @@ -1160,9 +992,6 @@ static int multitex(Tex *tex, BKE_image_tag_time(tex->ima); } break; - case TEX_ENVMAP: - retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool, skip_load_image); - break; case TEX_MUSGRAVE: /* newnoise: musgrave types */ @@ -1205,15 +1034,6 @@ static int multitex(Tex *tex, retval = mg_distNoiseTex(tex, tmpvec, texres); break; - case TEX_POINTDENSITY: - retval = pointdensitytex(tex, texvec, texres); - break; - case TEX_VOXELDATA: - retval = voxeldatatex(tex, texvec, texres); - break; - case TEX_OCEAN: - retval = ocean_texture(tex, texvec, texres); - break; } } @@ -1238,7 +1058,6 @@ static int multitex_nodes_intern(Tex *tex, TexResult *texres, const short thread, short which_output, - ShadeInput *shi, MTex *mtex, struct ImagePool *pool, const bool scene_color_manage, @@ -1259,7 +1078,7 @@ static int multitex_nodes_intern(Tex *tex, if (mtex) { /* we have mtex, use it for 2d mapping images only */ - do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, dxt, dyt); rgbnor = multitex(tex, texvec, dxt, dyt, @@ -1272,7 +1091,7 @@ static int multitex_nodes_intern(Tex *tex, texnode_preview, use_nodes); - if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { + if (mtex->mapto & (MAP_COL)) { ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ @@ -1307,7 +1126,7 @@ static int multitex_nodes_intern(Tex *tex, zero_v3(dyt_l); } - do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l); + do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l); rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, @@ -1357,41 +1176,15 @@ static int multitex_nodes_intern(Tex *tex, * Use it from render pipeline only! */ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, - const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool) + const short thread, short which_output, MTex *mtex, struct ImagePool *pool) { return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, - thread, which_output, shi, mtex, pool, R.scene_color_manage, - (R.r.scemode & R_NO_IMAGE_LOAD) != 0, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0, + thread, which_output, mtex, pool, true, + false, + false, true); } -/* this is called for surface shading */ -static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image) -{ - Tex *tex = mtex->tex; - /* TODO(sergey): Texture preview should become an argument? */ - if (tex->use_nodes && tex->nodetree) { - /* stupid exception here .. but we have to pass shi and mtex to - * textures nodes for 2d mapping and color management for images */ - return ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, shi->osatex, shi->thread, - tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex); - } - else { - return multitex(mtex->tex, - texvec, - dxt, dyt, - shi->osatex, - texres, - shi->thread, - mtex->which_output, - pool, - skip_load_image, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0, - true); - } -} - /* Warning, if the texres's values are not declared zero, check the return value to be sure * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell * @@ -1414,7 +1207,7 @@ int multitex_ext(Tex *tex, texres, thread, 0, - NULL, NULL, + NULL, pool, scene_color_manage, skip_load_image, @@ -1435,7 +1228,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image texres, 0, 0, - NULL, NULL, + NULL, pool, scene_color_manage, skip_load_image, @@ -1652,1949 +1445,6 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen return in; } -static void texco_mapping(ShadeInput *shi, Tex *tex, MTex *mtex, - const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3]) -{ - /* new: first swap coords, then map, then trans/scale */ - if (tex->type == TEX_IMAGE) { - /* placement */ - texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f; - texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f; - texvec[2] = mtex->projz ? co[mtex->projz - 1] : 0.f; - - if (shi->osatex) { - if (mtex->projx) { - dxt[0] = dx[mtex->projx - 1]; - dyt[0] = dy[mtex->projx - 1]; - } - else dxt[0] = dyt[0] = 0.f; - if (mtex->projy) { - dxt[1] = dx[mtex->projy - 1]; - dyt[1] = dy[mtex->projy - 1]; - } - else dxt[1] = dyt[1] = 0.f; - if (mtex->projz) { - dxt[2] = dx[mtex->projz - 1]; - dyt[2] = dy[mtex->projz - 1]; - } - else dxt[2] = dyt[2] = 0.f; - } - do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); - - /* translate and scale */ - texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f; - texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f; - if (shi->osatex) { - dxt[0] = mtex->size[0] * dxt[0]; - dxt[1] = mtex->size[1] * dxt[1]; - dyt[0] = mtex->size[0] * dyt[0]; - dyt[1] = mtex->size[1] * dyt[1]; - } - - /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */ - /* TXF: bug was here, only modify texvec when repeat mode set, old code affected other modes too. - * New texfilters solve mirroring differently so that it also works correctly when - * textures are scaled (sizeXYZ) as well as repeated. See also modification in do_2d_mapping(). - * (since currently only done in osa mode, results will look incorrect without osa TODO) */ - if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_XMIR)) { - if (tex->texfilter == TXF_BOX) - texvec[0] -= floorf(texvec[0]); /* this line equivalent to old code, same below */ - else if (texvec[0] < 0.f || texvec[0] > 1.f) { - const float tx = 0.5f*texvec[0]; - texvec[0] = 2.f*(tx - floorf(tx)); - if (texvec[0] > 1.f) texvec[0] = 2.f - texvec[0]; - } - } - if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_YMIR)) { - if (tex->texfilter == TXF_BOX) - texvec[1] -= floorf(texvec[1]); - else if (texvec[1] < 0.f || texvec[1] > 1.f) { - const float ty = 0.5f*texvec[1]; - texvec[1] = 2.f*(ty - floorf(ty)); - if (texvec[1] > 1.f) texvec[1] = 2.f - texvec[1]; - } - } - - } - else { /* procedural */ - /* placement */ - texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]); - texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]); - texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]); - - if (shi->osatex) { - if (mtex->projx) { - dxt[0] = mtex->size[0]*dx[mtex->projx - 1]; - dyt[0] = mtex->size[0]*dy[mtex->projx - 1]; - } - else dxt[0] = dyt[0] = 0.f; - if (mtex->projy) { - dxt[1] = mtex->size[1]*dx[mtex->projy - 1]; - dyt[1] = mtex->size[1]*dy[mtex->projy - 1]; - } - else dxt[1] = dyt[1] = 0.f; - if (mtex->projz) { - dxt[2] = mtex->size[2]*dx[mtex->projz - 1]; - dyt[2] = mtex->size[2]*dy[mtex->projz - 1]; - } - else dxt[2]= dyt[2] = 0.f; - } - - if (mtex->tex->type == TEX_ENVMAP) { - EnvMap *env = tex->env; - if (!env->object) { - // env->object is a view point for envmap rendering - // if it's not set, return the result depending on the world_space_shading flag - if (BKE_scene_use_world_space_shading(R.scene)) { - mul_mat3_m4_v3(R.viewinv, texvec); - if (shi->osatex) { - mul_mat3_m4_v3(R.viewinv, dxt); - mul_mat3_m4_v3(R.viewinv, dyt); - } - } - } - } - } -} - -/* Bump code from 2.5 development cycle, has a number of bugs, but here for compatibility */ - -typedef struct CompatibleBump { - float nu[3], nv[3], nn[3]; - float dudnu, dudnv, dvdnu, dvdnv; - bool nunvdone; -} CompatibleBump; - -static void compatible_bump_init(CompatibleBump *compat_bump) -{ - memset(compat_bump, 0, sizeof(*compat_bump)); - - compat_bump->dudnu = 1.0f; - compat_bump->dvdnv = 1.0f; -} - -static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, int i) -{ - /* uvmapping only, calculation of normal tangent u/v partial derivatives - * (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct, - * nu/nv in ShadeInput and this calculation should then move to shadeinput.c, - * shade_input_set_shade_texco() func.) */ - - /* NOTE: test for shi->obr->ob here, - * since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. */ - - /* NOTE: shi->v1 is NULL when called from displace_render_vert, - * assigning verts in this case is not trivial because the shi quad face side is not know. */ - if ((mtex->texflag & MTEX_COMPAT_BUMP) && shi->obr && shi->obr->ob && shi->v1) { - if (mtex->mapto & (MAP_NORM|MAP_WARP) && !((mtex->tex->type==TEX_IMAGE) && (mtex->tex->imaflag & TEX_NORMALMAP))) { - MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0); - int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; - - vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); - - /* compute ortho basis around normal */ - if (!compat_bump->nunvdone) { - /* render normal is negated */ - compat_bump->nn[0] = -shi->vn[0]; - compat_bump->nn[1] = -shi->vn[1]; - compat_bump->nn[2] = -shi->vn[2]; - ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn); - compat_bump->nunvdone = true; - } - - if (tf) { - const float *uv1 = tf->uv[j1], *uv2 = tf->uv[j2], *uv3 = tf->uv[j3]; - const float an[3] = {fabsf(compat_bump->nn[0]), fabsf(compat_bump->nn[1]), fabsf(compat_bump->nn[2])}; - const int a1 = (an[0] > an[1] && an[0] > an[2]) ? 1 : 0; - const int a2 = (an[2] > an[0] && an[2] > an[1]) ? 1 : 2; - const float dp1_a1 = shi->v1->co[a1] - shi->v3->co[a1]; - const float dp1_a2 = shi->v1->co[a2] - shi->v3->co[a2]; - const float dp2_a1 = shi->v2->co[a1] - shi->v3->co[a1]; - const float dp2_a2 = shi->v2->co[a2] - shi->v3->co[a2]; - const float du1 = uv1[0] - uv3[0], du2 = uv2[0] - uv3[0]; - const float dv1 = uv1[1] - uv3[1], dv2 = uv2[1] - uv3[1]; - const float dpdu_a1 = dv2*dp1_a1 - dv1*dp2_a1; - const float dpdu_a2 = dv2*dp1_a2 - dv1*dp2_a2; - const float dpdv_a1 = du1*dp2_a1 - du2*dp1_a1; - const float dpdv_a2 = du1*dp2_a2 - du2*dp1_a2; - float d = dpdu_a1*dpdv_a2 - dpdv_a1*dpdu_a2; - float uvd = du1*dv2 - dv1*du2; - - if (uvd == 0.f) uvd = 1e-5f; - if (d == 0.f) d = 1e-5f; - d = uvd / d; - - compat_bump->dudnu = (dpdv_a2*compat_bump->nu[a1] - dpdv_a1*compat_bump->nu[a2])*d; - compat_bump->dvdnu = (dpdu_a1*compat_bump->nu[a2] - dpdu_a2*compat_bump->nu[a1])*d; - compat_bump->dudnv = (dpdv_a2*compat_bump->nv[a1] - dpdv_a1*compat_bump->nv[a2])*d; - compat_bump->dvdnv = (dpdu_a1*compat_bump->nv[a2] - dpdu_a2*compat_bump->nv[a1])*d; - } - } - } -} - -static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, - float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3], - struct ImagePool *pool, const bool skip_load_image) -{ - TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ - float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); - const float bf = -0.04f*Tnor*mtex->norfac; - int rgbnor; - /* disable internal bump eval */ - float *nvec = texres->nor; - texres->nor = NULL; - /* du & dv estimates, constant value defaults */ - du = dv = 0.01f; - - /* compute ortho basis around normal */ - if (!compat_bump->nunvdone) { - /* render normal is negated */ - negate_v3_v3(compat_bump->nn, shi->vn); - ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn); - compat_bump->nunvdone = true; - } - - /* two methods, either constant based on main image resolution, - * (which also works without osa, though of course not always good (or even very bad) results), - * or based on tex derivative max values (osa only). Not sure which is best... */ - - if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { - /* in case we have no proper derivatives, fall back to - * computing du/dv it based on image size */ - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); - if (ibuf) { - du = 1.f/(float)ibuf->x; - dv = 1.f/(float)ibuf->y; - } - BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); - } - else if (shi->osatex) { - /* we have derivatives, can compute proper du/dv */ - if (tex->type == TEX_IMAGE) { /* 2d image, use u & v max. of dx/dy 2d vecs */ - const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])}; - const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])}; - du = MAX2(adx[0], ady[0]); - dv = MAX2(adx[1], ady[1]); - } - else { /* 3d procedural, estimate from all dx/dy elems */ - const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])}; - const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])}; - du = max_fff(adx[0], adx[1], adx[2]); - dv = max_fff(ady[0], ady[1], ady[2]); - } - } - - /* center, main return value */ - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image); - cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin; - - if (mtex->texco == TEXCO_UV) { - /* for the uv case, use the same value for both du/dv, - * since individually scaling the normal derivatives makes them useless... */ - du = min_ff(du, dv); - idu = (du < 1e-5f) ? bf : (bf/du); - - /* +u val */ - tco[0] = co[0] + compat_bump->dudnu*du; - tco[1] = co[1] + compat_bump->dvdnu*du; - tco[2] = 0.f; - texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image); - ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - - /* +v val */ - tco[0] = co[0] + compat_bump->dudnv*du; - tco[1] = co[1] + compat_bump->dvdnv*du; - tco[2] = 0.f; - texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image); - vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - } - else { - float tu[3], tv[3]; - - copy_v3_v3(tu, compat_bump->nu); - copy_v3_v3(tv, compat_bump->nv); - - idu = (du < 1e-5f) ? bf : (bf/du); - idv = (dv < 1e-5f) ? bf : (bf/dv); - - if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) { - mul_mat3_m4_v3(shi->obr->ob->imat_ren, tu); - mul_mat3_m4_v3(shi->obr->ob->imat_ren, tv); - normalize_v3(tu); - normalize_v3(tv); - } - else if (mtex->texco == TEXCO_GLOB) { - mul_mat3_m4_v3(R.viewinv, tu); - mul_mat3_m4_v3(R.viewinv, tv); - } - else if (mtex->texco == TEXCO_OBJECT && mtex->object) { - mul_mat3_m4_v3(mtex->object->imat_ren, tu); - mul_mat3_m4_v3(mtex->object->imat_ren, tv); - normalize_v3(tu); - normalize_v3(tv); - } - - /* +u val */ - tco[0] = co[0] + tu[0]*du; - tco[1] = co[1] + tu[1]*du; - tco[2] = co[2] + tu[2]*du; - texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image); - ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - - /* +v val */ - tco[0] = co[0] + tv[0]*dv; - tco[1] = co[1] + tv[1]*dv; - tco[2] = co[2] + tv[2]*dv; - texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image); - vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - } - - /* bumped normal */ - compat_bump->nu[0] += ud*compat_bump->nn[0]; - compat_bump->nu[1] += ud*compat_bump->nn[1]; - compat_bump->nu[2] += ud*compat_bump->nn[2]; - compat_bump->nv[0] += vd*compat_bump->nn[0]; - compat_bump->nv[1] += vd*compat_bump->nn[1]; - compat_bump->nv[2] += vd*compat_bump->nn[2]; - cross_v3_v3v3(nvec, compat_bump->nu, compat_bump->nv); - - nvec[0] = -nvec[0]; - nvec[1] = -nvec[1]; - nvec[2] = -nvec[2]; - texres->nor = nvec; - - rgbnor |= TEX_NOR; - return rgbnor; -} - -/* Improved bump code from later in 2.5 development cycle */ - -typedef struct NTapBump { - int init_done; - int iPrevBumpSpace; /* 0: uninitialized, 1: objectspace, 2: texturespace, 4: viewspace */ - /* bumpmapping */ - float vNorg[3]; /* backup copy of shi->vn */ - float vNacc[3]; /* original surface normal minus the surface gradient of every bump map which is encountered */ - float vR1[3], vR2[3]; /* cross products (sigma_y, original_normal), (original_normal, sigma_x) */ - float sgn_det; /* sign of the determinant of the matrix {sigma_x, sigma_y, original_normal} */ - float fPrevMagnitude; /* copy of previous magnitude, used for multiple bumps in different spaces */ -} NTapBump; - -static void ntap_bump_init(NTapBump *ntap_bump) -{ - memset(ntap_bump, 0, sizeof(*ntap_bump)); -} - -static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, - float Tnor, const float co[3], const float dx[3], const float dy[3], - float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool, - const bool skip_load_image) -{ - TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ - - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); - - /* The negate on Hscale is done because the - * normal in the renderer points inward which corresponds - * to inverting the bump map. The normals are generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. */ - float Hscale = -Tnor*mtex->norfac; - - int dimx=512, dimy=512; - const int imag_tspace_dimension_x = 1024; /* only used for texture space variant */ - float aspect = 1.0f; - - /* 2 channels for 2D texture and 3 for 3D textures. */ - const int nr_channels = (mtex->texco == TEXCO_UV)? 2 : 3; - int c, rgbnor, iBumpSpace; - float dHdx, dHdy; - int found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP); - - /* disable internal bump eval in sampler, save pointer */ - float *nvec = texres->nor; - texres->nor = NULL; - - if (found_deriv_map==0) { - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) - Hscale *= 13.0f; /* appears to be a sensible default value */ - } - else - Hscale *= 0.1f; /* factor 0.1 proved to look like the previous bump code */ - } - - if ( !ntap_bump->init_done ) { - copy_v3_v3(ntap_bump->vNacc, shi->vn); - copy_v3_v3(ntap_bump->vNorg, shi->vn); - ntap_bump->fPrevMagnitude = 1.0f; - ntap_bump->iPrevBumpSpace = 0; - - ntap_bump->init_done = true; - } - - /* resolve image dimensions */ - if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) { - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); - if (ibuf) { - dimx = ibuf->x; - dimy = ibuf->y; - aspect = ((float) dimy) / dimx; - } - BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); - } - - if (found_deriv_map) { - float dBdu, dBdv, auto_bump = 1.0f; - float s = 1; /* negate this if flipped texture coordinate */ - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image); - - if (shi->obr->ob->derivedFinal) { - auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale; - } - - { - float fVirtDim = sqrtf(fabsf((float) (dimx*dimy)*mtex->size[0]*mtex->size[1])); - auto_bump /= MAX2(fVirtDim, FLT_EPSILON); - } - - /* this variant using a derivative map is described here - * http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html */ - dBdu = auto_bump*Hscale*dimx*(2*texres->tr-1); - dBdv = auto_bump*Hscale*dimy*(2*texres->tg-1); - - dHdx = dBdu*dxt[0] + s * dBdv*dxt[1]; - dHdy = dBdu*dyt[0] + s * dBdv*dyt[1]; - } - else if (!(mtex->texflag & MTEX_5TAP_BUMP)) { - /* compute height derivatives with respect to output image pixel coordinates x and y */ - float STll[3], STlr[3], STul[3]; - float Hll, Hlr, Hul; - - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - - for (c=0; c<nr_channels; c++) { - /* dx contains the derivatives (du/dx, dv/dx) - * dy contains the derivatives (du/dy, dv/dy) */ - STll[c] = texvec[c]; - STlr[c] = texvec[c]+dxt[c]; - STul[c] = texvec[c]+dyt[c]; - } - - /* clear unused derivatives */ - for (c=nr_channels; c<3; c++) { - STll[c] = 0.0f; - STlr[c] = 0.0f; - STul[c] = 0.0f; - } - - /* use texres for the center sample, set rgbnor */ - rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image); - Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; - - /* use ttexr for the other 2 taps */ - multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image); - Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - - multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image); - Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - - dHdx = Hscale*(Hlr - Hll); - dHdy = Hscale*(Hul - Hll); - } - else { - /* same as above, but doing 5 taps, increasing quality at cost of speed */ - float STc[3], STl[3], STr[3], STd[3], STu[3]; - float /* Hc, */ /* UNUSED */ Hl, Hr, Hd, Hu; - - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - - for (c=0; c<nr_channels; c++) { - STc[c] = texvec[c]; - STl[c] = texvec[c] - 0.5f*dxt[c]; - STr[c] = texvec[c] + 0.5f*dxt[c]; - STd[c] = texvec[c] - 0.5f*dyt[c]; - STu[c] = texvec[c] + 0.5f*dyt[c]; - } - - /* clear unused derivatives */ - for (c=nr_channels; c<3; c++) { - STc[c] = 0.0f; - STl[c] = 0.0f; - STr[c] = 0.0f; - STd[c] = 0.0f; - STu[c] = 0.0f; - } - - /* use texres for the center sample, set rgbnor */ - rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image); - /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */ - - /* use ttexr for the other taps */ - multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image); - Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image); - Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image); - Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image); - Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; - - dHdx = Hscale*(Hr - Hl); - dHdy = Hscale*(Hu - Hd); - } - - /* restore pointer */ - texres->nor = nvec; - - /* replaced newbump with code based on listing 1 and 2 of - * [Mik10] Mikkelsen M. S.: Bump Mapping Unparameterized Surfaces on the GPU. - * -> http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf */ - - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) - iBumpSpace = 1; - else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) - iBumpSpace = 2; - else - iBumpSpace = 4; /* ViewSpace */ - - if ( ntap_bump->iPrevBumpSpace != iBumpSpace ) { - - /* initialize normal perturbation vectors */ - int xyz; - float fDet, abs_fDet, fMagnitude; - /* object2view and inverted matrix */ - float obj2view[3][3], view2obj[3][3], tmp[4][4]; - /* local copies of derivatives and normal */ - float dPdx[3], dPdy[3], vN[3]; - copy_v3_v3(dPdx, shi->dxco); - copy_v3_v3(dPdy, shi->dyco); - copy_v3_v3(vN, ntap_bump->vNorg); - - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) { - /* TODO: these calculations happen for every pixel! - * -> move to shi->obi */ - mul_m4_m4m4(tmp, R.viewmat, shi->obr->ob->obmat); - copy_m3_m4(obj2view, tmp); /* use only upper left 3x3 matrix */ - invert_m3_m3(view2obj, obj2view); - - /* generate the surface derivatives in object space */ - mul_m3_v3(view2obj, dPdx); - mul_m3_v3(view2obj, dPdy); - /* generate the unit normal in object space */ - mul_transposed_m3_v3(obj2view, vN); - normalize_v3(vN); - } - - cross_v3_v3v3(ntap_bump->vR1, dPdy, vN); - cross_v3_v3v3(ntap_bump->vR2, vN, dPdx); - fDet = dot_v3v3(dPdx, ntap_bump->vR1); - ntap_bump->sgn_det = (fDet < 0)? -1.0f: 1.0f; - abs_fDet = ntap_bump->sgn_det * fDet; - - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) { - /* crazy hack solution that gives results similar to normal mapping - part 1 */ - normalize_v3(ntap_bump->vR1); - normalize_v3(ntap_bump->vR2); - abs_fDet = 1.0f; - } - } - - fMagnitude = abs_fDet; - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) { - /* pre do transform of texres->nor by the inverse transposed of obj2view */ - mul_transposed_m3_v3(view2obj, vN); - mul_transposed_m3_v3(view2obj, ntap_bump->vR1); - mul_transposed_m3_v3(view2obj, ntap_bump->vR2); - - fMagnitude *= len_v3(vN); - } - - if (ntap_bump->fPrevMagnitude > 0.0f) - for (xyz=0; xyz<3; xyz++) - ntap_bump->vNacc[xyz] *= fMagnitude / ntap_bump->fPrevMagnitude; - - ntap_bump->fPrevMagnitude = fMagnitude; - ntap_bump->iPrevBumpSpace = iBumpSpace; - } - - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) { - /* crazy hack solution that gives results similar to normal mapping - part 2 */ - float vec[2]; - const float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x; - - vec[0] = imag_tspace_dimension_x*dxt[0]; - vec[1] = imag_tspace_dimension_y*dxt[1]; - dHdx *= 1.0f/len_v2(vec); - vec[0] = imag_tspace_dimension_x*dyt[0]; - vec[1] = imag_tspace_dimension_y*dyt[1]; - dHdy *= 1.0f/len_v2(vec); - } - } - - /* subtract the surface gradient from vNacc */ - for (c=0; c<3; c++) { - float vSurfGrad_compi = ntap_bump->sgn_det * (dHdx * ntap_bump->vR1[c] + dHdy * ntap_bump->vR2[c]); - ntap_bump->vNacc[c] -= vSurfGrad_compi; - texres->nor[c] = ntap_bump->vNacc[c]; /* copy */ - } - - rgbnor |= TEX_NOR; - return rgbnor; -} - -void do_material_tex(ShadeInput *shi, Render *re) -{ - const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0; - CompatibleBump compat_bump; - NTapBump ntap_bump; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float *co = NULL, *dx = NULL, *dy = NULL; - float fact, facm, factt, facmm, stencilTin=1.0; - float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0; - int tex_nr, rgbnor= 0; - bool warp_done = false, use_compat_bump = false, use_ntap_bump = false; - bool found_nmapping = false, found_deriv_map = false; - bool iFirstTimeNMap = true; - - compatible_bump_init(&compat_bump); - ntap_bump_init(&ntap_bump); - - if (re->r.scemode & R_NO_TEX) return; - /* here: test flag if there's a tex (todo) */ - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - - /* separate tex switching */ - if (shi->mat->septex & (1<<tex_nr)) continue; - - if (shi->mat->mtex[tex_nr]) { - mtex= shi->mat->mtex[tex_nr]; - - tex= mtex->tex; - if (tex == NULL) continue; - - found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP); - use_compat_bump= (mtex->texflag & MTEX_COMPAT_BUMP) != 0; - use_ntap_bump = ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP))!=0 || found_deriv_map!=0) ? true : false; - - /* XXX texture node trees don't work for this yet */ - if (tex->nodetree && tex->use_nodes) { - use_compat_bump = false; - use_ntap_bump = false; - } - - /* case displacement mapping */ - if (shi->osatex == 0 && use_ntap_bump) { - use_ntap_bump = false; - use_compat_bump = true; - } - - /* case ocean */ - if (tex->type == TEX_OCEAN) { - use_ntap_bump = false; - use_compat_bump = false; - } - - /* which coords */ - if (mtex->texco==TEXCO_ORCO) { - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - co= shi->duplilo; dx= dxt; dy= dyt; - dxt[0]= dxt[1]= dxt[2]= 0.0f; - dyt[0]= dyt[1]= dyt[2]= 0.0f; - } - else { - co= shi->lo; dx= shi->dxlo; dy= shi->dylo; - } - } - else if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - co= tempvec; - dx= dxt; - dy= dyt; - copy_v3_v3(tempvec, shi->co); - if (mtex->texflag & MTEX_OB_DUPLI_ORIG) - if (shi->obi && shi->obi->duplitexmat) - mul_m4_v3(shi->obi->duplitexmat, tempvec); - mul_m4_v3(ob->imat_ren, tempvec); - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxco); - copy_v3_v3(dyt, shi->dyco); - mul_mat3_m4_v3(ob->imat_ren, dxt); - mul_mat3_m4_v3(ob->imat_ren, dyt); - } - } - else { - /* if object doesn't exist, do not use orcos (not initialized) */ - co= shi->co; - dx= shi->dxco; dy= shi->dyco; - } - } - else if (mtex->texco==TEXCO_REFL) { - calc_R_ref(shi); - co= shi->ref; dx= shi->dxref; dy= shi->dyref; - } - else if (mtex->texco==TEXCO_NORM) { - co= shi->orn; dx= shi->dxno; dy= shi->dyno; - } - else if (mtex->texco==TEXCO_TANGENT) { - co= shi->tang; dx= shi->dxno; dy= shi->dyno; - } - else if (mtex->texco==TEXCO_GLOB) { - co= shi->gl; dx= shi->dxgl; dy= shi->dygl; - } - else if (mtex->texco==TEXCO_UV) { - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - co= shi->dupliuv; dx= dxt; dy= dyt; - dxt[0]= dxt[1]= dxt[2]= 0.0f; - dyt[0]= dyt[1]= dyt[2]= 0.0f; - } - else { - ShadeInputUV *suv= &shi->uv[shi->actuv]; - int i = shi->actuv; - - if (mtex->uvname[0] != 0) { - for (i = 0; i < shi->totuv; i++) { - if (STREQ(shi->uv[i].name, mtex->uvname)) { - suv= &shi->uv[i]; - break; - } - } - } - - co= suv->uv; - dx= suv->dxuv; - dy= suv->dyuv; - - compatible_bump_uv_derivs(&compat_bump, shi, mtex, i); - } - } - else if (mtex->texco==TEXCO_WINDOW) { - co= shi->winco; dx= shi->dxwin; dy= shi->dywin; - } - else if (mtex->texco==TEXCO_STRAND) { - co= tempvec; dx= dxt; dy= dyt; - co[0]= shi->strandco; - co[1]= co[2]= 0.0f; - dx[0]= shi->dxstrand; - dx[1]= dx[2]= 0.0f; - dy[0]= shi->dystrand; - dy[1]= dy[2]= 0.0f; - } - else if (mtex->texco==TEXCO_STRESS) { - co= tempvec; dx= dxt; dy= dyt; - co[0]= shi->stress; - co[1]= co[2]= 0.0f; - dx[0]= 0.0f; - dx[1]= dx[2]= 0.0f; - dy[0]= 0.0f; - dy[1]= dy[2]= 0.0f; - } - else { - continue; /* can happen when texco defines disappear and it renders old files */ - } - - /* the pointer defines if bumping happens */ - if (mtex->mapto & (MAP_NORM|MAP_WARP)) { - texres.nor= norvec; - norvec[0]= norvec[1]= norvec[2]= 0.0; - } - else texres.nor= NULL; - - if (warp_done) { - add_v3_v3v3(tempvec, co, warpvec); - co= tempvec; - } - - /* XXX texture node trees don't work for this yet */ - if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) { - if (use_compat_bump) { - rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt, - re->pool, skip_load_image); - } - else if (use_ntap_bump) { - rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt, - re->pool, skip_load_image); - } - else { - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image); - } - } - else { - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image); - } - - /* texture output */ - - if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgbnor -= TEX_RGB; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgbnor & TEX_RGB) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgbnor & TEX_RGB) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - Tnor*= stencilTin; - } - - if (texres.nor) { - if ((rgbnor & TEX_NOR)==0) { - /* make our own normal */ - if (rgbnor & TEX_RGB) { - copy_v3_v3(texres.nor, &texres.tr); - } - else { - float co_nor= 0.5f * cosf(texres.tin - 0.5f); - float si = 0.5f * sinf(texres.tin - 0.5f); - float f1, f2; - - f1= shi->vn[0]; - f2= shi->vn[1]; - texres.nor[0]= f1*co_nor+f2*si; - f1= shi->vn[1]; - f2= shi->vn[2]; - texres.nor[1]= f1*co_nor+f2*si; - texres.nor[2]= f2*co_nor-f1*si; - } - } - /* warping, local space */ - if (mtex->mapto & MAP_WARP) { - float *warpnor= texres.nor, warpnor_[3]; - - if (use_ntap_bump) { - copy_v3_v3(warpnor_, texres.nor); - warpnor= warpnor_; - normalize_v3(warpnor_); - } - warpvec[0]= mtex->warpfac*warpnor[0]; - warpvec[1]= mtex->warpfac*warpnor[1]; - warpvec[2]= mtex->warpfac*warpnor[2]; - warp_done = true; - } -#if 0 - if (mtex->texflag & MTEX_VIEWSPACE) { - /* rotate to global coords */ - if (mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) { - if (shi->vlr && shi->obr && shi->obr->ob) { - float len= normalize_v3(texres.nor); - /* can be optimized... (ton) */ - mul_mat3_m4_v3(shi->obr->ob->obmat, texres.nor); - mul_mat3_m4_v3(re->viewmat, texres.nor); - normalize_v3_length(texres.nor, len); - } - } - } -#endif - } - - /* mapping */ - if (mtex->mapto & (MAP_COL | MAP_COLSPEC | MAP_COLMIR)) { - float tcol[3]; - - /* stencil maps on the texture control slider, not texture intensity value */ - copy_v3_v3(tcol, &texres.tr); - - if ((rgbnor & TEX_RGB) == 0) { - copy_v3_v3(tcol, &mtex->r); - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin = stencilTin; - } - else { - texres.tin = texres.ta; - } - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf != NULL && - ibuf->rect_float == NULL && - (rgbnor & TEX_RGB) && - R.scene_color_manage) - { - IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - } - - BKE_image_pool_release_ibuf(ima, ibuf, re->pool); - } - - if (mtex->mapto & MAP_COL) { - float colfac= mtex->colfac*stencilTin; - texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype); - } - if (mtex->mapto & MAP_COLSPEC) { - float colspecfac= mtex->colspecfac*stencilTin; - texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colspecfac, mtex->blendtype); - } - if (mtex->mapto & MAP_COLMIR) { - float mirrfac= mtex->mirrfac*stencilTin; - - /* exception for envmap only */ - if (tex->type==TEX_ENVMAP && mtex->blendtype==MTEX_BLEND) { - fact= texres.tin*mirrfac; - facm= 1.0f- fact; - shi->refcol[0]= fact + facm*shi->refcol[0]; - shi->refcol[1]= fact*tcol[0] + facm*shi->refcol[1]; - shi->refcol[2]= fact*tcol[1] + facm*shi->refcol[2]; - shi->refcol[3]= fact*tcol[2] + facm*shi->refcol[3]; - } - else { - texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, mirrfac, mtex->blendtype); - } - } - } - if ( (mtex->mapto & MAP_NORM) ) { - if (texres.nor) { - float norfac= mtex->norfac; - - /* we need to code blending modes for normals too once.. now 1 exception hardcoded */ - - if ((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) { - - found_nmapping = 1; - - /* qdn: for normalmaps, to invert the normalmap vector, - * it is better to negate x & y instead of subtracting the vector as was done before */ - if (norfac < 0.0f) { - texres.nor[0] = -texres.nor[0]; - texres.nor[1] = -texres.nor[1]; - } - fact = Tnor*fabsf(norfac); - if (fact>1.f) fact = 1.f; - facm = 1.f-fact; - if (mtex->normapspace == MTEX_NSPACE_TANGENT) { - /* qdn: tangent space */ - float B[3], tv[3]; - const float *no = iFirstTimeNMap ? shi->nmapnorm : shi->vn; - iFirstTimeNMap = false; - cross_v3_v3v3(B, no, shi->nmaptang); /* bitangent */ - mul_v3_fl(B, shi->nmaptang[3]); - /* transform norvec from tangent space to object surface in camera space */ - tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*no[0]; - tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*no[1]; - tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*no[2]; - shi->vn[0]= facm*no[0] + fact*tv[0]; - shi->vn[1]= facm*no[1] + fact*tv[1]; - shi->vn[2]= facm*no[2] + fact*tv[2]; - } - else { - float nor[3]; - - copy_v3_v3(nor, texres.nor); - - if (mtex->normapspace == MTEX_NSPACE_CAMERA) { - /* pass */ - } - else if (mtex->normapspace == MTEX_NSPACE_WORLD) { - mul_mat3_m4_v3(re->viewmat, nor); - } - else if (mtex->normapspace == MTEX_NSPACE_OBJECT) { - if (shi->obr && shi->obr->ob) - mul_mat3_m4_v3(shi->obr->ob->obmat, nor); - mul_mat3_m4_v3(re->viewmat, nor); - } - - normalize_v3(nor); - - /* qdn: worldspace */ - shi->vn[0]= facm*shi->vn[0] + fact*nor[0]; - shi->vn[1]= facm*shi->vn[1] + fact*nor[1]; - shi->vn[2]= facm*shi->vn[2] + fact*nor[2]; - } - } - else { - /* XXX texture node trees don't work for this yet */ - if (use_compat_bump || use_ntap_bump) { - shi->vn[0] = texres.nor[0]; - shi->vn[1] = texres.nor[1]; - shi->vn[2] = texres.nor[2]; - } - else { - float nor[3], dot; - - if (shi->mat->mode & MA_TANGENT_V) { - shi->tang[0]+= Tnor*norfac*texres.nor[0]; - shi->tang[1]+= Tnor*norfac*texres.nor[1]; - shi->tang[2]+= Tnor*norfac*texres.nor[2]; - } - - /* prevent bump to become negative normal */ - nor[0]= Tnor*norfac*texres.nor[0]; - nor[1]= Tnor*norfac*texres.nor[1]; - nor[2]= Tnor*norfac*texres.nor[2]; - - dot= 0.5f + 0.5f * dot_v3v3(nor, shi->vn); - - shi->vn[0]+= dot*nor[0]; - shi->vn[1]+= dot*nor[1]; - shi->vn[2]+= dot*nor[2]; - } - } - normalize_v3(shi->vn); - - /* this makes sure the bump is passed on to the next texture */ - shi->orn[0]= -shi->vn[0]; - shi->orn[1]= -shi->vn[1]; - shi->orn[2]= -shi->vn[2]; - } - } - - if ( mtex->mapto & MAP_DISPLACE ) { - /* Now that most textures offer both Nor and Intensity, allow */ - /* both to work, and let user select with slider. */ - if (texres.nor) { - float norfac= mtex->norfac; - - shi->displace[0]+= 0.2f*Tnor*norfac*texres.nor[0]; - shi->displace[1]+= 0.2f*Tnor*norfac*texres.nor[1]; - shi->displace[2]+= 0.2f*Tnor*norfac*texres.nor[2]; - } - - if (rgbnor & TEX_RGB) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; - - if (mtex->blendtype==MTEX_BLEND) { - shi->displace[0]= factt*shi->vn[0] + facmm*shi->displace[0]; - shi->displace[1]= factt*shi->vn[1] + facmm*shi->displace[1]; - shi->displace[2]= factt*shi->vn[2] + facmm*shi->displace[2]; - } - else if (mtex->blendtype==MTEX_MUL) { - shi->displace[0]*= factt*shi->vn[0]; - shi->displace[1]*= factt*shi->vn[1]; - shi->displace[2]*= factt*shi->vn[2]; - } - else { /* add or sub */ - if (mtex->blendtype==MTEX_SUB) factt= -factt; - shi->displace[0]+= factt*shi->vn[0]; - shi->displace[1]+= factt*shi->vn[1]; - shi->displace[2]+= factt*shi->vn[2]; - } - } - - if (mtex->mapto & MAP_VARS) { - /* stencil maps on the texture control slider, not texture intensity value */ - - if (rgbnor & TEX_RGB) { - if (texres.talpha) texres.tin = texres.ta; - else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - if (mtex->mapto & MAP_REF) { - float difffac= mtex->difffac*stencilTin; - - shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, difffac, mtex->blendtype); - if (shi->refl<0.0f) shi->refl= 0.0f; - } - if (mtex->mapto & MAP_SPEC) { - float specfac= mtex->specfac*stencilTin; - - shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, specfac, mtex->blendtype); - if (shi->spec<0.0f) shi->spec= 0.0f; - } - if (mtex->mapto & MAP_EMIT) { - float emitfac= mtex->emitfac*stencilTin; - - shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, emitfac, mtex->blendtype); - if (shi->emit<0.0f) shi->emit= 0.0f; - } - if (mtex->mapto & MAP_ALPHA) { - float alphafac= mtex->alphafac*stencilTin; - - shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, alphafac, mtex->blendtype); - if (shi->alpha<0.0f) shi->alpha= 0.0f; - else if (shi->alpha>1.0f) shi->alpha= 1.0f; - } - if (mtex->mapto & MAP_HAR) { - float har; /* have to map to 0-1 */ - float hardfac= mtex->hardfac*stencilTin; - - har= ((float)shi->har)/128.0f; - har= 128.0f*texture_value_blend(mtex->def_var, har, texres.tin, hardfac, mtex->blendtype); - - if (har<1.0f) shi->har= 1; - else if (har>511) shi->har= 511; - else shi->har= (int)har; - } - if (mtex->mapto & MAP_RAYMIRR) { - float raymirrfac= mtex->raymirrfac*stencilTin; - - shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, raymirrfac, mtex->blendtype); - if (shi->ray_mirror<0.0f) shi->ray_mirror= 0.0f; - else if (shi->ray_mirror>1.0f) shi->ray_mirror= 1.0f; - } - if (mtex->mapto & MAP_TRANSLU) { - float translfac= mtex->translfac*stencilTin; - - shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, translfac, mtex->blendtype); - if (shi->translucency<0.0f) shi->translucency= 0.0f; - else if (shi->translucency>1.0f) shi->translucency= 1.0f; - } - if (mtex->mapto & MAP_AMB) { - float ambfac= mtex->ambfac*stencilTin; - - shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, ambfac, mtex->blendtype); - if (shi->amb<0.0f) shi->amb= 0.0f; - else if (shi->amb>1.0f) shi->amb= 1.0f; - - shi->ambr= shi->amb*re->wrld.ambr; - shi->ambg= shi->amb*re->wrld.ambg; - shi->ambb= shi->amb*re->wrld.ambb; - } - } - } - } - if ((use_compat_bump || use_ntap_bump || found_nmapping) && (shi->mat->mode & MA_TANGENT_V) != 0) { - const float fnegdot = -dot_v3v3(shi->vn, shi->tang); - /* apply Gram-Schmidt projection */ - madd_v3_v3fl(shi->tang, shi->vn, fnegdot); - normalize_v3(shi->tang); - } -} - - -void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_r[3], float *val, Render *re) -{ - const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; - const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - int tex_nr, rgbnor= 0; - float co[3], texvec[3]; - float fact, stencilTin=1.0; - - if (re->r.scemode & R_NO_TEX) return; - /* here: test flag if there's a tex (todo) */ - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - /* separate tex switching */ - if (shi->mat->septex & (1<<tex_nr)) continue; - - if (shi->mat->mtex[tex_nr]) { - mtex= shi->mat->mtex[tex_nr]; - tex= mtex->tex; - if (tex == NULL) continue; - - /* only process if this texture is mapped - * to one that we're interested in */ - if (!(mtex->mapto & mapto_flag)) continue; - - /* which coords */ - if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - copy_v3_v3(co, xyz); - if (mtex->texflag & MTEX_OB_DUPLI_ORIG) { - if (shi->obi && shi->obi->duplitexmat) - mul_m4_v3(shi->obi->duplitexmat, co); - } - mul_m4_v3(ob->imat_ren, co); - - if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { - /* use bb vec[0] as min and bb vec[6] as max */ - co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; - co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; - co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; - } - } - } - /* not really orco, but 'local' */ - else if (mtex->texco==TEXCO_ORCO) { - - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - copy_v3_v3(co, shi->duplilo); - } - else { - Object *ob= shi->obi->ob; - copy_v3_v3(co, xyz); - mul_m4_v3(ob->imat_ren, co); - - if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { - /* use bb vec[0] as min and bb vec[6] as max */ - co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; - co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; - co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; - } - } - } - else if (mtex->texco==TEXCO_GLOB) { - copy_v3_v3(co, xyz); - mul_m4_v3(re->viewinv, co); - } - else { - continue; /* can happen when texco defines disappear and it renders old files */ - } - - texres.nor= NULL; - - if (tex->type == TEX_IMAGE) { - continue; /* not supported yet */ - //do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - } - else { - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - } - - rgbnor = multitex(tex, - texvec, - NULL, NULL, - 0, - &texres, - shi->thread, - mtex->which_output, - re->pool, - skip_load_image, - texnode_preview, - true); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ - - /* texture output */ - - if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgbnor -= TEX_RGB; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgbnor & TEX_RGB) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgbnor & TEX_RGB) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - - - if ((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) { - float tcol[3]; - - /* stencil maps on the texture control slider, not texture intensity value */ - - if ((rgbnor & TEX_RGB) == 0) { - copy_v3_v3(tcol, &mtex->r); - } - else if (mtex->mapto & MAP_DENSITY) { - copy_v3_v3(tcol, &texres.tr); - if (texres.talpha) { - texres.tin = stencilTin; - } - } - else { - copy_v3_v3(tcol, &texres.tr); - if (texres.talpha) { - texres.tin= texres.ta; - } - } - - /* used for emit */ - if ((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) { - float colemitfac= mtex->colemitfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, colemitfac, mtex->blendtype); - } - - if ((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) { - float colreflfac= mtex->colreflfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, colreflfac, mtex->blendtype); - } - - if ((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) { - float coltransfac= mtex->coltransfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, coltransfac, mtex->blendtype); - } - } - - if ((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) { - /* stencil maps on the texture control slider, not texture intensity value */ - - /* convert RGB to intensity if intensity info isn't provided */ - if (rgbnor & TEX_RGB) { - if (texres.talpha) texres.tin = texres.ta; - else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) { - float emitfac= mtex->emitfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, emitfac, mtex->blendtype); - if (*val<0.0f) *val= 0.0f; - } - if ((mapto_flag & MAP_DENSITY) && (mtex->mapto & MAP_DENSITY)) { - float densfac= mtex->densfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, densfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - if ((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) { - float scatterfac= mtex->scatterfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, scatterfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - if ((mapto_flag & MAP_REFLECTION) && (mtex->mapto & MAP_REFLECTION)) { - float reflfac= mtex->reflfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, reflfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - } - } - } -} - - -/* ------------------------------------------------------------------------- */ - -void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) -{ - const bool skip_load_image = har->skip_load_image; - const bool texnode_preview = har->texnode_preview; - MTex *mtex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float texvec[3], dxt[3], dyt[3], fact, facm, dx; - int rgb, osatex; - - if (R.r.scemode & R_NO_TEX) return; - - mtex= har->mat->mtex[0]; - if (har->mat->septex & (1<<0)) return; - if (mtex->tex==NULL) return; - - /* no normal mapping */ - texres.nor= NULL; - - texvec[0]= xn/har->rad; - texvec[1]= yn/har->rad; - texvec[2]= 0.0; - - osatex= (har->mat->texco & TEXCO_OSA); - - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - if (osatex) { - - dx= 1.0f/har->rad; - - if (mtex->projx) { - dxt[0]= mtex->size[0]*dx; - dyt[0]= mtex->size[0]*dx; - } - else dxt[0]= dyt[0]= 0.0; - - if (mtex->projy) { - dxt[1]= mtex->size[1]*dx; - dyt[1]= mtex->size[1]*dx; - } - else dxt[1]= dyt[1]= 0.0; - - if (mtex->projz) { - dxt[2]= 0.0; - dyt[2]= 0.0; - } - else dxt[2]= dyt[2]= 0.0; - - } - - if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - - rgb = multitex(mtex->tex, - texvec, - dxt, dyt, - osatex, - &texres, - 0, - mtex->which_output, - har->pool, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - - /* mapping */ - if (mtex->mapto & MAP_COL) { - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin= 1.0; - } - else texres.tin= texres.ta; - - /* inverse gamma correction */ - if (mtex->tex->type==TEX_IMAGE) { - Image *ima = mtex->tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, har->pool); - } - - fact= texres.tin*mtex->colfac; - facm= 1.0f-fact; - - if (mtex->blendtype==MTEX_MUL) { - facm= 1.0f-mtex->colfac; - } - - if (mtex->blendtype==MTEX_SUB) fact= -fact; - - if (mtex->blendtype==MTEX_BLEND) { - col_r[0]= (fact*texres.tr + facm*har->r); - col_r[1]= (fact*texres.tg + facm*har->g); - col_r[2]= (fact*texres.tb + facm*har->b); - } - else if (mtex->blendtype==MTEX_MUL) { - col_r[0]= (facm+fact*texres.tr)*har->r; - col_r[1]= (facm+fact*texres.tg)*har->g; - col_r[2]= (facm+fact*texres.tb)*har->b; - } - else { - col_r[0]= (fact*texres.tr + har->r); - col_r[1]= (fact*texres.tg + har->g); - col_r[2]= (fact*texres.tb + har->b); - - CLAMP(col_r[0], 0.0f, 1.0f); - CLAMP(col_r[1], 0.0f, 1.0f); - CLAMP(col_r[2], 0.0f, 1.0f); - } - } - if (mtex->mapto & MAP_ALPHA) { - if (rgb) { - if (texres.talpha) { - texres.tin = texres.ta; - } - else { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - } - - col_r[3]*= texres.tin; - } -} - -/* ------------------------------------------------------------------------- */ - -/* hor and zen are RGB vectors, blend is 1 float, should all be initialized */ -void do_sky_tex( - const float rco[3], const float view[3], const float lo[3], const float dxyview[2], - float hor[3], float zen[3], float *blend, int skyflag, short thread) -{ - const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0; - const bool texnode_preview = (R.r.scemode & R_TEXNODE_PREVIEW) != 0; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float fact, stencilTin=1.0; - float tempvec[3], texvec[3], dxt[3], dyt[3]; - int tex_nr, rgb= 0; - - if (R.r.scemode & R_NO_TEX) return; - /* todo: add flag to test if there's a tex */ - texres.nor= NULL; - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - if (R.wrld.mtex[tex_nr]) { - const float *co; - - mtex= R.wrld.mtex[tex_nr]; - - tex= mtex->tex; - if (tex == NULL) continue; - /* if (mtex->mapto==0) continue; */ - - /* which coords */ - co= lo; - - /* dxt dyt just from 1 value */ - if (dxyview) { - dxt[0]= dxt[1]= dxt[2]= dxyview[0]; - dyt[0]= dyt[1]= dyt[2]= dxyview[1]; - } - else { - dxt[0]= dxt[1]= dxt[2]= 0.0; - dyt[0]= dyt[1]= dyt[2]= 0.0; - } - - /* Grab the mapping settings for this texture */ - switch (mtex->texco) { - case TEXCO_ANGMAP: - /* only works with texture being "real" */ - /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less than -1.0 */ - if (lo[0] || lo[1]) { /* check for zero case [#24807] */ - fact= (1.0f/(float)M_PI)*saacos(lo[2])/(sqrtf(lo[0]*lo[0] + lo[1]*lo[1])); - tempvec[0]= lo[0]*fact; - tempvec[1]= lo[1]*fact; - tempvec[2]= 0.0; - } - else { - /* this value has no angle, the vector is directly along the view. - * avoid divide by zero and use a dummy value. */ - tempvec[0]= 1.0f; - tempvec[1]= 0.0; - tempvec[2]= 0.0; - } - co= tempvec; - break; - - case TEXCO_H_SPHEREMAP: - case TEXCO_H_TUBEMAP: - if (skyflag & WO_ZENUP) { - if (mtex->texco==TEXCO_H_TUBEMAP) map_to_tube( tempvec, tempvec+1, lo[0], lo[2], lo[1]); - else map_to_sphere(tempvec, tempvec+1, lo[0], lo[2], lo[1]); - /* tube/spheremap maps for outside view, not inside */ - tempvec[0]= 1.0f-tempvec[0]; - /* only top half */ - tempvec[1]= 2.0f*tempvec[1]-1.0f; - tempvec[2]= 0.0; - /* and correction for do_2d_mapping */ - tempvec[0]= 2.0f*tempvec[0]-1.0f; - tempvec[1]= 2.0f*tempvec[1]-1.0f; - co= tempvec; - } - else { - /* potentially dangerous... check with multitex! */ - continue; - } - break; - case TEXCO_EQUIRECTMAP: - tempvec[0]= -atan2f(lo[2], lo[0]) / (float)M_PI; - tempvec[1]= atan2f(lo[1], hypot(lo[0], lo[2])) / (float)M_PI_2; - tempvec[2]= 0.0f; - co= tempvec; - break; - case TEXCO_OBJECT: - if (mtex->object) { - copy_v3_v3(tempvec, lo); - mul_m4_v3(mtex->object->imat_ren, tempvec); - co= tempvec; - } - break; - - case TEXCO_GLOB: - if (rco) { - copy_v3_v3(tempvec, rco); - mul_m4_v3(R.viewinv, tempvec); - co= tempvec; - } - else - co= lo; - -// copy_v3_v3(shi->dxgl, shi->dxco); -// mul_m3_v3(R.imat, shi->dxco); -// copy_v3_v3(shi->dygl, shi->dyco); -// mul_m3_v3(R.imat, shi->dyco); - break; - case TEXCO_VIEW: - co = view; - break; - } - - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - /* texture */ - if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - - rgb = multitex(mtex->tex, - texvec, - dxt, dyt, - R.osa, - &texres, - thread, - mtex->which_output, - R.pool, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgb) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - if (rgb) texres.ta *= stencilTin; - else texres.tin*= stencilTin; - } - - /* color mapping */ - if (mtex->mapto & (WOMAP_HORIZ+WOMAP_ZENUP+WOMAP_ZENDOWN)) { - float tcol[3]; - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else texres.tin= texres.ta; - - tcol[0]= texres.tr; tcol[1]= texres.tg; tcol[2]= texres.tb; - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, R.pool); - } - - if (mtex->mapto & WOMAP_HORIZ) { - texture_rgb_blend(hor, tcol, hor, texres.tin, mtex->colfac, mtex->blendtype); - } - if (mtex->mapto & (WOMAP_ZENUP+WOMAP_ZENDOWN)) { - float zenfac = 0.0f; - - if (R.wrld.skytype & WO_SKYREAL) { - if ((skyflag & WO_ZENUP)) { - if (mtex->mapto & WOMAP_ZENUP) zenfac= mtex->zenupfac; - } - else if (mtex->mapto & WOMAP_ZENDOWN) zenfac= mtex->zendownfac; - } - else { - if (mtex->mapto & WOMAP_ZENUP) zenfac= mtex->zenupfac; - else if (mtex->mapto & WOMAP_ZENDOWN) zenfac= mtex->zendownfac; - } - - if (zenfac != 0.0f) - texture_rgb_blend(zen, tcol, zen, texres.tin, zenfac, mtex->blendtype); - } - } - if (mtex->mapto & WOMAP_BLEND) { - if (rgb) texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - - *blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype); - } - } - } -} - -/* ------------------------------------------------------------------------- */ -/* col_r supposed to be initialized with la->r,g,b */ - -void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r[3], int effect) -{ - const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0; - const bool texnode_preview = (R.r.scemode & R_TEXNODE_PREVIEW) != 0; - Object *ob; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float *co = NULL, *dx = NULL, *dy = NULL, fact, stencilTin=1.0; - float texvec[3], dxt[3], dyt[3], tempvec[3]; - int i, tex_nr, rgb= 0; - - if (R.r.scemode & R_NO_TEX) return; - tex_nr= 0; - - for (; tex_nr<MAX_MTEX; tex_nr++) { - - if (la->mtex[tex_nr]) { - mtex= la->mtex[tex_nr]; - - tex= mtex->tex; - if (tex==NULL) continue; - texres.nor= NULL; - - /* which coords */ - if (mtex->texco==TEXCO_OBJECT) { - ob= mtex->object; - if (ob) { - co= tempvec; - dx= dxt; - dy= dyt; - copy_v3_v3(tempvec, shi->co); - mul_m4_v3(ob->imat_ren, tempvec); - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxco); - copy_v3_v3(dyt, shi->dyco); - mul_mat3_m4_v3(ob->imat_ren, dxt); - mul_mat3_m4_v3(ob->imat_ren, dyt); - } - } - else { - co= shi->co; - dx= shi->dxco; dy= shi->dyco; - } - } - else if (mtex->texco==TEXCO_GLOB) { - co= shi->gl; dx= shi->dxco; dy= shi->dyco; - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(R.viewinv, shi->gl); - } - else if (mtex->texco==TEXCO_VIEW) { - - copy_v3_v3(tempvec, lavec); - mul_m3_v3(la->imat, tempvec); - - if (la->type==LA_SPOT) { - tempvec[0]*= la->spottexfac; - tempvec[1]*= la->spottexfac; - /* project from 3d to 2d */ - tempvec[0] /= -tempvec[2]; - tempvec[1] /= -tempvec[2]; - } - co= tempvec; - - dx= dxt; dy= dyt; - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxlv); - copy_v3_v3(dyt, shi->dylv); - /* need some matrix conversion here? la->imat is a [3][3] matrix!!! **/ - mul_m3_v3(la->imat, dxt); - mul_m3_v3(la->imat, dyt); - - mul_v3_fl(dxt, la->spottexfac); - mul_v3_fl(dyt, la->spottexfac); - } - } - - - /* placement */ - if (mtex->projx && co) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy && co) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz && co) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - if (shi->osatex) { - if (!dx) { - for (i=0;i<2;i++) { - dxt[i] = dyt[i] = 0.0; - } - } - else { - if (mtex->projx) { - dxt[0]= mtex->size[0]*dx[mtex->projx-1]; - dyt[0]= mtex->size[0]*dy[mtex->projx-1]; - } - else { - dxt[0]= 0.0; - dyt[0]= 0.0; - } - if (mtex->projy) { - dxt[1]= mtex->size[1]*dx[mtex->projy-1]; - dyt[1]= mtex->size[1]*dy[mtex->projy-1]; - } - else { - dxt[1]= 0.0; - dyt[1]= 0.0; - } - if (mtex->projz) { - dxt[2]= mtex->size[2]*dx[mtex->projz-1]; - dyt[2]= mtex->size[2]*dy[mtex->projz-1]; - } - else { - dxt[2]= 0.0; - dyt[2]= 0.0; - } - } - } - - /* texture */ - if (tex->type==TEX_IMAGE) { - do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - } - - rgb = multitex(tex, - texvec, - dxt, dyt, - shi->osatex, - &texres, - shi->thread, - mtex->which_output, - R.pool, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgb) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - if (rgb) texres.ta*= stencilTin; - else texres.tin*= stencilTin; - } - - /* mapping */ - if (((mtex->mapto & LAMAP_COL) && (effect & LA_TEXTURE))||((mtex->mapto & LAMAP_SHAD) && (effect & LA_SHAD_TEX))) { - float col[3]; - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin= stencilTin; - } - else texres.tin= texres.ta; - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, R.pool); - } - - /* lamp colors were premultiplied with this */ - col[0]= texres.tr*la->energy; - col[1]= texres.tg*la->energy; - col[2]= texres.tb*la->energy; - - if (effect & LA_SHAD_TEX) - texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->shadowfac, mtex->blendtype); - else - texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype); - } - } - } -} - /* ------------------------------------------------------------------------- */ int externtex(const MTex *mtex, @@ -3626,7 +1476,7 @@ int externtex(const MTex *mtex, /* texture */ if (tex->type==TEX_IMAGE) { - do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, dxt, dyt); } rgb = multitex(tex, @@ -3658,327 +1508,3 @@ int externtex(const MTex *mtex, return (rgb != 0); } - -/* ------------------------------------------------------------------------- */ - -void render_realtime_texture(ShadeInput *shi, Image *ima) -{ - const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0; - TexResult texr; - static Tex imatex[BLENDER_MAX_THREADS]; /* threadsafe */ - static int firsttime= 1; - Tex *tex; - float texvec[3], dx[2], dy[2]; - ShadeInputUV *suv= &shi->uv[shi->actuv]; - int a; - - if (R.r.scemode & R_NO_TEX) return; - - if (firsttime) { - BLI_thread_lock(LOCK_IMAGE); - if (firsttime) { - const int num_threads = BLI_system_thread_count(); - for (a = 0; a < num_threads; a++) { - memset(&imatex[a], 0, sizeof(Tex)); - BKE_texture_default(&imatex[a]); - imatex[a].type= TEX_IMAGE; - } - - firsttime= 0; - } - BLI_thread_unlock(LOCK_IMAGE); - } - - tex= &imatex[shi->thread]; - tex->iuser.ok= ima->ok; - tex->ima = ima; - - texvec[0]= 0.5f+0.5f*suv->uv[0]; - texvec[1]= 0.5f+0.5f*suv->uv[1]; - texvec[2] = 0.0f; /* initalize it because imagewrap looks at it. */ - if (shi->osatex) { - dx[0]= 0.5f*suv->dxuv[0]; - dx[1]= 0.5f*suv->dxuv[1]; - dy[0]= 0.5f*suv->dyuv[0]; - dy[1]= 0.5f*suv->dyuv[1]; - } - - texr.nor= NULL; - - if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool, skip_load_image); - else imagewrap(tex, ima, NULL, texvec, &texr, R.pool, skip_load_image); - - shi->vcol[0]*= texr.tr; - shi->vcol[1]*= texr.tg; - shi->vcol[2]*= texr.tb; - shi->vcol[3]*= texr.ta; -} - -/* A modified part of shadeinput.c -> shade_input_set_uv() - * Used for sampling UV mapped texture color */ -static void textured_face_generate_uv( - const float normal[3], const float hit[3], - const float v1[3], const float v2[3], const float v3[3], - float r_uv[2]) -{ - - float detsh, t00, t10, t01, t11; - int axis1, axis2; - - /* find most stable axis to project */ - axis_dominant_v3(&axis1, &axis2, normal); - - /* compute u,v and derivatives */ - t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; - t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; - - detsh= 1.0f/(t00*t11-t10*t01); - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - r_uv[0] = (hit[axis1] - v3[axis1]) * t11 - (hit[axis2] - v3[axis2]) * t10; - r_uv[1] = (hit[axis2] - v3[axis2]) * t00 - (hit[axis1] - v3[axis1]) * t01; - - /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */ - CLAMP(r_uv[0], -2.0f, 1.0f); - CLAMP(r_uv[1], -2.0f, 1.0f); -} - -/* Generate an updated copy of material to use for color sampling. */ -Material *RE_sample_material_init(Depsgraph *depsgraph, Material *orig_mat, Scene *scene) -{ - Tex *tex = NULL; - Material *mat; - int tex_nr; - - if (!orig_mat) return NULL; - - /* copy material */ - mat = BKE_material_localize(orig_mat); - - /* update material anims */ - BKE_animsys_evaluate_animdata(scene, &mat->id, mat->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM); - - /* strip material copy from unsupported flags */ - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - - if (mat->mtex[tex_nr]) { - MTex *mtex = mat->mtex[tex_nr]; - - /* just in case make all non-used mtexes empty*/ - Tex *cur_tex = mtex->tex; - mtex->tex = NULL; - - if (mat->septex & (1<<tex_nr) || !cur_tex) continue; - - /* only keep compatible texflags */ - mtex->texflag = mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE | MTEX_ALPHAMIX); - - /* depending of material type, strip non-compatible mapping modes */ - if (mat->material_type == MA_TYPE_SURFACE) { - if (!ELEM(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) { - /* ignore this texture */ - mtex->texco = 0; - continue; - } - /* strip all mapto flags except color and alpha */ - mtex->mapto = (mtex->mapto & MAP_COL) | (mtex->mapto & MAP_ALPHA); - } - else if (mat->material_type == MA_TYPE_VOLUME) { - if (!ELEM(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) { - /* ignore */ - mtex->texco = 0; - continue; - } - /* strip all mapto flags except color and alpha */ - mtex->mapto = mtex->mapto & (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY); - } - - /* if mapped to an object, calculate inverse matrices */ - if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - invert_m4_m4(ob->imat, ob->obmat); - copy_m4_m4(ob->imat_ren, ob->imat); - } - } - - /* copy texture */ - tex= mtex->tex = BKE_texture_localize(cur_tex); - - /* update texture anims */ - BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM); - - /* update texture cache if required */ - if (tex->type==TEX_VOXELDATA) { - cache_voxeldata(tex, (int)scene->r.cfra); - } - if (tex->type==TEX_POINTDENSITY) { - /* set dummy values for render and do cache */ - Render dummy_re = {NULL}; - dummy_re.scene = scene; - unit_m4(dummy_re.viewinv); - unit_m4(dummy_re.viewmat); - unit_m4(dummy_re.winmat); - dummy_re.winx = dummy_re.winy = 128; - cache_pointdensity(depsgraph, &dummy_re, tex->pd); - } - - /* update image sequences and movies */ - if (tex->ima && BKE_image_is_animated(tex->ima)) { - BKE_image_user_check_frame_calc(&tex->iuser, (int)scene->r.cfra, 0); - } - } - } - return mat; -} - -/* free all duplicate data allocated by RE_sample_material_init() */ -void RE_sample_material_free(Material *mat) -{ - int tex_nr; - - /* free textures */ - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - if (mat->septex & (1<<tex_nr)) continue; - if (mat->mtex[tex_nr]) { - MTex *mtex= mat->mtex[tex_nr]; - - if (mtex->tex) { - /* don't update user counts as we are freeing a duplicate */ - BKE_texture_free(mtex->tex); - MEM_freeN(mtex->tex); - mtex->tex = NULL; - } - } - } - - /* don't update user counts as we are freeing a duplicate */ - BKE_material_free(mat); - MEM_freeN(mat); -} - -/* - * Get material diffuse color and alpha (including linked textures) in given coordinates - * - * color,alpha : input/output color values - * volume_co : sample coordinate in global space. used by volumetric materials - * surface_co : sample surface coordinate in global space. used by "surface" materials - * tri_index : surface tri index - * orcoDm : orco state derived mesh - */ -void RE_sample_material_color( - Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], - int tri_index, DerivedMesh *orcoDm, Object *ob) -{ - int v1, v2, v3; - MVert *mvert; - MLoop *mloop; - const MLoopTri *mlooptri; - float normal[3]; - ShadeInput shi = {NULL}; - Render re = {NULL}; - - /* Get face data */ - mvert = orcoDm->getVertArray(orcoDm); - mloop = orcoDm->getLoopArray(orcoDm); - mlooptri = orcoDm->getLoopTriArray(orcoDm); - - if (!mvert || !mlooptri || !mat) { - return; - } - - v1 = mloop[mlooptri[tri_index].tri[0]].v; - v2 = mloop[mlooptri[tri_index].tri[1]].v; - v3 = mloop[mlooptri[tri_index].tri[2]].v; - normal_tri_v3(normal, mvert[v1].co, mvert[v2].co, mvert[v3].co); - - /* generate shadeinput with data required */ - shi.mat = mat; - - /* fill shadeinput data depending on material type */ - if (mat->material_type == MA_TYPE_SURFACE) { - /* global coordinates */ - copy_v3_v3(shi.gl, surface_co); - /* object space coordinates */ - copy_v3_v3(shi.co, surface_co); - mul_m4_v3(ob->imat, shi.co); - /* orco coordinates */ - { - float uv[2]; - float l; - /* Get generated UV */ - textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv); - l= 1.0f+uv[0]+uv[1]; - - /* calculate generated coordinate */ - shi.lo[0]= l*mvert[v3].co[0]-uv[0]*mvert[v1].co[0]-uv[1]*mvert[v2].co[0]; - shi.lo[1]= l*mvert[v3].co[1]-uv[0]*mvert[v1].co[1]-uv[1]*mvert[v2].co[1]; - shi.lo[2]= l*mvert[v3].co[2]-uv[0]*mvert[v1].co[2]-uv[1]*mvert[v2].co[2]; - } - /* uv coordinates */ - { - const int layers = CustomData_number_of_layers(&orcoDm->loopData, CD_MLOOPUV); - const int layer_index = CustomData_get_layer_index(&orcoDm->loopData, CD_MLOOPUV); - int i; - - /* for every uv map set coords and name */ - for (i=0; i<layers; i++) { - if (layer_index >= 0) { - const float *uv1, *uv2, *uv3; - const CustomData *data = &orcoDm->loopData; - const MLoopUV *mloopuv = data->layers[layer_index + i].data; - float uv[2]; - float l; - - /* point layer name from actual layer data */ - shi.uv[i].name = data->layers[i].name; - /* Get generated coordinates to calculate UV from */ - textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv); - /* Get UV mapping coordinate */ - l= 1.0f+uv[0]+uv[1]; - - uv1 = mloopuv[mlooptri[tri_index].tri[0]].uv; - uv2 = mloopuv[mlooptri[tri_index].tri[1]].uv; - uv3 = mloopuv[mlooptri[tri_index].tri[2]].uv; - - shi.uv[i].uv[0]= -1.0f + 2.0f*(l*uv3[0]-uv[0]*uv1[0]-uv[1]*uv2[0]); - shi.uv[i].uv[1]= -1.0f + 2.0f*(l*uv3[1]-uv[0]*uv1[1]-uv[1]*uv2[1]); - shi.uv[i].uv[2]= 0.0f; /* texture.c assumes there are 3 coords */ - } - } - /* active uv map */ - shi.actuv = CustomData_get_active_layer_index(&orcoDm->loopData, CD_MLOOPUV) - layer_index; - shi.totuv = layers; - } - - /* apply initial values from material */ - shi.r = mat->r; - shi.g = mat->g; - shi.b = mat->b; - shi.alpha = mat->alpha; - - /* do texture */ - do_material_tex(&shi, &re); - - /* apply result */ - color[0] = shi.r; - color[1] = shi.g; - color[2] = shi.b; - *alpha = shi.alpha; - } - else if (mat->material_type == MA_TYPE_VOLUME) { - ObjectInstanceRen obi = {NULL}; - obi.ob = ob; - shi.obi = &obi; - unit_m4(re.viewinv); - copy_v3_v3(color, mat->vol.reflection_col); - *alpha = mat->vol.density; - - /* do texture */ - do_volume_tex(&shi, volume_co, (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY), - color, alpha, &re); - } -} - -/* eof */ |