Bicubic bump map filtering.

This commit introduces bicubic bump map capabilities for the viewport for OpenGL 3.0+ capable GPUs. 

To use the functionality change the bump mapping method to "best quality"
Previous "best quality" setting becomes "medium quality" now.
For non OpenGL 3.0 GPUs this becomes the same as "medium quality"

Also:
* added tooltip descriptions to the bump method settings.
* modified the shader to ommit extraneous matrix multiplications for matrices already provided by OpenGL.

Bicubic shader by Morten Mikkelsen. Thanks a lot!

Oh...and FIRST!
This commit is contained in:
Antony Riakiotakis 2011-12-15 13:58:09 +00:00
parent 030694b260
commit 6ccc605660
11 changed files with 1745 additions and 1456 deletions

View File

@ -1056,7 +1056,7 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
# the space setting is supported for: derivative-maps + bump-maps (DEFAULT,BEST_QUALITY), not for normal-maps
sub = row.row()
sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_LOW_QUALITY', 'BUMP_MEDIUM_QUALITY', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
sub.prop(tex, "bump_objectspace", text="Space")

View File

@ -903,7 +903,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
/* always get derivatives for these textures */
if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) ma->texco |= TEXCO_OSA;
else if(mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1;
else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1;

View File

@ -61,6 +61,8 @@ int GPU_print_error(const char *str);
int GPU_glsl_support(void);
int GPU_non_power_of_two_support(void);
int GPU_color_depth(void);
void GPU_code_generate_glsl_lib(void);
int GPU_bicubic_bump_support(void);
/* GPU Types */

View File

@ -59,6 +59,10 @@
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_vertex_glsl[];
static char *glsl_material_library = NULL;
/* structs and defines */
static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
@ -229,7 +233,7 @@ GPUFunction *GPU_lookup_function(const char *name)
{
if(!FUNCTION_HASH) {
FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "GPU_lookup_function gh");
gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl);
gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
/*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
}
@ -248,6 +252,9 @@ void GPU_extensions_exit(void)
BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
FUNCTION_HASH = NULL;
}
if(glsl_material_library)
MEM_freeN(glsl_material_library);
/*if(FUNCTION_PROTOTYPES) {
MEM_freeN(FUNCTION_PROTOTYPES);
FUNCTION_PROTOTYPES = NULL;
@ -640,6 +647,35 @@ static char *code_generate_vertex(ListBase *nodes)
return code;
}
int GPU_bicubic_bump_support(void){
return GLEW_ARB_texture_gather && GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
}
void GPU_code_generate_glsl_lib(void){
DynStr *ds;
/* only initialize the library once */
if(glsl_material_library)
return;
ds = BLI_dynstr_new();
if(GPU_bicubic_bump_support()){
BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
"#version 130\n"
"#extension GL_ARB_texture_gather: enable\n"
"#extension GL_ARB_texture_query_lod: enable\n"
"#define BUMP_BICUBIC\n");
}
BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
glsl_material_library = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
}
/* GPU pass binding/unbinding */
GPUShader *GPU_pass_shader(GPUPass *pass)
@ -1318,7 +1354,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
/* generate code and compile with opengl */
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
vertexcode = code_generate_vertex(nodes);
shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/
/* failed? */
if (!shader) {
@ -1335,7 +1371,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->vertexcode = vertexcode;
pass->libcode = datatoc_gpu_shader_material_glsl;
pass->libcode = glsl_material_library;
/* extract dynamic inputs and throw away nodes */
GPU_nodes_extract_dynamic_inputs(pass, nodes);

View File

@ -1086,7 +1086,7 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn);
}
} else if( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) || found_deriv_map) {
} else if( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) || found_deriv_map) {
/* ntap bumpmap image */
int iBumpSpace;
float ima_x, ima_y;
@ -1184,10 +1184,21 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link( mat, "mtex_bump_tap3",
texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
&dBs, &dBt );
else
GPU_link( mat, "mtex_bump_tap5",
else if( mtex->texflag & MTEX_5TAP_BUMP )
GPU_link( mat, "mtex_bump_tap5",
texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
&dBs, &dBt );
else if( mtex->texflag & MTEX_BICUBIC_BUMP ){
if(GPU_bicubic_bump_support()){
GPU_link( mat, "mtex_bump_bicubic",
texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
&dBs, &dBt );
}else{
GPU_link( mat, "mtex_bump_tap5",
texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
&dBs, &dBt );
}
}
if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {

View File

@ -1152,8 +1152,8 @@ void mtex_bump_init_objspace( vec3 surf_pos, vec3 surf_norm,
out float fPrevMagnitude_out, out vec3 vNacc_out,
out vec3 vR1, out vec3 vR2, out float fDet )
{
mat3 obj2view = to_mat3(mView * mObj);
mat3 view2obj = to_mat3(mObjInv * mViewInv);
mat3 obj2view = to_mat3(gl_ModelViewMatrix);
mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
vec3 vSigmaS = view2obj * dFdx( surf_pos );
vec3 vSigmaT = view2obj * dFdy( surf_pos );
@ -1225,6 +1225,84 @@ void mtex_bump_tap3( vec3 texco, sampler2D ima, float hScale,
dBt = hScale * (Hul - Hll);
}
#ifdef BUMP_BICUBIC
void mtex_bump_bicubic( vec3 texco, sampler2D ima, float hScale,
out float dBs, out float dBt )
{
vec2 TexDx = dFdx(texco.xy);
vec2 TexDy = dFdy(texco.xy);
vec2 STl = texco.xy - 0.5 * TexDx ;
vec2 STr = texco.xy + 0.5 * TexDx ;
vec2 STd = texco.xy - 0.5 * TexDy ;
vec2 STu = texco.xy + 0.5 * TexDy ;
float Hl = texture2D(ima, STl).x;
float Hr = texture2D(ima, STr).x;
float Hd = texture2D(ima, STd).x;
float Hu = texture2D(ima, STu).x;
vec2 dHdxy = vec2(Hr - Hl, Hu - Hd);
float fBlend = clamp(1.0-textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
if(fBlend!=0.0)
{
// the derivative of the bicubic sampling of level 0
ivec2 vDim;
vDim = textureSize(ima, 0);
vec2 fTexLoc = vDim*texco.xy-vec2(0.5,0.5);
ivec2 iTexLoc = ivec2(floor(fTexLoc));
vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0); // sat just to be pedantic
ivec2 iTexLocMod = iTexLoc + ivec2(-1, -1);
/*******************************************************************************************
* This block will replace the one below when one channel textures are properly supported. *
*******************************************************************************************
vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim );
vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim );
vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim );
vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim );
mat4 H = mat4(vSamplesUL.w, vSamplesUL.x, vSamplesLL.w, vSamplesLL.x,
vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y,
vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x,
vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y);
*/
mat4 H;
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
mtex_rgbtoint(texelFetch(ima, (iTexLocMod + ivec2(i,j)), 0), H[i][j]);
}
}
float x = t.x, y = t.y;
float x2 = x * x, x3 = x2 * x, y2 = y * y, y3 = y2 * y;
vec4 X = vec4(-0.5*(x3+x)+x2, 1.5*x3-2.5*x2+1, -1.5*x3+2*x2+0.5*x, 0.5*(x3-x2));
vec4 Y = vec4(-0.5*(y3+y)+y2, 1.5*y3-2.5*y2+1, -1.5*y3+2*y2+0.5*y, 0.5*(y3-y2));
vec4 dX = vec4(-1.5*x2+2*x-0.5, 4.5*x2-5*x, -4.5*x2+4*x+0.5, 1.5*x2-x);
vec4 dY = vec4(-1.5*y2+2*y-0.5, 4.5*y2-5*y, -4.5*y2+4*y+0.5, 1.5*y2-y);
// complete derivative in normalized coordinates (mul by vDim)
vec2 dHdST = vDim * vec2(dot(Y, H * dX), dot(dY, H * X));
// transform derivative to screen-space
vec2 dHdxy_bicubic = vec2( dHdST.x * TexDx.x + dHdST.y * TexDx.y,
dHdST.x * TexDy.x + dHdST.y * TexDy.y );
// blend between the two
dHdxy = dHdxy*(1-fBlend) + dHdxy_bicubic*fBlend;
}
dBs = hScale * dHdxy.x;
dBt = hScale * dHdxy.y;
}
#endif
void mtex_bump_tap5( vec3 texco, sampler2D ima, float hScale,
out float dBs, out float dBt )
{

File diff suppressed because it is too large Load Diff

View File

@ -494,6 +494,7 @@ typedef struct ColorMapping {
#define MTEX_BUMP_OBJECTSPACE 1024
#define MTEX_BUMP_TEXTURESPACE 2048
/* #define MTEX_BUMP_FLIPPED 4096 */ /* UNUSED */
#define MTEX_BICUBIC_BUMP 8192
/* blendtype */
#define MTEX_BLEND 0

View File

@ -413,8 +413,10 @@ static void rna_def_material_mtex(BlenderRNA *brna)
static EnumPropertyItem prop_bump_method_items[] = {
{0, "BUMP_ORIGINAL", 0, "Original", ""},
{MTEX_COMPAT_BUMP, "BUMP_COMPATIBLE", 0, "Compatible", ""},
{MTEX_3TAP_BUMP, "BUMP_DEFAULT", 0, "Default", ""},
{MTEX_5TAP_BUMP, "BUMP_BEST_QUALITY", 0, "Best Quality", ""},
{MTEX_3TAP_BUMP, "BUMP_LOW_QUALITY", 0, "Low Quality", "Use 3 tap filtering"},
{MTEX_5TAP_BUMP, "BUMP_MEDIUM_QUALITY", 0, "Medium Quality", "Use 5 tap filtering"},
{MTEX_BICUBIC_BUMP, "BUMP_BEST_QUALITY", 0, "Best Quality", "Use bicubic filtering. Requires OpenGL 3.0+. "
"It will fall back on medium setting for other systems"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem prop_bump_space_items[] = {

View File

@ -2191,7 +2191,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP);
use_compat_bump= (mtex->texflag & MTEX_COMPAT_BUMP);
use_ntap_bump= ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP))!=0 || found_deriv_map!=0) ? 1 : 0;
use_ntap_bump= ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP))!=0 || found_deriv_map!=0) ? 1 : 0;
/* XXX texture node trees don't work for this yet */
if(tex->nodetree && tex->use_nodes) {

View File

@ -176,6 +176,7 @@ void WM_init(bContext *C, int argc, const char **argv)
GPU_extensions_init();
GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP));
GPU_set_anisotropic(U.anisotropic_filter);
GPU_code_generate_glsl_lib();
UI_init();
}