diff options
author | Miika Hamalainen <blender@miikah.org> | 2011-10-22 20:16:14 +0400 |
---|---|---|
committer | Miika Hamalainen <blender@miikah.org> | 2011-10-22 20:16:14 +0400 |
commit | 30cba27987362054d16b10e73ddf2601af93be68 (patch) | |
tree | d971f10db56b5d024cf5f7d6f3d48d1e3c20d698 /source/blender/render | |
parent | 8be3249537e7930e0fa5adb59bc343455da309e9 (diff) |
Dynamic Paint:
* Some changes and cleanup pointed on the codereview.
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/extern/include/RE_render_ext.h | 7 | ||||
-rw-r--r-- | source/blender/render/intern/include/texture.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/source/render_texture.c | 258 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeinput.c | 28 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeoutput.c | 16 |
5 files changed, 289 insertions, 22 deletions
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index e98f481b162..deae2ed9b66 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -50,6 +50,7 @@ struct RNode; struct Render; struct MTex; struct ImBuf; +struct DerivedMesh; // RADIO REMOVED, Maybe this will be useful later //void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re); @@ -65,5 +66,11 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result); void antialias_tagbuf(int xsize, int ysize, char *rectmove); +/* dynamicpaint.c */ +struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene); +void RE_free_sample_material(struct Material *mat); +void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], + int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob); + #endif /* RE_RENDER_EXT_H */ diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 294c7b53766..9815cfdff7d 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -68,7 +68,7 @@ void do_halo_tex(struct HaloRen *har, float xn, float yn, float col_r[4]); void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float hor[3], float zen[3], float *blend, int skyflag, short thread); void do_material_tex(struct ShadeInput *shi); void do_lamp_tex(LampRen *la, const float lavec[3], struct ShadeInput *shi, float col_r[3], int effect); -void do_volume_tex(struct ShadeInput *shi, const float *xyz, int mapto_flag, float *col, float *val, struct Render *re); +void do_volume_tex(struct ShadeInput *shi, const float xyz[3], int mapto_flag, float col[3], float *val, struct Render *re); void init_render_textures(Render *re); void end_render_textures(Render *re); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 2d9ce24b46c..a050fd8622b 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -40,6 +40,7 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_texture_types.h" #include "DNA_object_types.h" #include "DNA_lamp_types.h" @@ -57,10 +58,12 @@ #include "BKE_node.h" #include "BKE_plugin_types.h" - +#include "BKE_animsys.h" +#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_scene.h" #include "BKE_library.h" #include "BKE_image.h" @@ -3474,4 +3477,257 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) 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(float *uv, float *normal, float *hit, float *v1, float *v2, float *v3) +{ + + float detsh, t00, t10, t01, t11, xn, yn, zn; + int axis1, axis2; + + /* find most stable axis to project */ + xn= fabs(normal[0]); + yn= fabs(normal[1]); + zn= fabs(normal[2]); + + if(zn>=xn && zn>=yn) { axis1= 0; axis2= 1; } + else if(yn>=xn && yn>=zn) { axis1= 0; axis2= 2; } + else { axis1= 1; axis2= 2; } + + /* 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; + + uv[0] = (hit[axis1]-v3[axis1])*t11-(hit[axis2]-v3[axis2])*t10; + 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(uv[0], -2.0f, 1.0f); + CLAMP(uv[1], -2.0f, 1.0f); +} + +/* Generate an updated copy of material to use for color sampling. */ +Material *RE_init_sample_material(Material *orig_mat, Scene *scene) +{ + Tex *tex = NULL; + Material *mat; + int tex_nr; + + if (!orig_mat) return NULL; + + /* copy material */ + mat = localize_material(orig_mat); + + /* update material anims */ + BKE_animsys_evaluate_animdata(scene, &mat->id, mat->adt, BKE_curframe(scene), ADT_RECALC_ANIM); + + /* strip material copy from unsupported flags */ + 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]; + + /* 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 (!ELEM4(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 (!ELEM3(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 = localize_texture(mtex->tex); + + /* update texture anims */ + BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_curframe(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 = {0}; + 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(&dummy_re, tex); + } + + /* update image sequences and movies */ + if(tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + if(tex->iuser.flag & IMA_ANIM_ALWAYS) + BKE_image_user_calc_frame(&tex->iuser, (int)scene->r.cfra, 0); + } + } + } + return mat; +} + +/* free all duplicate data allocated by RE_init_sample_material() */ +void RE_free_sample_material(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]; + free_texture(mtex->tex); + } + } + + free_material(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 +* face_index : surface face index +* hit_quad : whether point is on second "half" of a quad +* 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 face_index, short hit_quad, DerivedMesh *orcoDm, Object *ob) +{ + MFace *mface; + int v1, v2, v3; + MVert *mvert; + float uv[3], normal[3]; + ShadeInput shi = {0}; + + /* Get face data */ + mvert = orcoDm->getVertArray(orcoDm); + mface = orcoDm->getFaceArray(orcoDm); + + if (!mvert || !mface || !mat) return; + v1=mface[face_index].v1, v2=mface[face_index].v2, v3=mface[face_index].v3; + if (hit_quad) {v2=mface[face_index].v3; v3=mface[face_index].v4;} + 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 */ + VECCOPY(shi.gl, surface_co); + /* object space coordinates */ + VECCOPY(shi.co, surface_co); + mul_m4_v3(ob->imat, shi.co); + /* orco coordinates */ + { + float l; + /* Get generated UV */ + textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co); + 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 */ + { + int i, layers = CustomData_number_of_layers(&orcoDm->faceData, CD_MTFACE); + int layer_index = CustomData_get_layer_index(&orcoDm->faceData, CD_MTFACE); + + /* for every uv layer set coords and name */ + for (i=0; i<layers; i++) { + if(layer_index >= 0) { + float *uv1, *uv2, *uv3; + float l; + CustomData *data = &orcoDm->faceData; + MTFace *tface = (MTFace*) data->layers[layer_index+i].data; + float uv[3]; + /* 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(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co); + /* Get UV mapping coordinate */ + l= 1.0f+uv[0]+uv[1]; + + uv1= tface[face_index].uv[0]; + uv2= (hit_quad) ? tface[face_index].uv[2] : tface[face_index].uv[1]; + uv3= (hit_quad) ? tface[face_index].uv[3] : tface[face_index].uv[2]; + + 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 layer */ + shi.actuv = CustomData_get_active_layer_index(&orcoDm->faceData,CD_MTFACE) - 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); + + /* 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 = {0}; + Render re = {0}; + obi.ob = ob; + shi.obi = &obi; + unit_m4(re.viewinv); + + color[0] = mat->vol.reflection_col[0]; + color[1] = mat->vol.reflection_col[1]; + color[2] = mat->vol.reflection_col[2]; + *alpha = mat->vol.density; + + /* do texture */ + do_volume_tex(&shi, volume_co, (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY), + color, alpha, &re); + } +} + /* eof */ diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index f3e5fc63bda..e20c6ee174c 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1103,6 +1103,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { ShadeInputCol *scol= &shi->col[i]; char *cp1, *cp2, *cp3; + float a[3]; shi->totcol++; scol->name= name; @@ -1111,18 +1112,21 @@ void shade_input_set_shade_texco(ShadeInput *shi) cp2= (char *)(mcol+j2); cp3= (char *)(mcol+j3); - /* alpha value */ - scol->col[3]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f; - - /* try to prevent invalid color sampling of zero alpha points */ - if (!cp1[0]) cp1 = cp2; if (!cp1[0]) cp1 = cp3; - if (!cp2[0]) cp2 = cp1; if (!cp2[0]) cp2 = cp3; - if (!cp3[0]) cp3 = cp1; if (!cp3[0]) cp3 = cp2; - - /* sample color value */ - scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f; - scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f; - scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f; + /* alpha values */ + a[0] = ((float)cp1[0])/255.f; + a[1] = ((float)cp2[0])/255.f; + a[2] = ((float)cp3[0])/255.f; + scol->col[3]= l*a[2] - u*a[0] - v*a[1]; + + /* sample premultiplied color value */ + scol->col[0]= (l*((float)cp3[3])*a[2] - u*((float)cp1[3])*a[0] - v*((float)cp2[3])*a[1])/255.f; + scol->col[1]= (l*((float)cp3[2])*a[2] - u*((float)cp1[2])*a[0] - v*((float)cp2[2])*a[1])/255.f; + scol->col[2]= (l*((float)cp3[1])*a[2] - u*((float)cp1[1])*a[0] - v*((float)cp2[1])*a[1])/255.f; + + /* if not zero alpha, restore non-multiplied color */ + if (scol->col[3]) { + mul_v3_fl(scol->col, 1.0f/scol->col[3]); + } } if(shi->totcol) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 0056b073c81..eece830f5b9 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -874,10 +874,10 @@ void shade_color(ShadeInput *shi, ShadeResult *shr) shi->alpha= shi->vcol[3]; } else if(ma->mode & (MA_VERTEXCOLP)) { - float inv_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*inv_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*inv_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*inv_alpha + shi->vcol[2]*shi->vcol[3]; + float neg_alpha = 1.0f - shi->vcol[3]; + shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; + shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; + shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; } if(ma->texco) @@ -1671,10 +1671,10 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shi->alpha= shi->vcol[3]; } else if(ma->mode & (MA_VERTEXCOLP)) { - float inv_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*inv_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*inv_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*inv_alpha + shi->vcol[2]*shi->vcol[3]; + float neg_alpha = 1.0f - shi->vcol[3]; + shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; + shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; + shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; } if(ma->texco){ do_material_tex(shi); |