diff options
author | Morten Mikkelsen <mikkelsen7@gmail.com> | 2011-12-10 03:26:06 +0400 |
---|---|---|
committer | Morten Mikkelsen <mikkelsen7@gmail.com> | 2011-12-10 03:26:06 +0400 |
commit | 965c287630b7528a4a0b146212e8f1783a904948 (patch) | |
tree | d54baf4bcaaadc72c6910a0dd48705721bdea5d3 | |
parent | 82480e99954f3618e953c5f669577efd72ba3f1f (diff) |
fixes scale on derivative maps
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 158 | ||||
-rw-r--r-- | source/blender/gpu/GPU_material.h | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 49 | ||||
-rw-r--r-- | source/blender/python/intern/gpu.c | 1 | ||||
-rw-r--r-- | source/blender/render/intern/source/render_texture.c | 21 | ||||
-rw-r--r-- | source/gameengine/Ketsji/BL_BlenderShader.cpp | 3 |
9 files changed, 214 insertions, 31 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 429d5e84785..5f451ce7821 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -94,6 +94,7 @@ struct DerivedMesh { BVHCache bvhCache; struct GPUDrawObject *drawObject; DerivedMeshType type; + float auto_bump_scale; /* Misc. Queries */ @@ -578,6 +579,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); void DM_add_tangent_layer(DerivedMesh *dm); +void DM_calc_auto_bump_scale(DerivedMesh *dm); /* Set object's bounding box based on DerivedMesh min/max data */ void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4b91911a6ab..c829d840ace 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -184,6 +184,7 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, DM_init_funcs(dm); dm->needsFree = 1; + dm->auto_bump_scale = -1.0f; } void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, @@ -1831,6 +1832,159 @@ void DM_add_tangent_layer(DerivedMesh *dm) MEM_freeN(vtangents); } +void DM_calc_auto_bump_scale(DerivedMesh *dm) +{ + int totvert= dm->getNumVerts(dm); + int totface= dm->getNumFaces(dm); + + MVert * mvert = dm->getVertArray(dm); + MFace * mface = dm->getFaceArray(dm); + MTFace * mtface = dm->getFaceDataArray(dm, CD_MTFACE); + + if(mtface) + { + double dsum = 0.0; + int nr_accumulated = 0; + int f; + + for ( f=0; f<totface; f++ ) + { + { + float * verts[4], * tex_coords[4]; + const int nr_verts = mface[f].v4!=0 ? 4 : 3; + int i, is_degenerate; + + verts[0]=mvert[mface[f].v1].co; verts[1]=mvert[mface[f].v2].co; verts[2]=mvert[mface[f].v3].co; + tex_coords[0]=mtface[f].uv[0]; tex_coords[1]=mtface[f].uv[1]; tex_coords[2]=mtface[f].uv[2]; + if(nr_verts==4) + { + verts[3]=mvert[mface[f].v4].co; + tex_coords[3]=mtface[f].uv[3]; + } + + // discard degenerate faces + is_degenerate = 0; + if( equals_v3v3(verts[0], verts[1]) || equals_v3v3(verts[0], verts[2]) || equals_v3v3(verts[1], verts[2]) || + equals_v2v2(tex_coords[0], tex_coords[1]) || equals_v2v2(tex_coords[0], tex_coords[2]) || equals_v2v2(tex_coords[1], tex_coords[2]) ) + { + is_degenerate = 1; + } + + // verify last vertex as well if this is a quad + if ( is_degenerate==0 && nr_verts==4 ) + { + if( equals_v3v3(verts[3], verts[0]) || equals_v3v3(verts[3], verts[1]) || equals_v3v3(verts[3], verts[2]) || + equals_v2v2(tex_coords[3], tex_coords[0]) || equals_v2v2(tex_coords[3], tex_coords[1]) || equals_v2v2(tex_coords[3], tex_coords[2]) ) + { + is_degenerate = 1; + } + + // verify the winding is consistent + if ( is_degenerate==0 ) + { + float prev_edge[2]; + int is_signed = 0; + sub_v2_v2v2(prev_edge, tex_coords[0], tex_coords[3]); + + i = 0; + while ( is_degenerate==0 && i<4 ) + { + float cur_edge[2], signed_area; + sub_v2_v2v2(cur_edge, tex_coords[(i+1)&0x3], tex_coords[i]); + signed_area = prev_edge[0]*cur_edge[1] - prev_edge[1]*cur_edge[0]; + if ( i==0 ) is_signed = signed_area<0.0f ? 1 : 0; + else if((is_signed!=0)!=(signed_area<0.0f)) is_degenerate=1; + + if ( is_degenerate==0 ) + { + copy_v2_v2(prev_edge, cur_edge); + ++i; + } + } + } + } + + // proceed if not a degenerate face + if ( is_degenerate==0 ) + { + int nr_tris_to_pile=0; + // quads split at shortest diagonal + int offs = 0; // initial triangulation is 0,1,2 and 0, 2, 3 + if ( nr_verts==4 ) + { + float pos_len_diag0, pos_len_diag1; + float vtmp[3]; + sub_v3_v3v3(vtmp, verts[2], verts[0]); + pos_len_diag0 = dot_v3v3(vtmp, vtmp); + sub_v3_v3v3(vtmp, verts[3], verts[1]); + pos_len_diag1 = dot_v3v3(vtmp, vtmp); + + if(pos_len_diag1<pos_len_diag0) + offs=1; // alter split + else if(pos_len_diag0==pos_len_diag1) // do UV check instead + { + float tex_len_diag0, tex_len_diag1; + + sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]); + tex_len_diag0 = dot_v2v2(vtmp, vtmp); + sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]); + tex_len_diag1 = dot_v2v2(vtmp, vtmp); + + if(tex_len_diag1<tex_len_diag0) + { + offs=1; // alter split + } + } + } + nr_tris_to_pile = nr_verts-2 ; + if ( nr_tris_to_pile==1 || nr_tris_to_pile==2 ) + { + const int indices[] = {offs+0, offs+1, offs+2, offs+0, offs+2, (offs+3)&0x3 }; + int t; + for ( t=0; t<nr_tris_to_pile; t++ ) + { + float f2x_area_uv; + float * p0 = verts[indices[t*3+0]]; + float * p1 = verts[indices[t*3+1]]; + float * p2 = verts[indices[t*3+2]]; + + float edge_t0[2], edge_t1[2]; + sub_v2_v2v2(edge_t0, tex_coords[indices[t*3+1]], tex_coords[indices[t*3+0]]); + sub_v2_v2v2(edge_t1, tex_coords[indices[t*3+2]], tex_coords[indices[t*3+0]]); + + f2x_area_uv = fabsf(edge_t0[0]*edge_t1[1] - edge_t0[1]*edge_t1[0]); + if ( f2x_area_uv>FLT_EPSILON ) + { + float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio; + sub_v3_v3v3(v0, p1, p0); + sub_v3_v3v3(v1, p2, p0); + cross_v3_v3v3(norm, v0, v1); + + f2x_surf_area = len_v3(norm); + fsurf_ratio = f2x_surf_area/f2x_area_uv; // tri area divided by texture area + + ++nr_accumulated; + dsum += (double)(fsurf_ratio); + } + } + } + } + } + } + + // finalize + { + const float avg_area_ratio = (nr_accumulated>0) ? ((float)(dsum / nr_accumulated)) : 1.0f; + const float use_as_render_bump_scale = sqrtf(avg_area_ratio); // use width of average surface ratio as your bump scale + dm->auto_bump_scale = use_as_render_bump_scale; + } + } + else + { + dm->auto_bump_scale = 1.0f; + } +} + void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) { CustomData *vdata, *fdata, *tfdata = NULL; @@ -1851,6 +2005,10 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, else tfdata = fdata; + /* calc auto bump scale if necessary */ + if(dm->auto_bump_scale<=0.0f) + DM_calc_auto_bump_scale(dm); + /* add a tangent layer if necessary */ for(b = 0; b < gattribs->totlayer; b++) if(gattribs->layer[b].type == CD_TANGENT) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 418bea5fe9c..5689f02d2d7 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -83,7 +83,8 @@ typedef enum GPUBuiltin { GPU_INVERSE_OBJECT_MATRIX = 8, GPU_VIEW_POSITION = 16, GPU_VIEW_NORMAL = 32, - GPU_OBCOLOR = 64 + GPU_OBCOLOR = 64, + GPU_AUTO_BUMPSCALE = 128 } GPUBuiltin; typedef enum GPUBlendMode { @@ -129,7 +130,7 @@ void GPU_material_free(struct Material *ma); void GPU_materials_free(void); void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap); -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]); +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale); void GPU_material_unbind(GPUMaterial *material); int GPU_material_bound(GPUMaterial *material); @@ -162,6 +163,7 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_OBJECT_VIEWIMAT = 3, GPU_DYNAMIC_OBJECT_IMAT = 4, GPU_DYNAMIC_OBJECT_COLOR = 5, + GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 15, GPU_DYNAMIC_LAMP_FIRST = 6, GPU_DYNAMIC_LAMP_DYNVEC = 6, GPU_DYNAMIC_LAMP_DYNCO = 7, diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 185f9eb185e..05c459b703d 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -344,6 +344,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin) return "varnormal"; else if(builtin == GPU_OBCOLOR) return "unfobcolor"; + else if(builtin == GPU_AUTO_BUMPSCALE) + return "unfobautobumpscale"; else return ""; } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 3cd3cde8aad..6a11010002f 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -60,6 +60,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_DerivedMesh.h" #include "BLI_threads.h" #include "BLI_blenlib.h" @@ -1159,7 +1160,7 @@ int GPU_enable_material(int nr, void *attribs) gpumat = GPU_material_from_blender(GMS.gscene, mat); GPU_material_vertex_attributes(gpumat, gattribs); GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT)); - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col, GMS.gob->derivedFinal->auto_bump_scale); GMS.gboundmat= mat; /* for glsl use alpha blend mode, unless it's set to solid and diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 397c0e32c69..2d8487deb71 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -94,7 +94,7 @@ struct GPUMaterial { /* for passing uniforms */ int viewmatloc, invviewmatloc; int obmatloc, invobmatloc; - int obcolloc; + int obcolloc, obautobumpscaleloc; ListBase lamps; }; @@ -212,7 +212,8 @@ static int GPU_material_construct_end(GPUMaterial *material) material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX)); if(material->builtins & GPU_OBCOLOR) material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR)); - + if(material->builtins & GPU_AUTO_BUMPSCALE) + material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE)); return 1; } @@ -273,7 +274,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim } } -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]) +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale) { if(material->pass) { GPUShader *shader = GPU_pass_shader(material->pass); @@ -300,7 +301,9 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float v CLAMP(col[3], 0.0f, 1.0f); GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); } - + if(material->builtins & GPU_AUTO_BUMPSCALE) { + GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale); + } /* update lamps */ for(nlink=material->lamps.first; nlink; nlink=nlink->next) { lamp= nlink->data; @@ -1087,8 +1090,7 @@ static void do_material_tex(GPUShadeInput *shi) /* ntap bumpmap image */ int iBumpSpace; float ima_x, ima_y; - float hScale = 0.1f; // compatibility adjustment factor for all bumpspace types - float hScaleTex = 13.0f; // factor for scaling texspace bumps + float hScale; float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant float aspect = 1.0f; @@ -1096,16 +1098,35 @@ static void do_material_tex(GPUShadeInput *shi) GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION); GPUNodeLink *vR1, *vR2; GPUNodeLink *dBs, *dBt, *fDet; - + + hScale = 0.1; // compatibility adjustment factor for all bumpspace types if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) - hScale = hScaleTex; + hScale = 13.0f; // factor for scaling texspace bumps + else if(found_deriv_map!=0) + hScale = 1.0f; + + // resolve texture resolution + if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { + ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); + ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only + if(ibuf) { + ima_x= ibuf->x; + ima_y= ibuf->y; + aspect = ((float) ima_y) / ima_x; + } + } // The negate on norfac is done because the // normal in the renderer points inward which corresponds // to inverting the bump map. Should this ever change // this negate must be removed. norfac = -hScale * mtex->norfac; + if(found_deriv_map) norfac /= sqrtf(ima_x*ima_y); + tnorfac = GPU_uniform(&norfac); + + if(found_deriv_map) + GPU_link(mat, "math_multiply", tnorfac, GPU_builtin(GPU_AUTO_BUMPSCALE), &tnorfac); if(GPU_link_changed(stencil)) GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); @@ -1152,17 +1173,6 @@ static void do_material_tex(GPUShadeInput *shi) iBumpSpacePrev = iBumpSpace; } - - // resolve texture resolution - if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { - ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); - ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only - if(ibuf) { - ima_x= ibuf->x; - ima_y= ibuf->y; - aspect = ((float) ima_y) / ima_x; - } - } if(found_deriv_map) { @@ -1703,6 +1713,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F }, { GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F }, { GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F }, + { GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F }, { 0 } }; diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 57ce7b59067..0da63297077 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -87,6 +87,7 @@ PyInit_gpu(void) PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index ae48b0f777f..e55d2676b17 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1932,11 +1932,13 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T float *nvec = texres->nor; texres->nor = NULL; - 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(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); @@ -1958,15 +1960,18 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T } if(found_deriv_map) { - float dBdu, dBdv; + float dBdu, dBdv, auto_bump; 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); + + auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale; + auto_bump /= sqrtf((float) (dimx*dimy)); // this variant using a derivative map is described here // http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html - dBdu = Hscale*dimx*(2*texres->tr-1); - dBdv = Hscale*dimy*(2*texres->tg-1); + 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]; diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 6680e9556b9..52c9846772d 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -8,6 +8,7 @@ #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_DerivedMesh.h" #include "BL_BlenderShader.h" #include "BL_Material.h" @@ -146,7 +147,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) else obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol); + GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, ms.m_pDerivedMesh->auto_bump_scale); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } |