| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2006 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Brecht Van Lommel, Clément Foucault. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/gpu/intern/gpu_lamp.c
 | 
					
						
							|  |  |  |  *  \ingroup gpu | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Manages Opengl lights. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_lamp_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_group.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GPU_framebuffer.h"
 | 
					
						
							|  |  |  | #include "GPU_glew.h"
 | 
					
						
							|  |  |  | #include "GPU_lamp.h"
 | 
					
						
							|  |  |  | #include "GPU_material.h"
 | 
					
						
							|  |  |  | #include "GPU_shader.h"
 | 
					
						
							|  |  |  | #include "GPU_texture.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_lamp_private.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 16:32:13 -02:00
										 |  |  | bool GPU_lamp_visible(GPULamp *lamp, Material *ma) | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-12 14:01:17 +02:00
										 |  |  | 	if (lamp->hide) | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 	else if (ma && ma->group) | 
					
						
							|  |  |  | 		return BKE_group_object_exists(ma->group, lamp->ob); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void gpu_lamp_calc_winmat(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float temp, angle, pixsize, wsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (lamp->type == LA_SUN) { | 
					
						
							|  |  |  | 		wsize = lamp->la->shadow_frustum_size; | 
					
						
							|  |  |  | 		orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (lamp->type == LA_SPOT) { | 
					
						
							|  |  |  | 		angle = saacos(lamp->spotsi); | 
					
						
							|  |  |  | 		temp = 0.5f * lamp->size * cosf(angle) / sinf(angle); | 
					
						
							|  |  |  | 		pixsize = lamp->d / temp; | 
					
						
							|  |  |  | 		wsize = pixsize * 0.5f * lamp->size; | 
					
						
							|  |  |  | 		/* compute shadows according to X and Y scaling factors */ | 
					
						
							|  |  |  | 		perspective_m4( | 
					
						
							|  |  |  | 		        lamp->winmat, | 
					
						
							|  |  |  | 		        -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0], | 
					
						
							|  |  |  | 		        -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1], | 
					
						
							|  |  |  | 		        lamp->d, lamp->clipend); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float mat[4][4]; | 
					
						
							|  |  |  | 	float obmat_scale[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->lay = lay; | 
					
						
							|  |  |  | 	lamp->hide = hide; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	normalize_m4_m4_ex(mat, obmat, obmat_scale); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy_v3_v3(lamp->vec, mat[2]); | 
					
						
							|  |  |  | 	copy_v3_v3(lamp->co, mat[3]); | 
					
						
							|  |  |  | 	copy_m4_m4(lamp->obmat, mat); | 
					
						
							|  |  |  | 	invert_m4_m4(lamp->imat, mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (lamp->type == LA_SPOT) { | 
					
						
							|  |  |  | 		/* update spotlamp scale on X and Y axis */ | 
					
						
							|  |  |  | 		lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2]; | 
					
						
							|  |  |  | 		lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (GPU_lamp_has_shadow_buffer(lamp)) { | 
					
						
							|  |  |  | 		/* makeshadowbuf */ | 
					
						
							|  |  |  | 		gpu_lamp_calc_winmat(lamp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	lamp->energy = energy; | 
					
						
							|  |  |  | 	if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->col[0] = r; | 
					
						
							|  |  |  | 	lamp->col[1] = g; | 
					
						
							|  |  |  | 	lamp->col[2] = b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, | 
					
						
							|  |  |  |                               float coeff_const, float coeff_lin, float coeff_quad) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	lamp->dist = distance; | 
					
						
							|  |  |  | 	lamp->att1 = att1; | 
					
						
							|  |  |  | 	lamp->att2 = att2; | 
					
						
							|  |  |  | 	lamp->coeff_const = coeff_const; | 
					
						
							|  |  |  | 	lamp->coeff_lin = coeff_lin; | 
					
						
							|  |  |  | 	lamp->coeff_quad = coeff_quad; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	lamp->spotsi = cosf(spotsize * 0.5f); | 
					
						
							|  |  |  | 	lamp->spotbl = (1.0f - lamp->spotsi) * spotblend; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	lamp->scene = scene; | 
					
						
							|  |  |  | 	lamp->ob = ob; | 
					
						
							|  |  |  | 	lamp->par = par; | 
					
						
							|  |  |  | 	lamp->la = la; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add_render_lamp */ | 
					
						
							|  |  |  | 	lamp->mode = la->mode; | 
					
						
							|  |  |  | 	lamp->type = la->type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->energy = la->energy; | 
					
						
							|  |  |  | 	if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->col[0] = la->r; | 
					
						
							|  |  |  | 	lamp->col[1] = la->g; | 
					
						
							|  |  |  | 	lamp->col[2] = la->b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->spotsi = la->spotsize; | 
					
						
							|  |  |  | 	if (lamp->mode & LA_HALO) | 
					
						
							|  |  |  | 		if (lamp->spotsi > DEG2RADF(170.0f)) | 
					
						
							|  |  |  | 			lamp->spotsi = DEG2RADF(170.0f); | 
					
						
							|  |  |  | 	lamp->spotsi = cosf(lamp->spotsi * 0.5f); | 
					
						
							|  |  |  | 	lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend; | 
					
						
							|  |  |  | 	lamp->k = la->k; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->dist = la->dist; | 
					
						
							|  |  |  | 	lamp->falloff_type = la->falloff_type; | 
					
						
							|  |  |  | 	lamp->att1 = la->att1; | 
					
						
							|  |  |  | 	lamp->att2 = la->att2; | 
					
						
							|  |  |  | 	lamp->coeff_const = la->coeff_const; | 
					
						
							|  |  |  | 	lamp->coeff_lin = la->coeff_lin; | 
					
						
							|  |  |  | 	lamp->coeff_quad = la->coeff_quad; | 
					
						
							|  |  |  | 	lamp->curfalloff = la->curfalloff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* initshadowbuf */ | 
					
						
							|  |  |  | 	lamp->bias = 0.02f * la->bias; | 
					
						
							|  |  |  | 	lamp->size = la->bufsize; | 
					
						
							|  |  |  | 	lamp->d = la->clipsta; | 
					
						
							|  |  |  | 	lamp->clipend = la->clipend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* arbitrary correction for the fact we do no soft transition */ | 
					
						
							|  |  |  | 	lamp->bias *= 0.25f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void gpu_lamp_shadow_free(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (lamp->tex) { | 
					
						
							|  |  |  | 		GPU_texture_free(lamp->tex); | 
					
						
							|  |  |  | 		lamp->tex = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lamp->depthtex) { | 
					
						
							|  |  |  | 		GPU_texture_free(lamp->depthtex); | 
					
						
							|  |  |  | 		lamp->depthtex = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lamp->fb) { | 
					
						
							|  |  |  | 		GPU_framebuffer_free(lamp->fb); | 
					
						
							|  |  |  | 		lamp->fb = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lamp->blurtex) { | 
					
						
							|  |  |  | 		GPU_texture_free(lamp->blurtex); | 
					
						
							|  |  |  | 		lamp->blurtex = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (lamp->blurfb) { | 
					
						
							|  |  |  | 		GPU_framebuffer_free(lamp->blurfb); | 
					
						
							|  |  |  | 		lamp->blurfb = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | LampEngineData *GPU_lamp_engine_data_get(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re) | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	GPULamp *lamp; | 
					
						
							|  |  |  | 	LinkData *link; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (link = ob->gpulamp.first; link; link = link->next) { | 
					
						
							|  |  |  | 		lamp = (GPULamp *)link->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re)) | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | 			return &lamp->data; | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	link = MEM_callocN(sizeof(LinkData), "GPULampLink"); | 
					
						
							|  |  |  | 	link->data = lamp; | 
					
						
							|  |  |  | 	BLI_addtail(&ob->gpulamp, link); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp->scene = scene; | 
					
						
							|  |  |  | 	lamp->ob = ob; | 
					
						
							|  |  |  | 	lamp->par = par; | 
					
						
							|  |  |  | 	lamp->la = ob->data; | 
					
						
							|  |  |  | 	lamp->re = re; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | 	return &lamp->data; | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Lamp *la; | 
					
						
							|  |  |  | 	GPULamp *lamp; | 
					
						
							|  |  |  | 	LinkData *link; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (link = ob->gpulamp.first; link; link = link->next) { | 
					
						
							|  |  |  | 		lamp = (GPULamp *)link->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (lamp->par == par && lamp->scene == scene) | 
					
						
							|  |  |  | 			return link->data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	link = MEM_callocN(sizeof(LinkData), "GPULampLink"); | 
					
						
							|  |  |  | 	link->data = lamp; | 
					
						
							|  |  |  | 	BLI_addtail(&ob->gpulamp, link); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	la = ob->data; | 
					
						
							|  |  |  | 	gpu_lamp_from_blender(scene, ob, par, la, lamp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || | 
					
						
							|  |  |  | 	    (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* opengl */ | 
					
						
							|  |  |  | 		lamp->fb = GPU_framebuffer_create(); | 
					
						
							|  |  |  | 		if (!lamp->fb) { | 
					
						
							|  |  |  | 			gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 			return lamp; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { | 
					
						
							|  |  |  | 			/* Shadow depth map */ | 
					
						
							|  |  |  | 			lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); | 
					
						
							|  |  |  | 			if (!lamp->depthtex) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 17:02:16 +02:00
										 |  |  | 			GPU_texture_bind(lamp->depthtex, 0); | 
					
						
							|  |  |  | 			GPU_texture_compare_mode(lamp->depthtex, true); | 
					
						
							|  |  |  | 			GPU_texture_unbind(lamp->depthtex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 11:28:11 +02:00
										 |  |  | 			if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0)) { | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Shadow color map */ | 
					
						
							|  |  |  | 			lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size); | 
					
						
							|  |  |  | 			if (!lamp->tex) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 11:28:11 +02:00
										 |  |  | 			if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) { | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* FBO and texture for blurring */ | 
					
						
							|  |  |  | 			lamp->blurfb = GPU_framebuffer_create(); | 
					
						
							|  |  |  | 			if (!lamp->blurfb) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5); | 
					
						
							|  |  |  | 			if (!lamp->blurtex) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 11:28:11 +02:00
										 |  |  | 			if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0)) { | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* we need to properly bind to test for completeness */ | 
					
						
							|  |  |  | 			GPU_texture_bind_as_framebuffer(lamp->blurtex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); | 
					
						
							|  |  |  | 			if (!lamp->tex) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 17:02:16 +02:00
										 |  |  | 			GPU_texture_bind(lamp->tex, 0); | 
					
						
							|  |  |  | 			GPU_texture_compare_mode(lamp->tex, true); | 
					
						
							|  |  |  | 			GPU_texture_unbind(lamp->tex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 11:28:11 +02:00
										 |  |  | 			if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) { | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { | 
					
						
							|  |  |  | 				gpu_lamp_shadow_free(lamp); | 
					
						
							|  |  |  | 				return lamp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		GPU_framebuffer_restore(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		lamp->shadow_color[0] = la->shdwr; | 
					
						
							|  |  |  | 		lamp->shadow_color[1] = la->shdwg; | 
					
						
							|  |  |  | 		lamp->shadow_color[2] = la->shdwb; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		lamp->shadow_color[0] = 1.0; | 
					
						
							|  |  |  | 		lamp->shadow_color[1] = 1.0; | 
					
						
							|  |  |  | 		lamp->shadow_color[2] = 1.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return lamp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | void GPU_lamp_engine_data_free(LampEngineData *led) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-07 15:57:14 +11:00
										 |  |  | 	for (int i = 0; i < MAX_LAMP_DATA; ++i) { | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | 		if (led->storage[i]) { | 
					
						
							|  |  |  | 			MEM_freeN(led->storage[i]); | 
					
						
							|  |  |  | 			led->storage[i] = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | void GPU_lamp_free(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GPULamp *lamp; | 
					
						
							|  |  |  | 	LinkData *link; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (link = ob->gpulamp.first; link; link = link->next) { | 
					
						
							|  |  |  | 		lamp = link->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		gpu_lamp_shadow_free(lamp); | 
					
						
							| 
									
										
										
										
											2017-04-10 12:06:17 +02:00
										 |  |  | 		GPU_lamp_engine_data_free(&lamp->data); | 
					
						
							| 
									
										
										
										
											2017-04-03 15:38:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN(lamp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_freelistN(&ob->gpulamp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GPU_lamp_has_shadow_buffer(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && | 
					
						
							|  |  |  | 	        !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) && | 
					
						
							|  |  |  | 	        lamp->tex && lamp->fb); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_update_buffer_mats(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float rangemat[4][4], persmat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* initshadowbuf */ | 
					
						
							|  |  |  | 	invert_m4_m4(lamp->viewmat, lamp->obmat); | 
					
						
							|  |  |  | 	normalize_v3(lamp->viewmat[0]); | 
					
						
							|  |  |  | 	normalize_v3(lamp->viewmat[1]); | 
					
						
							|  |  |  | 	normalize_v3(lamp->viewmat[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* makeshadowbuf */ | 
					
						
							|  |  |  | 	mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ | 
					
						
							|  |  |  | 	unit_m4(rangemat); | 
					
						
							|  |  |  | 	rangemat[0][0] = 0.5f; | 
					
						
							|  |  |  | 	rangemat[1][1] = 0.5f; | 
					
						
							|  |  |  | 	rangemat[2][2] = 0.5f; | 
					
						
							|  |  |  | 	rangemat[3][0] = 0.5f; | 
					
						
							|  |  |  | 	rangemat[3][1] = 0.5f; | 
					
						
							|  |  |  | 	rangemat[3][2] = 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mul_m4_m4m4(lamp->persmat, rangemat, persmat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GPU_lamp_update_buffer_mats(lamp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* opengl */ | 
					
						
							|  |  |  | 	glDisable(GL_SCISSOR_TEST); | 
					
						
							|  |  |  | 	GPU_texture_bind_as_framebuffer(lamp->tex); | 
					
						
							|  |  |  | 	if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) | 
					
						
							|  |  |  | 		GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* set matrices */ | 
					
						
							|  |  |  | 	copy_m4_m4(viewmat, lamp->viewmat); | 
					
						
							|  |  |  | 	copy_m4_m4(winmat, lamp->winmat); | 
					
						
							|  |  |  | 	*winsize = lamp->size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { | 
					
						
							|  |  |  | 		GPU_shader_unbind(); | 
					
						
							|  |  |  | 		GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); | 
					
						
							|  |  |  | 	GPU_framebuffer_restore(); | 
					
						
							|  |  |  | 	glEnable(GL_SCISSOR_TEST); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int GPU_lamp_shadow_buffer_type(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return lamp->la->shadowmap_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int GPU_lamp_shadow_bind_code(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float *GPU_lamp_dynpersmat(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return &lamp->dynpersmat[0][0]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int GPU_lamp_shadow_layer(GPULamp *lamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW))) | 
					
						
							|  |  |  | 		return lamp->lay; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | } |