diff options
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 50 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 104 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 54 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 46 |
5 files changed, 202 insertions, 54 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 4432627ee7e..b27a4be9f21 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -68,6 +68,9 @@ static char *glsl_material_library = NULL; static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"}; +#define LINK_IMAGE_BLENDER 1 +#define LINK_IMAGE_PREVIEW 2 + /* GLSL code parsing for finding function definitions. * These are stored in a hash for lookup when creating a material. */ @@ -339,7 +342,7 @@ static int codegen_input_has_texture(GPUInput *input) { if (input->link) return 0; - else if (input->ima) + else if (input->ima || input->prv) return 1; else return input->tex != NULL; @@ -411,6 +414,17 @@ static void codegen_set_unique_ids(ListBase *nodes) else input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); } + else if (input->prv) { + /* input is texture from preview render, assign only one texid per + * buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->prv)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv)); + } else { if (!BLI_ghash_haskey(bindhash, input->tex)) { /* input is user created texture, check tex pointer */ @@ -718,7 +732,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) continue; } - if (input->ima || input->tex) + if (input->ima || input->tex || input->prv) BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); else BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); @@ -726,7 +740,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) /* pass non-dynamic uniforms to opengl */ extract = 0; - if (input->ima || input->tex) { + if (input->ima || input->tex || input->prv) { if (input->bindtex) extract = 1; } @@ -762,11 +776,14 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) for (input=inputs->first; input; input=input->next) { if (input->ima) input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap); + else if (input->prv) + input->tex = GPU_texture_from_preview(input->prv, mipmap); if (input->tex && input->bindtex) { GPU_texture_bind(input->tex, input->texid); GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); } + } } @@ -781,7 +798,7 @@ void GPU_pass_update_uniforms(GPUPass *pass) /* pass dynamic inputs to opengl, others were removed */ for (input=inputs->first; input; input=input->next) - if (!(input->ima || input->tex)) + if (!(input->ima || input->tex || input->prv)) GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, input->dynamicvec); } @@ -799,7 +816,7 @@ void GPU_pass_unbind(GPUPass *pass) if (input->tex && input->bindtex) GPU_texture_unbind(input->tex); - if (input->ima) + if (input->ima || input->prv) input->tex = NULL; } @@ -915,9 +932,13 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; - input->ima = link->ptr1; - input->iuser = link->ptr2; - input->image_isdata = link->image_isdata; + if (link->image == LINK_IMAGE_PREVIEW) + input->prv = link->ptr1; + else { + input->ima = link->ptr1; + input->iuser = link->ptr2; + input->image_isdata = link->image_isdata; + } input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); @@ -1117,7 +1138,7 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) { GPUNodeLink *link = GPU_node_link_create(0); - link->image= 1; + link->image= LINK_IMAGE_BLENDER; link->ptr1= ima; link->ptr2= iuser; link->image_isdata= isdata; @@ -1125,6 +1146,17 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) return link; } +GPUNodeLink *GPU_image_preview(PreviewImage *prv) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->image= LINK_IMAGE_PREVIEW; + link->ptr1= prv; + + return link; +} + + GPUNodeLink *GPU_texture(int size, float *pixels) { GPUNodeLink *link = GPU_node_link_create(0); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index f61f34908c5..2e4cfe2e37c 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -43,6 +43,7 @@ struct GPUOutput; struct GPUNode; struct GPUVertexAttribs; struct GPUFrameBuffer; +struct PreviewImage; #define MAX_FUNCTION_NAME 64 #define MAX_PARAMETER 32 @@ -138,6 +139,7 @@ typedef struct GPUInput { struct Image *ima; /* image */ struct ImageUser *iuser;/* image user */ + struct PreviewImage *prv; /* preview images & icons */ int image_isdata; /* image does not contain color data */ float *dynamicvec; /* vector data in case it is dynamic */ int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 254899e6e07..90a92dbcddc 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -664,6 +664,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return *bind; } +/* Image *ima can be NULL */ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) { unsigned int *scalerect = NULL; @@ -723,7 +724,8 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - ima->tpageflag |= IMA_MIPMAP_COMPLETE; + if (ima) + ima->tpageflag |= IMA_MIPMAP_COMPLETE; } if (GLEW_EXT_texture_filter_anisotropic) @@ -1283,10 +1285,9 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPUMaterial *gpumat; GPUBlendMode alphablend; int a; - int gamma = BKE_scene_check_color_management_enabled(scene); - int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); + int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */ /* initialize state */ memset(&GMS, 0, sizeof(GMS)); @@ -1298,7 +1299,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.gob = ob; GMS.gscene = scene; - GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */ + GMS.totmat= use_matcap? 1 : ob->totcol+1; /* materials start from 1, default material is 0 */ GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */ GMS.gviewmat= rv3d->viewmat; GMS.gviewinv= rv3d->viewinv; @@ -1324,59 +1325,72 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.alphablend= GMS.alphablend_fixed; } - /* no materials assigned? */ - if (ob->totcol==0) { - gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); - + /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */ + if (use_matcap) { + GMS.gmatbuf[0] = v3d->defmaterial; + GPU_material_matcap(scene, v3d->defmaterial); + /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - - if (glsl) { - GMS.gmatbuf[0]= &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial); - } - + GMS.alphablend[0]= GPU_BLEND_SOLID; } + else { - /* setup materials */ - for (a=1; a<=ob->totcol; a++) { - /* find a suitable material */ - ma= give_current_material(ob, a); - if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); - if (ma==NULL) ma= &defmaterial; - - /* create glsl material if requested */ - gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; - - if (gpumat) { - /* do glsl only if creating it succeed, else fallback */ - GMS.gmatbuf[a]= ma; - alphablend = GPU_material_alpha_blend(gpumat, ob->col); - } - else { - /* fixed function opengl materials */ - gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + /* no materials assigned? */ + if (ob->totcol==0) { + gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); + + /* do material 1 too, for displists! */ + memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - if (GMS.use_alpha_pass) { - GMS.matbuf[a].diff[3]= ma->alpha; - alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + if (glsl) { + GMS.gmatbuf[0]= &defmaterial; + GPU_material_from_blender(GMS.gscene, &defmaterial); + } + + GMS.alphablend[0]= GPU_BLEND_SOLID; + } + + /* setup materials */ + for (a=1; a<=ob->totcol; a++) { + /* find a suitable material */ + ma= give_current_material(ob, a); + if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); + if (ma==NULL) ma= &defmaterial; + + /* create glsl material if requested */ + gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + + if (gpumat) { + /* do glsl only if creating it succeed, else fallback */ + GMS.gmatbuf[a]= ma; + alphablend = GPU_material_alpha_blend(gpumat, ob->col); } else { - GMS.matbuf[a].diff[3]= 1.0f; - alphablend = GPU_BLEND_SOLID; + /* fixed function opengl materials */ + gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + + if (GMS.use_alpha_pass) { + GMS.matbuf[a].diff[3]= ma->alpha; + alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + } + else { + GMS.matbuf[a].diff[3]= 1.0f; + alphablend = GPU_BLEND_SOLID; + } } - } - /* setting 'do_alpha_after = TRUE' indicates this object needs to be - * drawn in a second alpha pass for improved blending */ - if (do_alpha_after && !GMS.is_alpha_pass) - if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) - *do_alpha_after = TRUE; + /* setting 'do_alpha_after = TRUE' indicates this object needs to be + * drawn in a second alpha pass for improved blending */ + if (do_alpha_after && !GMS.is_alpha_pass) + if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) + *do_alpha_after = TRUE; - GMS.alphablend[a]= alphablend; + GMS.alphablend[a]= alphablend; + } } - + /* let's start with a clean state */ GPU_disable_material(); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index bc859d0ec07..0ef60aaf978 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -539,6 +539,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); GPU_update_image_time(ima, time); + /* this binds a texture, so that's why to restore it with lastbindcode */ bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata); if (ima->gputexture) { @@ -579,6 +580,59 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d return tex; } +GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) +{ + GPUTexture *tex = prv->gputexture[0]; + GLint w, h, lastbindcode; + GLuint bindcode = 0; + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); + + if (tex) + bindcode = tex->bindcode; + + /* this binds a texture, so that's why to restore it */ + if (bindcode == 0) { + GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL); + } + if (tex) { + tex->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return tex; + } + + /* error binding anything */ + if (!bindcode) { + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return NULL; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + + prv->gputexture[0]= tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error("Blender Texture"); + } + else { + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + + tex->w = w; + tex->h = h; + } + + glBindTexture(GL_TEXTURE_2D, lastbindcode); + + return tex; + +} + GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256]) { GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index f6403e9359d..9731d7a6b3a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1506,6 +1506,52 @@ static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) return outlink; } +static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma) +{ + GPUNodeLink *outlink; + + GPU_link(mat, "material_preview_matcap", GPU_uniform(&ma->r), GPU_image_preview(ma->preview), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + + return outlink; +} + +/* new solid draw mode with glsl matcaps */ +GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) +{ + GPUMaterial *mat; + GPUNodeLink *outlink; + LinkData *link; + + for (link=ma->gpumaterial.first; link; link=link->next) + if (((GPUMaterial*)link->data)->scene == scene) + return link->data; + + /* allocate material */ + mat = GPU_material_construct_begin(ma); + mat->scene = scene; + + if (ma->preview && ma->preview->rect[0]) { + outlink = gpu_material_preview_matcap(mat, ma); + } + else { + outlink = gpu_material_diffuse_bsdf(mat, ma); + } + + GPU_material_output_link(mat, outlink); + + GPU_material_construct_end(mat); + + /* note that even if building the shader fails in some way, we still keep + * it to avoid trying to compile again and again, and simple do not use + * the actual shader on drawing */ + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(&ma->gpumaterial, link); + + return mat; +} + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; |