Displacement map

- changed code to make use of actual textures, not the hackish
  'externtex', which is only for tools
- added a 'displacement' vector in ShadeInput, and moved calculation of
  displacement vector to texture.c itself. So it works with stencil, but
  also for options as 'add', 'mult' and 'sub'.
- for RGB textures it uses the brightness value of color for displace
- for stucci, and plugin textures returning a normal, it uses that

- Also: wrote call in end of preparing renderfaces, to split non-flat
  quad faces in triangles. gives a lot fewer errors in displace textures,
  but also raytracing irregular subsurfs goes better now.

- texture mapping that works for displace: orco, sticky, global, obj, normal.
  UV not yet. Reflection-displace? uhh! :)
This commit is contained in:
Ton Roosendaal
2004-01-05 20:25:07 +00:00
parent f78c0478f5
commit 1170f5f6ed
4 changed files with 166 additions and 120 deletions

View File

@@ -548,16 +548,6 @@ void init_render_material(Material *ma)
for(a=0; a<8; a++) {
mtex= ma->mtex[a];
if(mtex && mtex->tex) {
/* force std. ref mapping for envmap */
if(mtex->tex->type==TEX_ENVMAP) {
/* mtex->texco= TEXCO_REFL; */
/* mtex->projx= PROJ_X; */
/* mtex->projy= PROJ_Y; */
/* mtex->projz= PROJ_Z; */
/* mtex->mapping= MTEX_FLAT; */
}
/* do not test for mtex->object and set mtex->texco at TEXCO_ORCO: mtex is linked! */
ma->texco |= mtex->texco;
ma->mapto |= mtex->mapto;

View File

@@ -58,7 +58,7 @@ typedef struct ShadeInput
struct VlakRen *vlr;
float co[3];
float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3];
float vn[3], view[3], refcol[4];
float vn[3], view[3], refcol[4], displace[3];
short osatex;
} ShadeInput;

View File

@@ -918,7 +918,7 @@ void do_material_tex(ShadeInput *shi)
}
/* de pointer defines if bumping happens */
if(mtex->mapto & MAP_NORM) {
if(mtex->mapto & (MAP_NORM|MAP_DISPLACE)) {
tex->nor= norvec;
norvec[0]= norvec[1]= norvec[2]= 0.0;
}
@@ -1159,6 +1159,53 @@ void do_material_tex(ShadeInput *shi)
calc_R_ref(shi);
}
}
if( mtex->mapto & MAP_DISPLACE ) {
/* we check for == here, not '&', to limit it to stucci for now */
/* otherwise image texture bump is used, which is plain ugly */
if(rgbnor == TEX_NOR) {
if(tex->nor) {
if(mtex->maptoneg & MAP_DISPLACE) tex->norfac= -mtex->norfac;
else tex->norfac= mtex->norfac;
shi->displace[0]+= Tnor*tex->norfac*tex->nor[0];
shi->displace[1]+= Tnor*tex->norfac*tex->nor[1];
shi->displace[2]+= Tnor*tex->norfac*tex->nor[2];
}
}
else {
if(rgbnor & TEX_RGB) {
if(Talpha) Tin= Ta;
else Tin= (0.35*Tr+0.45*Tg+0.2*Tb);
}
if(mtex->maptoneg & MAP_DISPLACE) {
factt= 1.0-mtex->varfac; facmm= mtex->varfac;
}
else {
factt= mtex->varfac; facmm= 1.0-mtex->varfac;
}
factt*= (Tin-0.5);
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;
else 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) {
if(rgbnor & TEX_RGB) {

View File

@@ -145,10 +145,10 @@ static void init_render_object(Object *ob);
static HaloRen *initstar(float *vec, float hasize);
/* Displacement Texture */
void displace_render_face(VlakRen *vlr, int tex, float scale);
void displace_render_face(VlakRen *vlr, float scale);
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
short test_for_displace(Object *ob);
void displace_render_vert(VertRen *vr, MTex *mtex, short mask, float scale);
void displace_render_vert(ShadeInput *shi, VertRen *vr, float scale);
/* more prototypes for autosmoothing below */
@@ -1107,7 +1107,6 @@ static void init_render_displist_mesh(Object *ob)
int a, b, flipnorm= -1, need_orco=0, startvert, p1, p2, p3, p4;
int old_totvert= R.totvert, numvert=0;
int old_totvlak= R.totvlak, numface=0;
short displace_chanels=0;
me= ob->data;
@@ -1130,9 +1129,6 @@ static void init_render_displist_mesh(Object *ob)
}
}
/* Test to see if there are displacement chanels */
displace_chanels=test_for_displace(ob);
dl= me->disp.first;
/* Force a displist rebuild if this is a subsurf and we have a different subdiv level */
@@ -1325,7 +1321,8 @@ static void init_render_displist_mesh(Object *ob)
dl= dl->next;
}
if (displace_chanels) {
/* Test to see if there are displacement chanels */
if(test_for_displace(ob)) {
do_displacement(ob, old_totvlak, numface, old_totvert, numvert );
}
@@ -1573,9 +1570,6 @@ static void init_render_mesh(Object *ob)
}
}
/* Test to see if there are displacement chanels */
displace_chanels=test_for_displace(ob);
if(me->orco==0) {
need_orco= 0;
for(a=1; a<=ob->totcol; a++) {
@@ -1693,7 +1687,7 @@ static void init_render_mesh(Object *ob)
if(mface->v4) vlr->v4= RE_findOrAddVert(vertofs+mface->v4);
else vlr->v4= 0;
/* render normalen are inverted in render */
/* render normals are inverted in render */
if(vlr->v4) vlr->len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
vlr->v1->co, vlr->n);
else vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co,
@@ -1728,40 +1722,6 @@ static void init_render_mesh(Object *ob)
vlr->tface= tface;
/* test if rendering as a quad or triangle */
if(vlr->v4) {
if(ma->mode & MA_WIRE);
else {
CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor);
if(flipnorm) {
nor[0]= -nor[0];
nor[1]= -nor[1];
nor[2]= -nor[2];
}
xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2];
if( xn < 0.9990 ) {
/* recalc this nor, previous calc was with calcnormfloat4 */
if(flipnorm) CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
else CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
vlr1= RE_findOrAddVlak(R.totvlak++);
*vlr1= *vlr;
vlr1->flag |= R_FACE_SPLIT;
VECCOPY(vlr1->n, nor);
vlr1->v2= vlr->v3;
vlr1->v3= vlr->v4;
vlr->v4= vlr1->v4= 0;
vlr1->puno= 0;
if(vlr->puno & ME_FLIPV1) vlr1->puno |= ME_FLIPV1;
if(vlr->puno & ME_FLIPV3) vlr1->puno |= ME_FLIPV2;
if(vlr->puno & ME_FLIPV4) vlr1->puno |= ME_FLIPV3;
}
}
}
}
}
else if(mface->v2 && (ma->mode & MA_WIRE)) {
@@ -1789,7 +1749,7 @@ static void init_render_mesh(Object *ob)
}
}
if (displace_chanels) {
if(test_for_displace(ob)) {
do_displacement(ob, totvlako, end, totverto, me->totvert );
do_puno=1;
}
@@ -2891,6 +2851,52 @@ void RE_freeRotateBlenderScene(void)
R.totvlak=R.totvert=R.totlamp=R.tothalo= 0;
}
static void check_non_flat_quads(void)
{
VlakRen *vlr, *vlr1;
float nor[3], xn;
int a, flipnorm;
for(a=R.totvlak-1; a>=0; a--) {
vlr= RE_findOrAddVlak(a);
/* test if rendering as a quad or triangle */
if(vlr->v4) {
if(vlr->mat->mode & MA_WIRE);
else {
/* blahj, render normals are inverted in render */
CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor);
xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2];
if( fabs(xn) < 0.9990 ) {
if( xn<0.0 ) flipnorm= 1; else flipnorm= 0;
/* recalc this nor, previous calc was with calcnormfloat4 */
if(flipnorm) CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
else CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
vlr1= RE_findOrAddVlak(R.totvlak++);
*vlr1= *vlr;
vlr1->flag |= R_FACE_SPLIT;
VECCOPY(vlr1->n, nor); /* why not flipnorm here?! */
vlr1->v2= vlr->v3;
vlr1->v3= vlr->v4;
vlr->v4= vlr1->v4= 0;
vlr1->puno= 0;
if(vlr->puno & ME_FLIPV1) vlr1->puno |= ME_FLIPV1;
if(vlr->puno & ME_FLIPV3) vlr1->puno |= ME_FLIPV2;
if(vlr->puno & ME_FLIPV4) vlr1->puno |= ME_FLIPV3;
}
}
}
}
}
extern int slurph_opt; /* key.c */
extern ListBase duplilist;
@@ -3112,8 +3118,7 @@ void RE_rotateBlenderScene(void)
if(blender_test_break()) return;
/* if(R.totlamp==0) defaultlamp(); */
check_non_flat_quads();
set_normalflags();
}
@@ -3121,56 +3126,46 @@ void RE_rotateBlenderScene(void)
/* **************************************************************** */
/* Displacement mapping */
/* **************************************************************** */
extern float Tin, Tr, Tg, Tb;
short test_for_displace(Object *ob){
/* Produce bitfield indicating which textures are displacement textures. */
short test_for_displace(Object *ob)
{
/* return 1 when this object uses displacement textures. */
Material *ma;
short result = 0;
int i, j;
int i;
for (i=1; i<=ob->totcol; i++) {
ma=give_render_material(ob, i);
if (ma) for(j=0; j<8; j++){
if (ma->mtex[j] && (ma->mtex[j]->mapto & MAP_DISPLACE)){
result |= 1<<j;
}
}
/* ma->mapto is ORed total of all mapto channels */
if(ma && (ma->ren->mapto & MAP_DISPLACE)) return 1;
}
return result;
return 0;
}
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert ){
int i, j;
Material *ma;
MTex *mtex;
float co[3]={0,0,0}, min[3]={1e9, 1e9, 1e9}, max[3]={-1e9, -1e9, -1e9};
float scale=1.0f;
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert )
{
VertRen *vr;
VlakRen *vlr;
Mesh *me;
float min[3]={1e9, 1e9, 1e9}, max[3]={-1e9, -1e9, -1e9};
float scale=1.0f;
int i;
minmax_object(ob, min, max);
VecSubf(min, max, min);
scale=MAX3(min[0], min[1], min[2]); /*Overall scale of obj */
scale= MAX3(min[0], min[1], min[2]); /*Overall scale of obj */
/* calculate vertex normals */
//normalenrender(startvert, startface);
for(i=startvert; i<startvert+numvert; i++){ /* Clear vert flags */
vr=RE_findOrAddVert(i);
vr->flag=0;
vr= RE_findOrAddVert(i);
vr->flag= 0;
}
for(i=startface; i<startface+numface; i++){
vlr=RE_findOrAddVlak(i);
for(j=0; j<8; j++){
mtex = vlr->mat->mtex[j];
if ((mtex)&&( vlr->mat->mtex[j]->mapto & MAP_DISPLACE ) ) displace_render_face(vlr, j, scale);
}
displace_render_face(vlr, scale);
/* Recaluclate the face normal */
if(vlr->v4) vlr->len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
@@ -3181,55 +3176,69 @@ void do_displacement(Object *ob, int startface, int numface, int startvert, int
}
}
void displace_render_face(VlakRen *vlr, int tex, float scale){
MTex *mtex;
int mask;
float dp;
VlakRen vlr2;
void displace_render_face(VlakRen *vlr, float scale)
{
ShadeInput shi;
VertRen vr;
mask = 1<<tex; /* Displace vert once per displace texture channel */
mtex=vlr->mat->mtex[tex];
/* set up shadeinput struct for multitex() */
//VECCOPY(R.vn, vlr->n); /* extertex() needs face/puno */
//R.vlr=vlr;
shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */
shi.vlr= vlr; /* current render face */
shi.mat= vlr->mat; /* current input material */
shi.matren= shi.mat->ren; /* material temp block where output is written into */
/* Displace the verts, flag is set when done */
/* Displace the verts */
if (! (vlr->v1->flag)) displace_render_vert(&shi, vlr->v1, scale);
if (! (vlr->v1->flag & mask)) displace_render_vert(vlr->v1, mtex, mask, scale);
if (! (vlr->v2->flag) ) displace_render_vert(&shi, vlr->v2, scale);
if (! (vlr->v2->flag & mask) ) displace_render_vert(vlr->v2, mtex, mask, scale);
if (! (vlr->v3->flag & mask)) displace_render_vert(vlr->v3, mtex, mask, scale);
if (! (vlr->v3->flag)) displace_render_vert(&shi, vlr->v3, scale);
if (vlr->v4) {
if (!(vlr->v4->flag & mask)) displace_render_vert(vlr->v4, mtex, mask, scale);
if (! (vlr->v4->flag)) displace_render_vert(&shi, vlr->v4, scale);
}
}
void displace_render_vert(VertRen *vr, MTex *mtex, short mask, float scale){
float co[3]={0,0,0}, dp, sample[3];
if ((mtex->texco & TEXCO_ORCO) && (vr->orco)) {
VECCOPY(co, vr->orco);
void displace_render_vert(ShadeInput *shi, VertRen *vr, float scale)
{
short texco= shi->matren->texco;
/* shi->co is current render coord, just make sure at least some vector is here */
VECCOPY(shi->co, vr->co);
/* vertex normal is used for textures type 'col' and 'var' */
VECCOPY(shi->vn, vr->n);
/* set all rendercoords, 'texco' is an ORed value for all textures needed */
if ((texco & TEXCO_ORCO) && (vr->orco)) {
VECCOPY(shi->lo, vr->orco);
}
else if ((mtex->texco & TEXCO_STICKY) && (vr->sticky)) {
VECCOPY(co, vr->sticky);
if ((texco & TEXCO_STICKY) && (vr->sticky)) {
VECCOPY(shi->sticky, vr->sticky);
}
else if (mtex->texco & TEXCO_GLOB) {
/* VECCOPY(co, vr->co); Interesting, but not right. */
if (texco & TEXCO_GLOB) {
VECCOPY(shi->gl, shi->co);
MTC_Mat4MulVecfl(R.viewinv, shi->gl);
}
if (texco & TEXCO_NORM) {
VECCOPY(shi->orn, shi->vn);
}
if(texco & TEXCO_REFL) {
/* not (yet?) */
}
externtex(mtex, co);
vr->co[0]+=0.25*(Tin-0.5) * vr->n[0] * mtex->varfac *scale ;
vr->co[1]+=0.25*(Tin-0.5) * vr->n[1] * mtex->varfac *scale ;
vr->co[2]+=0.25*(Tin-0.5) * vr->n[2] * mtex->varfac *scale ;
shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
vr->flag |= mask;
do_material_tex(shi);
/* 0.25 could become button once? */
vr->co[0] += 0.25*shi->displace[0] * scale ;
vr->co[1] += 0.25*shi->displace[1] * scale ;
vr->co[2] += 0.25*shi->displace[2] * scale ;
/* we just don't do this vertex again, bad luck for other face using same vertex with
different material... */
vr->flag |= 1;
}