Misc Render Features

====================

- "From Dupli" option for orco and uv texture coordinates. For dupliverts,
  duplifaces and dupli particles, this uses the orco and uv at the point
  on the parent surface. Can for example be used for texturing feathers
  and leafs. Note that uv only works for duplifaces and particles emitted
  from faces, these are not defined at vertices.

- "Width Fade" option for strand render, to fade out along the width of the
  strand. Committing this so it can be tested, might be changed or removed
  even, if it doesn't give nice results.
This commit is contained in:
Brecht Van Lommel 2008-01-09 14:40:25 +00:00
parent 8b78a5cf35
commit ead7a33247
17 changed files with 296 additions and 118 deletions

@ -46,6 +46,7 @@ typedef struct DupliObject {
unsigned int origlay;
int index, no_draw, type;
float mat[4][4], omat[4][4];
float orco[3], uv[2];
} DupliObject;
void free_path(struct Path *path);

@ -244,6 +244,8 @@ float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);
void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco);
void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale);
ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread);
int psys_threads_init_distribution(ParticleThread *threads, struct DerivedMesh *dm, int from);

@ -2135,9 +2135,13 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
}
/* add an orco layer if needed */
if(dataMask & CD_MASK_ORCO)
if(dataMask & CD_MASK_ORCO) {
add_orco_dm(ob, finaldm, orcodm);
if(deform_r && *deform_r)
add_orco_dm(ob, *deform_r, NULL);
}
*final_r = finaldm;
if(orcodm)

@ -378,10 +378,12 @@ struct vertexDupliData {
float pmat[4][4];
float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
Object *ob, *par;
float (*orco)[3];
};
static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
DupliObject *dob;
struct vertexDupliData *vdd= userData;
float vec[3], *q2, mat[3][3], tmat[4][4], obmat[4][4];
@ -407,7 +409,9 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
Mat4CpyMat4(tmat, obmat);
Mat4MulMat43(obmat, tmat, mat);
}
new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS);
dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS);
if(vdd->orco)
VECCOPY(dob->orco, vdd->orco[index]);
if(vdd->ob->transflag & OB_DUPLI) {
float tmpmat[4][4];
@ -429,16 +433,25 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_
Scene *sce = NULL;
Group *group = NULL;
GroupObject * go = NULL;
CustomDataMask dataMask = CD_MASK_BAREMESH;
Mat4CpyMat4(pmat, par->obmat);
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
if(G.rendering)
dataMask |= CD_MASK_ORCO;
if(par==G.obedit)
dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
dm= editmesh_get_derived_cage(dataMask);
else
dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH);
dm= mesh_get_derived_deform(par, dataMask);
if(G.rendering)
vdd.orco= dm->getVertDataArray(dm, CD_ORCO);
else
vdd.orco= NULL;
totvert = dm->getNumVerts(dm);
@ -517,25 +530,31 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma
{
Object *ob, *ob_iter;
Base *base = NULL;
DupliObject *dob;
DerivedMesh *dm;
Mesh *me;
MTFace *mtface;
MFace *mface;
MVert *mvert;
float pmat[4][4], imat[3][3];
float pmat[4][4], imat[3][3], (*orco)[3], w;
int lay, oblay, totface, a;
Scene *sce = NULL;
Group *group = NULL;
GroupObject *go = NULL;
CustomDataMask dataMask = CD_MASK_BAREMESH;
float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
Mat4CpyMat4(pmat, par->obmat);
if(G.rendering)
dataMask |= CD_MASK_ORCO;
Mat4CpyMat4(pmat, par->obmat);
if(par==G.obedit) {
int totvert;
dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
dm= editmesh_get_derived_cage(dataMask);
totface= dm->getNumFaces(dm);
mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
@ -545,13 +564,22 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma
dm->copyVertArray(dm, mvert);
}
else {
dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH);
dm = mesh_get_derived_deform(par, dataMask);
totface= dm->getNumFaces(dm);
mface= dm->getFaceArray(dm);
mvert= dm->getVertArray(dm);
}
if(G.rendering) {
me= (Mesh*)par->data;
orco= dm->getVertDataArray(dm, CD_ORCO);
mtface= me->mtface;
}
else {
orco= NULL;
mtface= NULL;
}
/* having to loop on scene OR group objects is NOT FUN */
if (GS(id->name) == ID_SCE) {
@ -595,10 +623,14 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma
if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
for(a=0; a<totface; a++) {
float *v1= mvert[ mface[a].v1 ].co;
float *v2= mvert[ mface[a].v2 ].co;
float *v3= mvert[ mface[a].v3 ].co;
float *v4= mface[a].v4?mvert[ mface[a].v4 ].co:NULL;
int mv1 = mface[a].v1;
int mv2 = mface[a].v2;
int mv3 = mface[a].v3;
int mv4 = mface[a].v4;
float *v1= mvert[mv1].co;
float *v2= mvert[mv2].co;
float *v3= mvert[mv3].co;
float *v4= (mv4)? mvert[mv4].co: NULL;
float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];
/* translation */
@ -632,7 +664,32 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma
Mat4CpyMat4(tmat, obmat);
Mat4MulMat43(obmat, tmat, mat);
new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES);
dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES);
if(G.rendering) {
w= (mv4)? 0.25f: 1.0f/3.0f;
if(orco) {
VECADDFAC(dob->orco, dob->orco, orco[mv1], w);
VECADDFAC(dob->orco, dob->orco, orco[mv2], w);
VECADDFAC(dob->orco, dob->orco, orco[mv3], w);
if(mv4)
VECADDFAC(dob->orco, dob->orco, orco[mv4], w);
}
if(mtface) {
dob->uv[0] += w*mtface[a].uv[0][0];
dob->uv[1] += w*mtface[a].uv[0][1];
dob->uv[0] += w*mtface[a].uv[1][0];
dob->uv[1] += w*mtface[a].uv[1][1];
dob->uv[0] += w*mtface[a].uv[2][0];
dob->uv[1] += w*mtface[a].uv[2][1];
if(mv4) {
dob->uv[0] += w*mtface[a].uv[3][0];
dob->uv[1] += w*mtface[a].uv[3][1];
}
}
}
if(ob->transflag & OB_DUPLI) {
float tmpmat[4][4];
@ -660,38 +717,14 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma
dm->release(dm);
}
static void particle_dupli_path_rotation(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
{
float loc[3], nor[3], vec[3], side[3], len;
VecSubf(vec, (cache+cache->steps-1)->co, cache->co);
len= Normalize(vec);
if(pa)
psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
else
psys_particle_on_emitter(ob, psmd,
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
Crossf(side, nor, vec);
Normalize(side);
Crossf(nor, vec, side);
Mat4One(mat);
VECCOPY(mat[0], vec);
VECCOPY(mat[1], side);
VECCOPY(mat[2], nor);
*scale= len;
}
static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level)
{
GroupObject *go;
Object *ob=0, **oblist=0;
DupliObject *dob;
ParticleSettings *part;
ParticleData *pa;
ChildParticle *cpa=0;
ParticleKey state;
ParticleCacheKey *cache;
ParticleSystemModifierData *psmd;
@ -773,10 +806,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
}
else {
/* TODO: figure these two out */
cpa= &psys->child[a - totpart];
pa_num = a;
pa_time = psys->particles[psys->child[a - totpart].parent].time;
pa_time = psys->particles[cpa->parent].time;
size=psys_get_child_size(psys, &psys->child[a - totpart], ctime, 0);
size=psys_get_child_size(psys, cpa, ctime, 0);
}
if(part->draw_as==PART_DRAW_GR) {
@ -795,12 +829,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
if(hair) {
if(a < totpart) {
cache = psys->pathcache[a];
particle_dupli_path_rotation(par, part, psmd, pa, 0, cache, pamat, &scale);
psys_get_dupli_path_transform(par, part, psmd, pa, 0, cache, pamat, &scale);
}
else {
ChildParticle *cpa= psys->child+(a-totpart);
cache = psys->childcache[a-totpart];
particle_dupli_path_rotation(par, part, psmd, 0, cpa, cache, pamat, &scale);
psys_get_dupli_path_transform(par, part, psmd, 0, cpa, cache, pamat, &scale);
}
VECCOPY(pamat[3], cache->co);
@ -833,7 +866,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
else
Mat4CpyMat4(mat, tmat);
new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS);
dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS);
if(G.rendering)
psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco);
}
}
else {
@ -857,7 +892,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
else
Mat4CpyMat4(mat, tmat);
new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS);
dob= new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS);
if(G.rendering)
psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco);
}
}
}

@ -3563,3 +3563,78 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
//}
}
void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
{
MFace *mface;
MTFace *mtface;
float loc[3];
int num;
if(cpa) {
if(part->childtype == PART_CHILD_FACES) {
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
if(mtface) {
mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE);
mtface += cpa->num;
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
}
else
uv[0]= uv[1]= 0.0f;
}
else
uv[0]= uv[1]= 0.0f;
psys_particle_on_emitter(ob, psmd,
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
}
else {
if(part->from == PART_FROM_FACE) {
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
num= pa->num_dmcache;
if(num == DMCACHE_NOTFOUND)
if(pa->num < psmd->dm->getNumFaces(psmd->dm))
num= pa->num;
if(mtface && num != DMCACHE_NOTFOUND) {
mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
mtface += num;
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
}
else
uv[0]= uv[1]= 0.0f;
}
else
uv[0]= uv[1]= 0.0f;
psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
}
}
void psys_get_dupli_path_transform(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
{
float loc[3], nor[3], vec[3], side[3], len;
VecSubf(vec, (cache+cache->steps-1)->co, cache->co);
len= Normalize(vec);
if(pa)
psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
else
psys_particle_on_emitter(ob, psmd,
(part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
Crossf(side, nor, vec);
Normalize(side);
Crossf(nor, vec, side);
Mat4One(mat);
VECCOPY(mat[0], vec);
VECCOPY(mat[1], side);
VECCOPY(mat[2], nor);
*scale= len;
}

@ -85,7 +85,7 @@ typedef struct Material {
short flarec, starc, linec, ringc;
float hasize, flaresize, subsize, flareboost;
float strand_sta, strand_end, strand_ease, strand_surfnor;
float strand_min, strand_pad;
float strand_min, strand_widthfade;
char strand_uvname[32];
float sbias; /* shadow bias */

@ -347,11 +347,12 @@ typedef struct TexMapping {
#define PROJ_Z 3
/* texflag */
#define MTEX_RGBTOINT 1
#define MTEX_STENCIL 2
#define MTEX_NEGATIVE 4
#define MTEX_ALPHAMIX 8
#define MTEX_VIEWSPACE 16
#define MTEX_RGBTOINT 1
#define MTEX_STENCIL 2
#define MTEX_NEGATIVE 4
#define MTEX_ALPHAMIX 8
#define MTEX_VIEWSPACE 16
#define MTEX_DUPLI_MAPTO 32
/* blendtype */
#define MTEX_BLEND 0

@ -133,6 +133,7 @@ typedef struct ShadeInput
float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4], rad[3];
float refcol[4], displace[3];
float strand, tang[3], stress, winspeed[4];
float duplilo[3], dupliuv[3];
ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */
ShadeInputCol col[8]; /* 8 = MAX_MCOL */

@ -266,6 +266,8 @@ typedef struct ObjectInstanceRen {
float mat[4][4], imat[3][3];
short flag;
float dupliorco[3], dupliuv[2];
float *vectors;
int totvector;
} ObjectInstanceRen;
@ -343,7 +345,7 @@ typedef struct StrandBuffer {
unsigned int lay;
int overrideuv;
int flag, maxdepth;
float adaptcos, minwidth;
float adaptcos, minwidth, widthfade;
float winmat[4][4];
int winx, winy;

@ -94,7 +94,7 @@ struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, s
struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert);
struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex);
void RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]);
struct ObjectInstanceRen *RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]);
void RE_makeRenderInstances(struct Render *re);
void RE_instanceTransformNormal(struct ObjectInstanceRen *obi, float *nor, float *tnor);

@ -1496,11 +1496,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f;
float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
float adapt_angle=0.0, adapt_pix=0.0, random;
float simplify[2];
float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2];
int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0;
int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0};
int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num;
char **uv_name=0;
/* 1. check that everything is ok & updated */
@ -1644,6 +1643,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
strandbuf->overrideuv= override_uv;
strandbuf->minwidth= ma->strand_min;
if(ma->strand_widthfade == 0.0f)
strandbuf->widthfade= 0.0f;
else if(ma->strand_widthfade >= 1.0f)
strandbuf->widthfade= 2.0f - ma->strand_widthfade;
else
strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
if(part->flag & PART_HAIR_BSPLINE)
strandbuf->flag |= R_STRAND_BSPLINE;
if(ma->mode & MA_STR_B_UNITS)
@ -1700,13 +1706,25 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
for(i=0; i<totuv; i++){
MFace *mface=psmd->dm->getFaceData(psmd->dm,pa->num,CD_MFACE);
mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
mtface+=pa->num;
psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i);
num= pa->num_dmcache;
if(num == DMCACHE_NOTFOUND)
if(pa->num < psmd->dm->getNumFaces(psmd->dm))
num= pa->num;
for(i=0; i<totuv; i++){
if(num != DMCACHE_NOTFOUND) {
MFace *mface=psmd->dm->getFaceData(psmd->dm,num,CD_MFACE);
mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
mtface+=num;
psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i);
}
else {
uvco[2*i]= 0.0f;
uvco[2*i + 1]= 0.0f;
}
}
}
@ -4076,6 +4094,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
{
Base *base;
Object *ob;
ObjectInstanceRen *obi;
Scene *sce;
float mat[4][4], obmat[4][4];
@ -4136,11 +4155,18 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
Mat4Invert(imat, obmat);
MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0);
RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat);
obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat);
VECCOPY(obi->dupliorco, dob->orco);
obi->dupliuv[0]= dob->uv[0];
obi->dupliuv[1]= dob->uv[1];
psysindex= 1;
for(psys=obd->particlesystem.first; psys; psys=psys->next)
for(psys=obd->particlesystem.first; psys; psys=psys->next) {
RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat);
VECCOPY(obi->dupliorco, dob->orco);
obi->dupliuv[0]= dob->uv[0];
obi->dupliuv[1]= dob->uv[1];
}
obd->flag |= OB_DONE;
obd->transflag |= OB_RENDER_DUPLI;

@ -93,10 +93,10 @@ static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y)
else {
char *rect = (char *)( ibuf->rect+ ofs);
col[0] = ((float)rect[0])/255.0f;
col[1] = ((float)rect[1])/255.0f;
col[2] = ((float)rect[2])/255.0f;
col[3] = ((float)rect[3])/255.0f;
col[0] = ((float)rect[0])*(1.0f/255.0f);
col[1] = ((float)rect[1])*(1.0f/255.0f);
col[2] = ((float)rect[2])*(1.0f/255.0f);
col[3] = ((float)rect[3])*(1.0f/255.0f);
}
}

@ -1261,7 +1261,7 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
/* ------------------------------------------------------------------------- */
void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4])
ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4])
{
ObjectInstanceRen *obi;
float mat3[3][3];
@ -1281,6 +1281,8 @@ void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, i
}
BLI_addtail(&re->instancetable, obi);
return obi;
}
void RE_makeRenderInstances(Render *re)

@ -919,6 +919,8 @@ void shade_input_set_shade_texco(ShadeInput *shi)
shi->dylo[2]= dl*o3[2]-shi->dy_u*o1[2]-shi->dy_v*o2[2];
}
}
VECCOPY(shi->duplilo, obi->dupliorco);
}
if(texco & TEXCO_GLOB) {
@ -1033,6 +1035,10 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
}
shi->dupliuv[0]= -1.0f + 2.0f*obi->dupliuv[0];
shi->dupliuv[1]= -1.0f + 2.0f*obi->dupliuv[1];
shi->dupliuv[2]= 0.0f;
if(shi->totuv == 0) {
ShadeInputUV *suv= &shi->uv[0];

@ -436,7 +436,7 @@ typedef struct StrandPart {
GHash *hash;
StrandPoint point1, point2;
ShadeSample ssamp1, ssamp2, ssamp;
float t[3];
float t[3], s[3];
} StrandPart;
typedef struct StrandSortSegment {
@ -520,6 +520,23 @@ static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr)
}
}
static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
{
if(alpha < 1.0f) {
shr->combined[0] *= alpha;
shr->combined[1] *= alpha;
shr->combined[2] *= alpha;
shr->combined[3] *= alpha;
shr->col[0] *= alpha;
shr->col[1] *= alpha;
shr->col[2] *= alpha;
shr->col[3] *= alpha;
shr->alpha *= alpha;
}
}
static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco)
{
projectvert(co, winmat, hoco);
@ -537,7 +554,6 @@ static void strand_project_point(float winmat[][4], float winx, float winy, Stra
spoint->y= spoint->hoco[1]*div*winy*0.5f;
}
#include "BLI_rand.h"
static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint);
static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg)
@ -576,22 +592,6 @@ static void strand_shade_segment(StrandPart *spart)
strand_shade_get(spart, !last, &spart->ssamp2, &sseg->point2, sseg->v[2], sseg);
sseg->shaded= 1;
}
#if 0
float c[3];
c[0]= BLI_frand();
c[1]= BLI_frand();
c[2]= BLI_frand();
spart->ssamp1.shr[0].combined[0] *= c[0];
spart->ssamp1.shr[0].combined[1] *= c[1];
spart->ssamp1.shr[0].combined[2] *= c[2];
spart->ssamp2.shr[0].combined[0] *= c[0];
spart->ssamp2.shr[0].combined[1] *= c[1];
spart->ssamp2.shr[0].combined[2] *= c[2];
#endif
}
static void do_strand_blend(void *handle, int x, int y, float u, float v, float z)
@ -599,7 +599,7 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float
StrandPart *spart= (StrandPart*)handle;
StrandBuffer *buffer= spart->segment->buffer;
ShadeResult *shr;
float /**pass,*/ t;
float /**pass,*/ t, s;
int offset, zverg;
/* check again solid z-buffer */
@ -625,6 +625,14 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float
interpolate_shade_result(spart->ssamp1.shr, spart->ssamp2.shr, t,
spart->ssamp.shr, spart->addpassflag);
/* alpha along width */
if(buffer->widthfade != 0.0f) {
s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]);
s = 1.0f - pow(s, buffer->widthfade);
strand_apply_shaderesult_alpha(spart->ssamp.shr, s);
}
/* add in shaderesult array for part */
spart->ssamp.shi[0].mask= (1<<spart->sample);
addtosamp_shr(shr, &spart->ssamp, spart->addpassflag);
@ -696,19 +704,7 @@ static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *ss
shade_input_do_shade(shi, shr);
/* apply simplification */
if(spoint->alpha < 1.0f) {
shr->combined[0] *= spoint->alpha;
shr->combined[1] *= spoint->alpha;
shr->combined[2] *= spoint->alpha;
shr->combined[3] *= spoint->alpha;
shr->col[0] *= spoint->alpha;
shr->col[1] *= spoint->alpha;
shr->col[2] *= spoint->alpha;
shr->col[3] *= spoint->alpha;
shr->alpha *= spoint->alpha;
}
strand_apply_shaderesult_alpha(shr, spoint->alpha);
/* include lamphalos for strand, since halo layer was added already */
if(re->flag & R_LAMPHALO)
@ -747,12 +743,18 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f
spart->sample= sample;
spart->t[0]= t-dt;
spart->s[0]= -1.0f;
spart->t[1]= t-dt;
spart->s[1]= 1.0f;
spart->t[2]= t;
spart->s[2]= 1.0f;
zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_blend);
spart->t[0]= t-dt;
spart->s[0]= -1.0f;
spart->t[1]= t;
spart->s[1]= 1.0f;
spart->t[2]= t;
spart->s[2]= -1.0f;
zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend);
}

@ -1427,7 +1427,14 @@ void do_material_tex(ShadeInput *shi)
/* which coords */
if(mtex->texco==TEXCO_ORCO) {
co= shi->lo; dx= shi->dxlo; dy= shi->dylo;
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_STICKY) {
co= shi->sticky; dx= shi->dxsticky; dy= shi->dysticky;
@ -1466,21 +1473,28 @@ void do_material_tex(ShadeInput *shi)
co= shi->gl; dx= shi->dxco; dy= shi->dyco;
}
else if(mtex->texco==TEXCO_UV) {
ShadeInputUV *suv= &shi->uv[shi->actuv];
int i;
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;
if(mtex->uvname[0] != 0) {
for(i = 0; i < shi->totuv; i++) {
if(strcmp(shi->uv[i].name, mtex->uvname)==0) {
suv= &shi->uv[i];
break;
if(mtex->uvname[0] != 0) {
for(i = 0; i < shi->totuv; i++) {
if(strcmp(shi->uv[i].name, mtex->uvname)==0) {
suv= &shi->uv[i];
break;
}
}
}
}
co= suv->uv;
dx= suv->dxuv;
dy= suv->dyuv;
co= suv->uv;
dx= suv->dxuv;
dy= suv->dyuv;
}
}
else if(mtex->texco==TEXCO_WINDOW) {
co= shi->winco; dx= shi->dxwin; dy= shi->dywin;

@ -3299,7 +3299,7 @@ static void material_panel_map_input(Object *ob, Material *ma)
uiBlockBeginAlign(block);
uiDefButS(block, ROW, B_MATPRV, "Glob", 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates");
uiDefButS(block, ROW, B_MATPRV, "Object", 675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates");
if(mtex->texco == TEXCO_UV) {
if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) {
if(!verify_valid_uv_name(mtex->uvname))
uiBlockSetCol(block, TH_REDALERT);
but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
@ -3321,6 +3321,10 @@ static void material_panel_map_input(Object *ob, Material *ma)
uiDefButS(block, ROW, B_MATPRV, "Stress", 630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh");
uiDefButS(block, ROW, B_MATPRV, "Tangent", 700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates");
uiBlockEndAlign(block);
if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO))
uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "If object is duplicated by vertices, faces or particles, inherit texture coordinate from parent object");
/* COORDS */
uiBlockBeginAlign(block);
@ -3855,7 +3859,7 @@ static uiBlock *strand_menu(void *mat_v)
{
Material *ma= mat_v;
uiBlock *block;
int buth=20, butw=230, butx=10, buty=160;
int buth=20, butw=230, butx=10, buty=180;
block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win);
@ -3885,6 +3889,7 @@ static uiBlock *strand_menu(void *mat_v)
uiDefButF(block, NUMSLI, 0, "End ", butx,buty-=buth, butw,buth, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels");
}
uiDefButF(block, NUMSLI, 0, "Shape ", butx,buty-=buth, butw,buth, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky");
uiDefButF(block, NUMSLI, 0, "Width Fade ", butx,buty-=buth, butw,buth, &ma->strand_widthfade, 0.0, 2.0, 2, 0, "Transparency along the width of the strand");
uiDefBut(block, TEX, B_MATPRV, "UV:", butx,buty-=buth,butw,buth, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override");
uiBlockSetDirection(block, UI_TOP);