diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_draw.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 219 |
1 files changed, 119 insertions, 100 deletions
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index aaf4037197e..05d11549656 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -49,6 +49,7 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_node_types.h" @@ -74,10 +75,13 @@ #include "BKE_subsurf.h" #include "BKE_DerivedMesh.h" +#include "GPU_basic_shader.h" #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_material.h" +#include "GPU_shader.h" +#include "GPU_texture.h" #include "PIL_time.h" @@ -728,7 +732,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int /* scale if not a power of two. this is not strictly necessary for newer * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures * Then don't bother scaling for hardware that supports NPOT textures! */ - if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || + if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || is_over_resolution_limit(rectw, recth)) { rectw = smaller_power_of_2_limit(rectw); recth = smaller_power_of_2_limit(recth); @@ -753,12 +757,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int if (use_high_bit_depth) { if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); } else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); @@ -784,12 +788,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int ImBuf *mip = ibuf->mipmap[i - 1]; if (use_high_bit_depth) { if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); else glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); } else { - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); } } } @@ -804,8 +808,6 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - /* set to modulate with vertex color */ - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (ibuf) IMB_freeImBuf(ibuf); @@ -847,8 +849,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf) 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)); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); @@ -1002,7 +1002,7 @@ void GPU_paint_set_mipmap(bool mipmap) /* check if image has been downscaled and do scaled partial update */ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) { - if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) || + if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) || is_over_resolution_limit(ibuf->x, ibuf->y)) { int x_limit = smaller_power_of_2_limit(ibuf->x); @@ -1403,9 +1403,10 @@ void GPU_free_images_old(void) /* OpenGL state caching for materials */ typedef struct GPUMaterialFixed { - float diff[4]; - float spec[4]; + float diff[3]; + float spec[3]; int hard; + float alpha; } GPUMaterialFixed; static struct GPUMaterialState { @@ -1414,7 +1415,7 @@ static struct GPUMaterialState { int totmat; /* set when called inside GPU_begin_object_materials / GPU_end_object_materials - * otherwise calling GPU_enable_material returns zero */ + * otherwise calling GPU_object_material_bind returns zero */ bool is_enabled; Material **gmatbuf; @@ -1430,6 +1431,7 @@ static struct GPUMaterialState { float (*gviewcamtexcofac); bool backface_culling; + bool two_sided_lighting; GPUBlendMode *alphablend; GPUBlendMode alphablend_fixed[FIXEDMAT]; @@ -1447,20 +1449,18 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, { if (bmat->mode & MA_SHLESS) { copy_v3_v3(smat->diff, &bmat->r); - smat->diff[3] = 1.0; if (gamma) linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); - zero_v4(smat->spec); + zero_v3(smat->spec); + smat->alpha = 1.0f; smat->hard = 0; } else if (new_shading_nodes) { copy_v3_v3(smat->diff, &bmat->r); - smat->diff[3] = 1.0; - copy_v3_v3(smat->spec, &bmat->specr); - smat->spec[3] = 1.0; + smat->alpha = 1.0f; smat->hard = CLAMPIS(bmat->har, 0, 128); if (dimdown) { @@ -1475,14 +1475,13 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, } else { mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit); - smat->diff[3] = 1.0; /* caller may set this to bmat->alpha */ if (bmat->shade_flag & MA_OBCOLOR) mul_v3_v3(smat->diff, ob->col); mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec); - smat->spec[3] = 1.0; /* always 1 */ - smat->hard= CLAMPIS(bmat->har, 0, 128); + smat->hard = CLAMPIS(bmat->har, 1, 128); + smat->alpha = 1.0f; if (gamma) { linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); @@ -1570,6 +1569,10 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0; + GMS.two_sided_lighting = false; + if (ob && ob->type == OB_MESH) + GMS.two_sided_lighting = (((Mesh*)ob->data)->flag & ME_TWOSIDED) != 0; + GMS.gob = ob; GMS.gscene = scene; GMS.is_opensubdiv = use_opensubdiv; @@ -1648,11 +1651,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false); if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) { - GMS.matbuf[a].diff[3] = ma->alpha; + GMS.matbuf[a].alpha = ma->alpha; alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; } else { - GMS.matbuf[a].diff[3] = 1.0f; + GMS.matbuf[a].alpha = 1.0f; alphablend = GPU_BLEND_SOLID; } } @@ -1668,7 +1671,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O } /* let's start with a clean state */ - GPU_disable_material(); + GPU_object_material_unbind(); } static int GPU_get_particle_info(GPUParticleInfo *pi) @@ -1701,7 +1704,7 @@ static int GPU_get_particle_info(GPUParticleInfo *pi) return 0; } -int GPU_enable_material(int nr, void *attribs) +int GPU_object_material_bind(int nr, void *attribs) { GPUVertexAttribs *gattribs = attribs; GPUMaterial *gpumat; @@ -1709,19 +1712,17 @@ int GPU_enable_material(int nr, void *attribs) /* no GPU_begin_object_materials, use default material */ if (!GMS.matbuf) { - float diff[4], spec[4]; - memset(&GMS, 0, sizeof(GMS)); - mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit); - diff[3] = 1.0; - - mul_v3_v3fl(spec, &defmaterial.specr, defmaterial.spec); - spec[3] = 1.0; + float diffuse[3], specular[3]; + mul_v3_v3fl(diffuse, &defmaterial.r, defmaterial.ref + defmaterial.emit); + mul_v3_v3fl(specular, &defmaterial.specr, defmaterial.spec); + GPU_basic_shader_colors(diffuse, specular, 35, 1.0f); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); - glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35); /* blender default */ + if (GMS.two_sided_lighting) + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED); + else + GPU_basic_shader_bind(GPU_SHADER_LIGHTING); return 0; } @@ -1798,9 +1799,13 @@ int GPU_enable_material(int nr, void *attribs) } else { /* or do fixed function opengl material */ - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr].diff); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr].spec); - glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, GMS.matbuf[nr].hard); + GPU_basic_shader_colors(GMS.matbuf[nr].diff, + GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha); + + if (GMS.two_sided_lighting) + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED); + else + GPU_basic_shader_bind(GPU_SHADER_LIGHTING); } /* set (alpha) blending mode */ @@ -1810,6 +1815,31 @@ int GPU_enable_material(int nr, void *attribs) return GMS.lastretval; } +int GPU_object_material_visible(int nr, void *attribs) +{ + GPUVertexAttribs *gattribs = attribs; + int visible; + + if (!GMS.matbuf) + return 0; + + if (gattribs) + memset(gattribs, 0, sizeof(*gattribs)); + + if (nr>=GMS.totmat) + nr = 0; + + if (GMS.use_alpha_pass) { + visible = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); + if (GMS.is_alpha_pass) + visible = !visible; + } + else + visible = !GMS.is_alpha_pass; + + return visible; +} + void GPU_set_material_alpha_blend(int alphablend) { if (GMS.lastalphablend == alphablend) @@ -1824,7 +1854,7 @@ int GPU_get_material_alpha_blend(void) return GMS.lastalphablend; } -void GPU_disable_material(void) +void GPU_object_material_unbind(void) { GMS.lastmatnr = -1; GMS.lastretval = 1; @@ -1837,6 +1867,8 @@ void GPU_disable_material(void) GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv)); GMS.gboundmat = NULL; } + else + GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); GPU_set_material_alpha_blend(GPU_BLEND_SOLID); } @@ -1852,7 +1884,8 @@ void GPU_material_diffuse_get(int nr, float diff[4]) mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit); } else { - copy_v4_v4(diff, GMS.matbuf[nr].diff); + copy_v3_v3(diff, GMS.matbuf[nr].diff); + diff[3] = GMS.matbuf[nr].alpha; } } @@ -1868,7 +1901,7 @@ bool GPU_object_materials_check(void) void GPU_end_object_materials(void) { - GPU_disable_material(); + GPU_object_material_unbind(); GMS.is_enabled = false; @@ -1881,6 +1914,7 @@ void GPU_end_object_materials(void) GMS.matbuf = NULL; GMS.gmatbuf = NULL; GMS.alphablend = NULL; + GMS.two_sided_lighting = false; /* resetting the texture matrix after the scaling needed for tiled textures */ if (GTS.tilemode) { @@ -1894,7 +1928,6 @@ void GPU_end_object_materials(void) int GPU_default_lights(void) { - float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}, position[4]; int a, count = 0; /* initialize */ @@ -1918,42 +1951,25 @@ int GPU_default_lights(void) U.light[2].spec[3] = 1.0; } - glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); + GPU_basic_shader_light_set_viewer(false); for (a = 0; a < 8; a++) { - if (a < 3) { - if (U.light[a].flag) { - glEnable(GL_LIGHT0 + a); + if (a < 3 && U.light[a].flag) { + GPULightData light = {0}; - normalize_v3_v3(position, U.light[a].vec); - position[3] = 0.0f; - - glLightfv(GL_LIGHT0 + a, GL_POSITION, position); - glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, U.light[a].col); - glLightfv(GL_LIGHT0 + a, GL_SPECULAR, U.light[a].spec); + light.type = GPU_LIGHT_SUN; - count++; - } - else { - glDisable(GL_LIGHT0 + a); + normalize_v3_v3(light.direction, U.light[a].vec); + copy_v3_v3(light.diffuse, U.light[a].col); + copy_v3_v3(light.specular, U.light[a].spec); - glLightfv(GL_LIGHT0 + a, GL_POSITION, zero); - glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, zero); - glLightfv(GL_LIGHT0 + a, GL_SPECULAR, zero); - } + GPU_basic_shader_light_set(a, &light); - /* clear stuff from other opengl lamp usage */ - glLightf(GL_LIGHT0 + a, GL_SPOT_CUTOFF, 180.0); - glLightf(GL_LIGHT0 + a, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0 + a, GL_LINEAR_ATTENUATION, 0.0); + count++; } else - glDisable(GL_LIGHT0 + a); + GPU_basic_shader_light_set(a, NULL); } - - glDisable(GL_LIGHTING); - - glDisable(GL_COLOR_MATERIAL); return count; } @@ -1963,15 +1979,14 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ Base *base; Lamp *la; int count; - float position[4], direction[4], energy[4]; /* disable all lights */ for (count = 0; count < 8; count++) - glDisable(GL_LIGHT0 + count); + GPU_basic_shader_light_set(count, NULL); /* view direction for specular is not computed correct by default in * opengl, so we set the settings ourselfs */ - glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, ortho ? GL_FALSE : GL_TRUE); + GPU_basic_shader_light_set_viewer(!ortho); count = 0; @@ -1988,41 +2003,37 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ glPushMatrix(); glLoadMatrixf((float *)viewmat); - if (la->type == LA_SUN) { - /* sun lamp */ - copy_v3_v3(direction, base->object->obmat[2]); - direction[3] = 0.0; + /* setup light */ + GPULightData light = {0}; - glLightfv(GL_LIGHT0+count, GL_POSITION, direction); + mul_v3_v3fl(light.diffuse, &la->r, la->energy); + mul_v3_v3fl(light.specular, &la->r, la->energy); + + if (la->type == LA_SUN) { + /* directional sun light */ + light.type = GPU_LIGHT_SUN; + normalize_v3_v3(light.direction, base->object->obmat[2]); } else { - /* other lamps with attenuation */ - copy_v3_v3(position, base->object->obmat[3]); - position[3] = 1.0f; - - glLightfv(GL_LIGHT0+count, GL_POSITION, position); - glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1 / la->dist); - glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2 / (la->dist * la->dist)); + /* other lamps with position attenuation */ + copy_v3_v3(light.position, base->object->obmat[3]); + + light.constant_attenuation = 1.0f; + light.linear_attenuation = la->att1 / la->dist; + light.quadratic_attenuation = la->att2 / (la->dist * la->dist); if (la->type == LA_SPOT) { - /* spot lamp */ - negate_v3_v3(direction, base->object->obmat[2]); - glLightfv(GL_LIGHT0 + count, GL_SPOT_DIRECTION, direction); - glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f)); - glLightf(GL_LIGHT0 + count, GL_SPOT_EXPONENT, 128.0f * la->spotblend); + light.type = GPU_LIGHT_SPOT; + negate_v3_v3(light.direction, base->object->obmat[2]); + normalize_v3(light.direction); + light.spot_cutoff = RAD2DEGF(la->spotsize * 0.5f); + light.spot_exponent = 128.0f * la->spotblend; } else - glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, 180.0); + light.type = GPU_LIGHT_POINT; } - /* setup energy */ - mul_v3_v3fl(energy, &la->r, la->energy); - energy[3] = 1.0; - - glLightfv(GL_LIGHT0 + count, GL_DIFFUSE, energy); - glLightfv(GL_LIGHT0 + count, GL_SPECULAR, energy); - glEnable(GL_LIGHT0 + count); + GPU_basic_shader_light_set(count, &light); glPopMatrix(); @@ -2063,11 +2074,15 @@ static void gpu_multisample(bool enable) #endif } -/* Default OpenGL State */ +/* Default OpenGL State + * + * This is called on startup, for opengl offscreen render and to restore state + * for the game engine. Generally we should always return to this state when + * temporarily modifying the state for drawing, though that are (undocumented) + * exceptions that we should try to get rid of. */ void GPU_state_init(void) { - /* also called when doing opengl rendering and in the game engine */ float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; int a, x, y; @@ -2078,6 +2093,7 @@ void GPU_state_init(void) glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); GPU_default_lights(); @@ -2092,6 +2108,7 @@ void GPU_state_init(void) glDisable(GL_DEPTH_TEST); glDisable(GL_FOG); glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); glDisable(GL_LOGIC_OP); glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_1D); @@ -2136,6 +2153,8 @@ void GPU_state_init(void) glDisable(GL_CULL_FACE); gpu_multisample(false); + + GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } #ifdef WITH_OPENSUBDIV |