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:
parent
030694b260
commit
6ccc605660
|
@ -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")
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue