Example #1
0
static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire)
{
	GPU_shader_unbind();

	GPU_texture_unbind(sds->tex);

	if (use_fire) {
		GPU_texture_unbind(sds->tex_flame);
		GPU_texture_unbind(tex_spec);
		GPU_texture_free(tex_spec);
	}
	else {
		GPU_texture_unbind(sds->tex_shadow);
	}
}
Example #2
0
GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels)
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #3
0
GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #4
0
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #5
0
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);

	if (tex)
		GPU_texture_unbind(tex);

	return tex;
}
Example #6
0
GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #7
0
GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #8
0
GPUTexture *GPU_texture_create_depth(int w, int h)
{
	GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1);

	if (tex)
		GPU_texture_unbind(tex);
	
	return tex;
}
Example #9
0
void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
{
	GPUShader *depth_resolve_shader;
	GPU_framebuffer_texture_detach(fx->depth_buffer_xray);

	/* attach regular framebuffer */
	GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);

	/* full screen quad where we will always write to depth buffer */
	glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
	glDepthFunc(GL_ALWAYS);
	/* disable scissor from sculpt if any */
	glDisable(GL_SCISSOR_TEST);
	/* disable writing to color buffer, it's depth only pass */
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

	/* set up quad buffer */
	glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
	glVertexPointer(2, GL_FLOAT, 0, NULL);
	glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);

	if (depth_resolve_shader) {
		int depth_uniform;

		depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");

		GPU_shader_bind(depth_resolve_shader);

		GPU_texture_bind(fx->depth_buffer_xray, 0);
		GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
		GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);

		/* draw */
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		/* disable bindings */
		GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
		GPU_texture_unbind(fx->depth_buffer_xray);

		GPU_shader_unbind();
	}

	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glPopAttrib();
}
Example #10
0
void EEVEE_lightcache_load(LightCache *lcache)
{
  if (lcache->grid_tx.tex == NULL && lcache->grid_tx.data) {
    lcache->grid_tx.tex = GPU_texture_create_nD(lcache->grid_tx.tex_size[0],
                                                lcache->grid_tx.tex_size[1],
                                                lcache->grid_tx.tex_size[2],
                                                2,
                                                lcache->grid_tx.data,
                                                IRRADIANCE_FORMAT,
                                                GPU_DATA_UNSIGNED_BYTE,
                                                0,
                                                false,
                                                NULL);
    GPU_texture_bind(lcache->grid_tx.tex, 0);
    GPU_texture_filter_mode(lcache->grid_tx.tex, true);
    GPU_texture_unbind(lcache->grid_tx.tex);
  }

  if (lcache->cube_tx.tex == NULL && lcache->cube_tx.data) {
    lcache->cube_tx.tex = GPU_texture_create_nD(lcache->cube_tx.tex_size[0],
                                                lcache->cube_tx.tex_size[1],
                                                lcache->cube_tx.tex_size[2],
                                                2,
                                                lcache->cube_tx.data,
                                                GPU_R11F_G11F_B10F,
                                                GPU_DATA_10_11_11_REV,
                                                0,
                                                false,
                                                NULL);
    GPU_texture_bind(lcache->cube_tx.tex, 0);
    GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
    for (int mip = 0; mip < lcache->mips_len; ++mip) {
      GPU_texture_add_mipmap(
          lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
    }
    GPU_texture_unbind(lcache->cube_tx.tex);
  }
}
Example #11
0
/**
 * A shadow map for VSM needs two components (depth and depth^2)
 */
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);

	if (tex) {
		/* Now we tweak some of the settings */
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		GPU_texture_unbind(tex);
	}

	return tex;
}
Example #12
0
GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
{
	GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);

	if (tex) {
		/* Now we tweak some of the settings */
		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		GPU_texture_unbind(tex);
	}

	return tex;
}
void GPU_pass_unbind(GPUPass *pass)
{
	GPUInput *input;
	GPUShader *shader = pass->shader;
	ListBase *inputs = &pass->inputs;

	if (!shader)
		return;

	for (input=inputs->first; input; input=input->next) {
		if (input->tex && input->bindtex)
			GPU_texture_unbind(input->tex);

		if (input->ima || input->prv)
			input->tex = NULL;
	}
	
	GPU_shader_unbind();
}
Example #14
0
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels)
{
	GPUTexture *tex;
	GLenum type, format, internalformat;
	void *pixels = NULL;
	float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};

	if (!GLEW_VERSION_1_2)
		return NULL;

	tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
	tex->w = w;
	tex->h = h;
	tex->depth = depth;
	tex->number = -1;
	tex->refcount = 1;
	tex->target = GL_TEXTURE_3D;

	glGenTextures(1, &tex->bindcode);

	if (!tex->bindcode) {
		fprintf(stderr, "GPUTexture: texture create failed: %d\n",
			(int)glGetError());
		GPU_texture_free(tex);
		return NULL;
	}

	if (!GPU_non_power_of_two_support()) {
		tex->w = power_of_2_max_i(tex->w);
		tex->h = power_of_2_max_i(tex->h);
		tex->depth = power_of_2_max_i(tex->depth);
	}

	tex->number = 0;
	glBindTexture(tex->target, tex->bindcode);

	GPU_print_error("3D glBindTexture");

	type = GL_FLOAT;
	if (channels == 4) {
		format = GL_RGBA;
		internalformat = GL_RGBA;
	}
	else {
		format = GL_RED;
		internalformat = GL_INTENSITY;
	}

	//if (fpixels)
	//	pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);

	glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);

	GPU_print_error("3D glTexImage3D");

	if (fpixels) {
		if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
			/* clear first to avoid unitialized pixels */
			float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
			glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
			MEM_freeN(zero);
		}

		glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
		GPU_print_error("3D glTexSubImage3D");
	}


	glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
	GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	GPU_print_error("3D GL_LINEAR");
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	GPU_print_error("3D GL_CLAMP_TO_BORDER");

	if (pixels)
		MEM_freeN(pixels);

	GPU_texture_unbind(tex);

	return tex;
}
Example #15
0
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
                       GPUTexture *tex, const float min[3], const float max[3],
                       const int res[3], float dx, float UNUSED(base_scale), const float viewnormal[3],
                       GPUTexture *tex_shadow, GPUTexture *tex_flame)
{
	const float ob_sizei[3] = {
	    1.0f / fabsf(ob->size[0]),
	    1.0f / fabsf(ob->size[1]),
	    1.0f / fabsf(ob->size[2])};

	int i, j, k, n, good_index;
	float d /*, d0 */ /* UNUSED */, dd, ds;
	float (*points)[3] = NULL;
	int numpoints = 0;
	float cor[3] = {1.0f, 1.0f, 1.0f};
	int gl_depth = 0, gl_blend = 0;

	int use_fire = (sds->active_fields & SM_ACTIVE_FIRE);

	/* draw slices of smoke is adapted from c++ code authored
	 * by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */
	float cv[][3] = {
		{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
		{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
	};

	/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
	float edges[12][2][3] = {
		{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},

		{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},

		{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
	};

	unsigned char *spec_data;
	float *spec_pixels;
	GPUTexture *tex_spec;
	GPUProgram *smoke_program;
	int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
	float size[3];

	if (!tex) {
		printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
		return;
	}

#ifdef DEBUG_DRAW_TIME
	TIMEIT_START(draw);
#endif

	/* generate flame spectrum texture */
#define SPEC_WIDTH 256
#define FIRE_THRESH 7
#define MAX_FIRE_ALPHA 0.06f
#define FULL_ON_FIRE 100
	spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
	flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
	spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
	for (i = 0; i < 16; i++) {
		for (j = 0; j < 16; j++) {
			for (k = 0; k < SPEC_WIDTH; k++) {
				int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
				if (k >= FIRE_THRESH) {
					spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
					spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
					spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
					spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
					        (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
				}
				else {
					spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
				}
			}
		}
	}

	tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);

#undef SPEC_WIDTH
#undef FIRE_THRESH
#undef MAX_FIRE_ALPHA
#undef FULL_ON_FIRE

	sub_v3_v3v3(size, max, min);

	/* maxx, maxy, maxz */
	cv[0][0] = max[0];
	cv[0][1] = max[1];
	cv[0][2] = max[2];
	/* minx, maxy, maxz */
	cv[1][0] = min[0];
	cv[1][1] = max[1];
	cv[1][2] = max[2];
	/* minx, miny, maxz */
	cv[2][0] = min[0];
	cv[2][1] = min[1];
	cv[2][2] = max[2];
	/* maxx, miny, maxz */
	cv[3][0] = max[0];
	cv[3][1] = min[1];
	cv[3][2] = max[2];

	/* maxx, maxy, minz */
	cv[4][0] = max[0];
	cv[4][1] = max[1];
	cv[4][2] = min[2];
	/* minx, maxy, minz */
	cv[5][0] = min[0];
	cv[5][1] = max[1];
	cv[5][2] = min[2];
	/* minx, miny, minz */
	cv[6][0] = min[0];
	cv[6][1] = min[1];
	cv[6][2] = min[2];
	/* maxx, miny, minz */
	cv[7][0] = max[0];
	cv[7][1] = min[1];
	cv[7][2] = min[2];

	copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
	copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
	copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
	copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
	copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */

	// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
	// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);

	edges[0][1][2] = size[2];
	edges[1][1][2] = size[2];
	edges[2][1][2] = size[2];
	edges[3][1][2] = size[2];

	edges[4][1][1] = size[1];
	edges[5][1][1] = size[1];
	edges[6][1][1] = size[1];
	edges[7][1][1] = size[1];

	edges[8][1][0] = size[0];
	edges[9][1][0] = size[0];
	edges[10][1][0] = size[0];
	edges[11][1][0] = size[0];

	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);

	/* find cube vertex that is closest to the viewer */
	for (i = 0; i < 8; i++) {
		float x, y, z;

		x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
		y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
		z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;

		if ((x >= min[0]) && (x <= max[0]) &&
		    (y >= min[1]) && (y <= max[1]) &&
		    (z >= min[2]) && (z <= max[2]))
		{
			break;
		}
	}

	if (i >= 8) {
		/* fallback, avoid using buffer over-run */
		i = 0;
	}

	// printf("i: %d\n", i);
	// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);

	smoke_program = GPU_shader_get_builtin_program(progtype);
	if (smoke_program) {
		GPU_program_bind(smoke_program);

		/* cell spacing */
		GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0);
		/* custom parameter for smoke style (higher = thicker) */
		if (sds->active_fields & SM_ACTIVE_COLORS)
			GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0);
		else
			GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
	}
	else
		printf("Your gfx card does not support 3D View smoke drawing.\n");

	GPU_texture_bind(tex, 0);
	if (tex_shadow)
		GPU_texture_bind(tex_shadow, 1);
	else
		printf("No volume shadow\n");

	if (tex_flame) {
		GPU_texture_bind(tex_flame, 2);
		GPU_texture_bind(tex_spec, 3);
	}

	if (!GPU_non_power_of_two_support()) {
		cor[0] = (float)res[0] / (float)power_of_2_max_u(res[0]);
		cor[1] = (float)res[1] / (float)power_of_2_max_u(res[1]);
		cor[2] = (float)res[2] / (float)power_of_2_max_u(res[2]);
	}

	cor[0] /= size[0];
	cor[1] /= size[1];
	cor[2] /= size[2];

	/* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
	 * (a,b,c), the plane normal, are given by viewdir
	 * d is the parameter along the view direction. the first d is given by
	 * inserting previously found vertex into the plane equation */

	/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
	ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
	dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
	n = 0;
	good_index = i;

	// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);

	points = MEM_callocN(sizeof(*points) * 12, "smoke_points_preview");

	while (1) {
		float p0[3];
		float tmp_point[3], tmp_point2[3];

		if (dd * (float)n > ds)
			break;

		copy_v3_v3(tmp_point, viewnormal);
		mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
		add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
		d = dot_v3v3(tmp_point2, viewnormal);

		// printf("my d: %f\n", d);

		/* intersect_edges returns the intersection points of all cube edges with
		 * the given plane that lie within the cube */
		numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);

		// printf("points: %d\n", numpoints);

		if (numpoints > 2) {
			copy_v3_v3(p0, points[0]);

			/* sort points to get a convex polygon */
			for (i = 1; i < numpoints - 1; i++) {
				for (j = i + 1; j < numpoints; j++) {
					if (!convex(p0, viewnormal, points[j], points[i])) {
						swap_v3_v3(points[i], points[j]);
					}
				}
			}

			/* render fire slice */
			if (use_fire) {
				if (GLEW_VERSION_1_4)
					glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
				else
					glBlendFunc(GL_SRC_ALPHA, GL_ONE);

				GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0);
				glBegin(GL_POLYGON);
				glColor3f(1.0, 1.0, 1.0);
				for (i = 0; i < numpoints; i++) {
					glTexCoord3d((points[i][0] - min[0]) * cor[0],
					             (points[i][1] - min[1]) * cor[1],
					             (points[i][2] - min[2]) * cor[2]);
					glVertex3f(points[i][0] * ob_sizei[0],
					           points[i][1] * ob_sizei[1],
					           points[i][2] * ob_sizei[2]);
				}
				glEnd();
			}

			/* render smoke slice */
			if (GLEW_VERSION_1_4)
				glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
			else
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i][0] - min[0]) * cor[0],
				             (points[i][1] - min[1]) * cor[1],
				             (points[i][2] - min[2]) * cor[2]);
				glVertex3f(points[i][0] * ob_sizei[0],
				           points[i][1] * ob_sizei[1],
				           points[i][2] * ob_sizei[2]);
			}
			glEnd();
		}
		n++;
	}

#ifdef DEBUG_DRAW_TIME
	printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
	TIMEIT_END(draw);
#endif

	if (tex_shadow)
		GPU_texture_unbind(tex_shadow);
	GPU_texture_unbind(tex);
	if (tex_flame) {
		GPU_texture_unbind(tex_flame);
		GPU_texture_unbind(tex_spec);
	}
	GPU_texture_free(tex_spec);

	free(spec_data);
	free(spec_pixels);

	if (smoke_program)
		GPU_program_unbind(smoke_program);


	MEM_freeN(points);

	if (!gl_blend) {
		glDisable(GL_BLEND);
	}

	if (gl_depth) {
		glEnable(GL_DEPTH_TEST);
	}
}
Example #16
0
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels)
{
	GPUTexture *tex;
	GLenum type, format, internalformat;
	void *pixels = NULL;
	float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};

	tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
	tex->w = w;
	tex->h = h;
	tex->depth = depth;
	tex->number = -1;
	tex->refcount = 1;
	tex->target = GL_TEXTURE_3D;

	glGenTextures(1, &tex->bindcode);

	if (!tex->bindcode) {
		fprintf(stderr, "GPUTexture: texture create failed: %d\n",
			(int)glGetError());
		GPU_texture_free(tex);
		return NULL;
	}

	if (!GPU_non_power_of_two_support()) {
		tex->w = larger_pow2(tex->w);
		tex->h = larger_pow2(tex->h);
		tex->depth = larger_pow2(tex->depth);
	}

	tex->number = 0;
	glBindTexture(tex->target, tex->bindcode);

	GPU_print_error("3D glBindTexture");

	type = GL_FLOAT; // GL_UNSIGNED_BYTE
	format = GL_RED;
	internalformat = GL_INTENSITY;

	//if (fpixels)
	//	pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);

	glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, 0);

	GPU_print_error("3D glTexImage3D");

	if (fpixels) {
		glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
		GPU_print_error("3D glTexSubImage3D");
	}


	glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
	GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	GPU_print_error("3D GL_LINEAR");
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	GPU_print_error("3D GL_CLAMP_TO_BORDER");

	if (pixels)
		MEM_freeN(pixels);

	if (tex)
		GPU_texture_unbind(tex);

	return tex;
}
Example #17
0
void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow)
{
	RegionView3D *rv3d= ar->regiondata;

	float viewnormal[3];
	int i, j, n, good_index;
	float d /*, d0 */ /* UNUSED */, dd, ds;
	float *points = NULL;
	int numpoints = 0;
	float cor[3] = {1.,1.,1.};
	int gl_depth = 0, gl_blend = 0;

	/* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */
	float cv[][3] = {
		{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
		{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
	};

	// edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
	float edges[12][2][3] = {
		{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},

		{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},

		{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
	};

	/* Fragment program to calculate the view3d of smoke */
	/* using 2 textures, density and shadow */
	const char *text = "!!ARBfp1.0\n"
					"PARAM dx = program.local[0];\n"
					"PARAM darkness = program.local[1];\n"
					"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
					"TEMP temp, shadow, value;\n"
					"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
					"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
					"MUL value, temp, darkness;\n"
					"MUL value, value, dx;\n"
					"MUL value, value, f;\n"
					"EX2 temp, -value.r;\n"
					"SUB temp.a, 1.0, temp.r;\n"
					"MUL temp.r, temp.r, shadow.r;\n"
					"MUL temp.g, temp.g, shadow.r;\n"
					"MUL temp.b, temp.b, shadow.r;\n"
					"MOV result.color, temp;\n"
					"END\n";
	GLuint prog;

	
	float size[3];

	if(!tex) {
		printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
		return;
	}

	tstart();

	sub_v3_v3v3(size, max, min);

	// maxx, maxy, maxz
	cv[0][0] = max[0];
	cv[0][1] = max[1];
	cv[0][2] = max[2];
	// minx, maxy, maxz
	cv[1][0] = min[0];
	cv[1][1] = max[1];
	cv[1][2] = max[2];
	// minx, miny, maxz
	cv[2][0] = min[0];
	cv[2][1] = min[1];
	cv[2][2] = max[2];
	// maxx, miny, maxz
	cv[3][0] = max[0];
	cv[3][1] = min[1];
	cv[3][2] = max[2];

	// maxx, maxy, minz
	cv[4][0] = max[0];
	cv[4][1] = max[1];
	cv[4][2] = min[2];
	// minx, maxy, minz
	cv[5][0] = min[0];
	cv[5][1] = max[1];
	cv[5][2] = min[2];
	// minx, miny, minz
	cv[6][0] = min[0];
	cv[6][1] = min[1];
	cv[6][2] = min[2];
	// maxx, miny, minz
	cv[7][0] = max[0];
	cv[7][1] = min[1];
	cv[7][2] = min[2];

	copy_v3_v3(edges[0][0], cv[4]); // maxx, maxy, minz
	copy_v3_v3(edges[1][0], cv[5]); // minx, maxy, minz
	copy_v3_v3(edges[2][0], cv[6]); // minx, miny, minz
	copy_v3_v3(edges[3][0], cv[7]); // maxx, miny, minz

	copy_v3_v3(edges[4][0], cv[3]); // maxx, miny, maxz
	copy_v3_v3(edges[5][0], cv[2]); // minx, miny, maxz
	copy_v3_v3(edges[6][0], cv[6]); // minx, miny, minz
	copy_v3_v3(edges[7][0], cv[7]); // maxx, miny, minz

	copy_v3_v3(edges[8][0], cv[1]); // minx, maxy, maxz
	copy_v3_v3(edges[9][0], cv[2]); // minx, miny, maxz
	copy_v3_v3(edges[10][0], cv[6]); // minx, miny, minz
	copy_v3_v3(edges[11][0], cv[5]); // minx, maxy, minz

	// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
	// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);

	edges[0][1][2] = size[2];
	edges[1][1][2] = size[2];
	edges[2][1][2] = size[2];
	edges[3][1][2] = size[2];

	edges[4][1][1] = size[1];
	edges[5][1][1] = size[1];
	edges[6][1][1] = size[1];
	edges[7][1][1] = size[1];

	edges[8][1][0] = size[0];
	edges[9][1][0] = size[0];
	edges[10][1][0] = size[0];
	edges[11][1][0] = size[0];

	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glLoadMatrixf(rv3d->viewmat);
	// glMultMatrixf(ob->obmat);	

	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	/*
	printf("Viewinv:\n");
	printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]);
	printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]);
	printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]);
	*/

	// get view vector
	copy_v3_v3(viewnormal, rv3d->viewinv[2]);
	normalize_v3(viewnormal);

	// find cube vertex that is closest to the viewer
	for (i=0; i<8; i++) {
		float x,y,z;

		x = cv[i][0] - viewnormal[0];
		y = cv[i][1] - viewnormal[1];
		z = cv[i][2] - viewnormal[2];

		if ((x>=min[0])&&(x<=max[0])
			&&(y>=min[1])&&(y<=max[1])
			&&(z>=min[2])&&(z<=max[2])) {
			break;
		}
	}

	if(i >= 8) {
		/* fallback, avoid using buffer over-run */
		i= 0;
	}

	// printf("i: %d\n", i);
	// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);

	if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program"))
	{
		glEnable(GL_FRAGMENT_PROGRAM_ARB);
		glGenProgramsARB(1, &prog);

		glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
		glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text);

		// cell spacing
		glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
		// custom parameter for smoke style (higher = thicker)
		glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0);
	}
	else
		printf("Your gfx card does not support 3D View smoke drawing.\n");

	GPU_texture_bind(tex, 0);
	if(tex_shadow)
		GPU_texture_bind(tex_shadow, 1);
	else
		printf("No volume shadow\n");

	if (!GPU_non_power_of_two_support()) {
		cor[0] = (float)res[0]/(float)larger_pow2(res[0]);
		cor[1] = (float)res[1]/(float)larger_pow2(res[1]);
		cor[2] = (float)res[2]/(float)larger_pow2(res[2]);
	}

	// our slices are defined by the plane equation a*x + b*y +c*z + d = 0
	// (a,b,c), the plane normal, are given by viewdir
	// d is the parameter along the view direction. the first d is given by
	// inserting previously found vertex into the plane equation

	/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
	ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]);
	dd = 0.05; // ds/512.0f;
	n = 0;
	good_index = i;

	// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);

	points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview");

	while(1) {
		float p0[3];
		float tmp_point[3], tmp_point2[3];

		if(dd*(float)n > ds)
			break;

		copy_v3_v3(tmp_point, viewnormal);
		mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n));
		add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
		d = dot_v3v3(tmp_point2, viewnormal);

		// printf("my d: %f\n", d);

		// intersect_edges returns the intersection points of all cube edges with
		// the given plane that lie within the cube
		numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);

		// printf("points: %d\n", numpoints);

		if (numpoints > 2) {
			copy_v3_v3(p0, points);

			// sort points to get a convex polygon
			for(i = 1; i < numpoints - 1; i++)
			{
				for(j = i + 1; j < numpoints; j++)
				{
					if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3]))
					{
						float tmp2[3];
						copy_v3_v3(tmp2, &points[j * 3]);
						copy_v3_v3(&points[j * 3], &points[i * 3]);
						copy_v3_v3(&points[i * 3], tmp2);
					}
				}
			}

			// printf("numpoints: %d\n", numpoints);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0] )*cor[0]/size[0], (points[i * 3 + 1] - min[1])*cor[1]/size[1], (points[i * 3 + 2] - min[2])*cor[2]/size[2]);
				glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
			}
			glEnd();
		}
		n++;
	}

	tend();
	// printf ( "Draw Time: %f\n",( float ) tval() );

	if(tex_shadow)
		GPU_texture_unbind(tex_shadow);
	GPU_texture_unbind(tex);

	if(GLEW_ARB_fragment_program)
	{
		glDisable(GL_FRAGMENT_PROGRAM_ARB);
		glDeleteProgramsARB(1, &prog);
	}


	MEM_freeN(points);

	if(!gl_blend)
		glDisable(GL_BLEND);
	if(gl_depth)
	{
		glEnable(GL_DEPTH_TEST);
		glDepthMask(GL_TRUE);	
	}
}
Example #18
0
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
                       GPUTexture *tex, float min[3], float max[3],
                       int res[3], float dx, float UNUSED(base_scale), float viewnormal[3],
                       GPUTexture *tex_shadow, GPUTexture *tex_flame)
{
	int i, j, k, n, good_index;
	float d /*, d0 */ /* UNUSED */, dd, ds;
	float *points = NULL;
	int numpoints = 0;
	float cor[3] = {1.0f, 1.0f, 1.0f};
	int gl_depth = 0, gl_blend = 0;

	/* draw slices of smoke is adapted from c++ code authored
	 * by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */
	float cv[][3] = {
		{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
		{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
	};

	/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
	float edges[12][2][3] = {
		{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},

		{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},

		{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
	};

	unsigned char *spec_data;
	float *spec_pixels;
	GPUTexture *tex_spec;

	/* Fragment program to calculate the view3d of smoke */
	/* using 4 textures, density, shadow, flame and flame spectrum */
	const char *shader_basic =
	        "!!ARBfp1.0\n"
	        "PARAM dx = program.local[0];\n"
	        "PARAM darkness = program.local[1];\n"
	        "PARAM render = program.local[2];\n"
	        "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
	        "TEMP temp, shadow, flame, spec, value;\n"
	        "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
	        "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
	        "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
	        "TEX spec, flame.r, texture[3], 1D;\n"
	        /* calculate shading factor from density */
	        "MUL value.r, temp.a, darkness.a;\n"
	        "MUL value.r, value.r, dx.r;\n"
	        "MUL value.r, value.r, f.r;\n"
	        "EX2 temp, -value.r;\n"
	        /* alpha */
	        "SUB temp.a, 1.0, temp.r;\n"
	        /* shade colors */
	        "MUL temp.r, temp.r, shadow.r;\n"
	        "MUL temp.g, temp.g, shadow.r;\n"
	        "MUL temp.b, temp.b, shadow.r;\n"
	        "MUL temp.r, temp.r, darkness.r;\n"
	        "MUL temp.g, temp.g, darkness.g;\n"
	        "MUL temp.b, temp.b, darkness.b;\n"
	        /* for now this just replace smoke shading if rendering fire */
	        "CMP result.color, render.r, temp, spec;\n"
	        "END\n";

	/* color shader */
	const char *shader_color =
	        "!!ARBfp1.0\n"
	        "PARAM dx = program.local[0];\n"
	        "PARAM darkness = program.local[1];\n"
	        "PARAM render = program.local[2];\n"
	        "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
	        "TEMP temp, shadow, flame, spec, value;\n"
	        "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
	        "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
	        "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
	        "TEX spec, flame.r, texture[3], 1D;\n"
	        /* unpremultiply volume texture */
	        "RCP value.r, temp.a;\n"
	        "MUL temp.r, temp.r, value.r;\n"
	        "MUL temp.g, temp.g, value.r;\n"
	        "MUL temp.b, temp.b, value.r;\n"
	        /* calculate shading factor from density */
	        "MUL value.r, temp.a, darkness.a;\n"
	        "MUL value.r, value.r, dx.r;\n"
	        "MUL value.r, value.r, f.r;\n"
	        "EX2 value.r, -value.r;\n"
	        /* alpha */
	        "SUB temp.a, 1.0, value.r;\n"
	        /* shade colors */
	        "MUL temp.r, temp.r, shadow.r;\n"
	        "MUL temp.g, temp.g, shadow.r;\n"
	        "MUL temp.b, temp.b, shadow.r;\n"
	        "MUL temp.r, temp.r, value.r;\n"
	        "MUL temp.g, temp.g, value.r;\n"
	        "MUL temp.b, temp.b, value.r;\n"
	        /* for now this just replace smoke shading if rendering fire */
	        "CMP result.color, render.r, temp, spec;\n"
	        "END\n";

	GLuint prog;

	
	float size[3];

	if (!tex) {
		printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
		return;
	}

#ifdef DEBUG_DRAW_TIME
	TIMEIT_START(draw);
#endif

	/* generate flame spectrum texture */
	#define SPEC_WIDTH 256
	#define FIRE_THRESH 7
	#define MAX_FIRE_ALPHA 0.06f
	#define FULL_ON_FIRE 100
	spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
	flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
	spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
	for (i = 0; i < 16; i++) {
		for (j = 0; j < 16; j++) {
			for (k = 0; k < SPEC_WIDTH; k++) {
				int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
				if (k >= FIRE_THRESH) {
					spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
					spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
					spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
					spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
					        (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
				}
				else {
					spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
				}
			}
		}
	}

	tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);

	sub_v3_v3v3(size, max, min);

	/* maxx, maxy, maxz */
	cv[0][0] = max[0];
	cv[0][1] = max[1];
	cv[0][2] = max[2];
	/* minx, maxy, maxz */
	cv[1][0] = min[0];
	cv[1][1] = max[1];
	cv[1][2] = max[2];
	/* minx, miny, maxz */
	cv[2][0] = min[0];
	cv[2][1] = min[1];
	cv[2][2] = max[2];
	/* maxx, miny, maxz */
	cv[3][0] = max[0];
	cv[3][1] = min[1];
	cv[3][2] = max[2];

	/* maxx, maxy, minz */
	cv[4][0] = max[0];
	cv[4][1] = max[1];
	cv[4][2] = min[2];
	/* minx, maxy, minz */
	cv[5][0] = min[0];
	cv[5][1] = max[1];
	cv[5][2] = min[2];
	/* minx, miny, minz */
	cv[6][0] = min[0];
	cv[6][1] = min[1];
	cv[6][2] = min[2];
	/* maxx, miny, minz */
	cv[7][0] = max[0];
	cv[7][1] = min[1];
	cv[7][2] = min[2];

	copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
	copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
	copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
	copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
	copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */

	// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
	// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);

	edges[0][1][2] = size[2];
	edges[1][1][2] = size[2];
	edges[2][1][2] = size[2];
	edges[3][1][2] = size[2];

	edges[4][1][1] = size[1];
	edges[5][1][1] = size[1];
	edges[6][1][1] = size[1];
	edges[7][1][1] = size[1];

	edges[8][1][0] = size[0];
	edges[9][1][0] = size[0];
	edges[10][1][0] = size[0];
	edges[11][1][0] = size[0];

	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);

	/* find cube vertex that is closest to the viewer */
	for (i = 0; i < 8; i++) {
		float x, y, z;

		x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
		y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
		z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;

		if ((x >= min[0]) && (x <= max[0]) &&
		    (y >= min[1]) && (y <= max[1]) &&
		    (z >= min[2]) && (z <= max[2]))
		{
			break;
		}
	}

	if (i >= 8) {
		/* fallback, avoid using buffer over-run */
		i = 0;
	}

	// printf("i: %d\n", i);
	// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);

	if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) {
		glEnable(GL_FRAGMENT_PROGRAM_ARB);
		glGenProgramsARB(1, &prog);

		glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
		/* set shader */
		if (sds->active_fields & SM_ACTIVE_COLORS)
			glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
		else
			glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);

		/* cell spacing */
		glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
		/* custom parameter for smoke style (higher = thicker) */
		if (sds->active_fields & SM_ACTIVE_COLORS)
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
		else
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
	}
	else
		printf("Your gfx card does not support 3D View smoke drawing.\n");

	GPU_texture_bind(tex, 0);
	if (tex_shadow)
		GPU_texture_bind(tex_shadow, 1);
	else
		printf("No volume shadow\n");

	if (tex_flame) {
		GPU_texture_bind(tex_flame, 2);
		GPU_texture_bind(tex_spec, 3);
	}

	if (!GPU_non_power_of_two_support()) {
		cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]);
		cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]);
		cor[2] = (float)res[2] / (float)power_of_2_max_i(res[2]);
	}

	/* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
	 * (a,b,c), the plane normal, are given by viewdir
	 * d is the parameter along the view direction. the first d is given by
	 * inserting previously found vertex into the plane equation */

	/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
	ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
	dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
	n = 0;
	good_index = i;

	// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);

	points = MEM_callocN(sizeof(float) * 12 * 3, "smoke_points_preview");

	while (1) {
		float p0[3];
		float tmp_point[3], tmp_point2[3];

		if (dd * (float)n > ds)
			break;

		copy_v3_v3(tmp_point, viewnormal);
		mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
		add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
		d = dot_v3v3(tmp_point2, viewnormal);

		// printf("my d: %f\n", d);

		/* intersect_edges returns the intersection points of all cube edges with
		 * the given plane that lie within the cube */
		numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);

		// printf("points: %d\n", numpoints);

		if (numpoints > 2) {
			copy_v3_v3(p0, points);

			/* sort points to get a convex polygon */
			for (i = 1; i < numpoints - 1; i++) {
				for (j = i + 1; j < numpoints; j++) {
					if (!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) {
						float tmp2[3];
						copy_v3_v3(tmp2, &points[j * 3]);
						copy_v3_v3(&points[j * 3], &points[i * 3]);
						copy_v3_v3(&points[i * 3], tmp2);
					}
				}
			}

			/* render fire slice */
			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
				             (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
				             (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
				glVertex3f(points[i * 3 + 0] / fabsf(ob->size[0]),
				           points[i * 3 + 1] / fabsf(ob->size[1]),
				           points[i * 3 + 2] / fabsf(ob->size[2]));
			}
			glEnd();

			/* render smoke slice */
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
				             (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
				             (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
				glVertex3f(points[i * 3 + 0] / fabsf(ob->size[0]),
				           points[i * 3 + 1] / fabsf(ob->size[1]),
				           points[i * 3 + 2] / fabsf(ob->size[2]));
			}
			glEnd();
		}
		n++;
	}

#ifdef DEBUG_DRAW_TIME
	printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
	TIMEIT_END(draw);
#endif

	if (tex_shadow)
		GPU_texture_unbind(tex_shadow);
	GPU_texture_unbind(tex);
	if (tex_flame) {
		GPU_texture_unbind(tex_flame);
		GPU_texture_unbind(tex_spec);
	}
	GPU_texture_free(tex_spec);

	free(spec_data);
	free(spec_pixels);

	if (GLEW_ARB_fragment_program) {
		glDisable(GL_FRAGMENT_PROGRAM_ARB);
		glDeleteProgramsARB(1, &prog);
	}


	MEM_freeN(points);

	if (!gl_blend) {
		glDisable(GL_BLEND);
	}

	if (gl_depth) {
		glEnable(GL_DEPTH_TEST);
		glDepthMask(GL_TRUE);
	}
}
Example #19
0
bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
{
	GPUTexture *src, *target;
	int numslots = 0;
	float invproj[4][4];
	int i;
	/* number of passes left. when there are no more passes, the result is passed to the frambuffer */
	int passes_left = fx->num_passes;
	/* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
	float viewvecs[3][4] = {
	    {-1.0f, -1.0f, -1.0f, 1.0f},
	    {1.0f, -1.0f, -1.0f, 1.0f},
	    {-1.0f, 1.0f, -1.0f, 1.0f}
	};

	if (fx->effects == 0)
		return false;

	/* first, unbind the render-to-texture framebuffer */
	GPU_framebuffer_texture_detach(fx->color_buffer);
	GPU_framebuffer_texture_detach(fx->depth_buffer);

	if (fx->restore_stencil)
		glPopAttrib();

	src = fx->color_buffer;
	target = fx->color_buffer_sec;

	/* set up quad buffer */
	glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
	glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	/* full screen FX pass */

	/* invert the view matrix */
	invert_m4_m4(invproj, projmat);

	/* convert the view vectors to view space */
	for (i = 0; i < 3; i++) {
		mul_m4_v4(invproj, viewvecs[i]);
		/* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
		mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
		if (is_persp)
			mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
		viewvecs[i][3] = 1.0;
	}

	/* we need to store the differences */
	viewvecs[1][0] -= viewvecs[0][0];
	viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];

	/* calculate a depth offset as well */
	if (!is_persp) {
		float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
		mul_m4_v4(invproj, vec_far);
		mul_v3_fl(vec_far, 1.0f / vec_far[3]);
		viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
	}

	/* set invalid color in case shader fails */
	glColor3f(1.0, 0.0, 1.0);
	glDisable(GL_DEPTH_TEST);

	/* ssao pass */
	if (fx->effects & GPU_FX_FLAG_SSAO) {
		GPUShader *ssao_shader;
		ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
		if (ssao_shader) {
			const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
			int color_uniform, depth_uniform;
			int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
			int ssao_jitter_uniform, ssao_concentric_tex;
			float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
			float sample_params[4];

			sample_params[0] = fx->ssao_sample_count;
			/* multiplier so we tile the random texture on screen */
			sample_params[2] = fx->gbuffer_dim[0] / 64.0;
			sample_params[3] = fx->gbuffer_dim[1] / 64.0;

			ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
			ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
			color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
			depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
			viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
			ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
			ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
			ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");

			GPU_shader_bind(ssao_shader);

			GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
			GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
			GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
			GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params);

			GPU_texture_bind(src, numslots++);
			GPU_shader_uniform_texture(ssao_shader, color_uniform, src);

			GPU_texture_bind(fx->depth_buffer, numslots++);
			GPU_depth_texture_mode(fx->depth_buffer, false, true);
			GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);

			GPU_texture_bind(fx->jitter_buffer, numslots++);
			GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);

			GPU_texture_bind(fx->ssao_concentric_samples_tex, numslots++);
			GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_concentric_samples_tex);

			/* draw */
			gpu_fx_bind_render_target(&passes_left, fx, ofs, target);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

			/* disable bindings */
			GPU_texture_unbind(src);
			GPU_depth_texture_mode(fx->depth_buffer, true, false);
			GPU_texture_unbind(fx->depth_buffer);
			GPU_texture_unbind(fx->jitter_buffer);
			GPU_texture_unbind(fx->ssao_concentric_samples_tex);

			/* may not be attached, in that case this just returns */
			if (target) {
				GPU_framebuffer_texture_detach(target);
				if (ofs) {
					GPU_offscreen_bind(ofs, false);
				}
				else {
					GPU_framebuffer_restore();
				}
			}

			/* swap here, after src/target have been unbound */
			SWAP(GPUTexture *, target, src);
			numslots = 0;
		}
	}

	/* second pass, dof */
	if (fx->effects & GPU_FX_FLAG_DOF) {
		const GPUDOFSettings *fx_dof = fx->settings.dof;
		GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
		float dof_params[4];
		float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
		/* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
		 * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
		 * because the shader reads coordinates in world space, which is in blender units. */
		float scale_camera = 0.001f / scale;
		/* we want radius here for the aperture number  */
		float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;

		dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length));
		dof_params[1] = fx_dof->focus_distance / scale;
		dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
		dof_params[3] = 0.0f;

		/* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
		 * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
		 * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
		dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
		dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
		dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
		dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
		dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);

		/* error occured, restore framebuffers and return */
		if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
			GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
			GPU_framebuffer_restore();
			return false;
		}

		/* pass first, first level of blur in low res buffer */
		{
			int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
			int viewvecs_uniform;

			float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};

			dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
			invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
			color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
			depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
			viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");

			GPU_shader_bind(dof_shader_pass1);

			GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
			GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
			GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);

			GPU_texture_bind(src, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);

			GPU_texture_bind(fx->depth_buffer, numslots++);
			GPU_depth_texture_mode(fx->depth_buffer, false, true);
			GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);

			/* target is the downsampled coc buffer */
			GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
			/* binding takes care of setting the viewport to the downsampled size */
			GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
			/* disable bindings */
			GPU_texture_unbind(src);
			GPU_depth_texture_mode(fx->depth_buffer, true, false);
			GPU_texture_unbind(fx->depth_buffer);

			GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
			numslots = 0;
		}

		/* second pass, gaussian blur the downsampled image */
		{
			int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
			int viewvecs_uniform;
			float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
			                               1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
			float tmp = invrendertargetdim[0];
			invrendertargetdim[0] = 0.0f;

			dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);

			dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
			invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
			color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
			depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
			viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");

			/* Blurring vertically */
			GPU_shader_bind(dof_shader_pass2);

			GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
			GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
			GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);

			GPU_texture_bind(fx->depth_buffer, numslots++);
			GPU_depth_texture_mode(fx->depth_buffer, false, true);
			GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);

			GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);

			/* use final buffer as a temp here */
			GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);

			/* Drawing quad */
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

			/* *unbind/detach */
			GPU_texture_unbind(fx->dof_near_coc_buffer);
			GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);

			/* Blurring horizontally */
			invrendertargetdim[0] = tmp;
			invrendertargetdim[1] = 0.0f;
			GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);

			GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);

			GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

			/* *unbind/detach */
			GPU_depth_texture_mode(fx->depth_buffer, true, false);
			GPU_texture_unbind(fx->depth_buffer);

			GPU_texture_unbind(fx->dof_near_coc_final_buffer);
			GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);

			dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);

			numslots = 0;
		}

		/* third pass, calculate near coc */
		{
			int near_coc_downsampled, near_coc_blurred;

			near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
			near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");

			GPU_shader_bind(dof_shader_pass3);

			GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);

			GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);

			GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
			/* disable bindings */
			GPU_texture_unbind(fx->dof_near_coc_buffer);
			GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);

			/* unbinding here restores the size to the original */
			GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);

			numslots = 0;
		}

		/* fourth pass blur final coc once to eliminate discontinuities */
		{
			int near_coc_downsampled;
			int invrendertargetdim_uniform;
			float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
			                               1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};

			near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
			invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");

			GPU_shader_bind(dof_shader_pass4);

			GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
			GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);

			GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
			/* disable bindings */
			GPU_texture_unbind(fx->dof_near_coc_final_buffer);

			/* unbinding here restores the size to the original */
			GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
			GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);

			numslots = 0;
		}

		/* final pass, merge blurred layers according to final calculated coc */
		{
			int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
			int invrendertargetdim_uniform, viewvecs_uniform;
			float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};

			medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
			high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
			dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
			invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
			original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
			depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
			viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");

			GPU_shader_bind(dof_shader_pass5);

			GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
			GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
			GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);

			GPU_texture_bind(src, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);

			GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);

			GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
			GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);

			GPU_texture_bind(fx->depth_buffer, numslots++);
			GPU_depth_texture_mode(fx->depth_buffer, false, true);
			GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);

			/* if this is the last pass, prepare for rendering on the frambuffer */
			gpu_fx_bind_render_target(&passes_left, fx, ofs, target);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
			/* disable bindings */
			GPU_texture_unbind(fx->dof_near_coc_buffer);
			GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
			GPU_texture_unbind(src);
			GPU_depth_texture_mode(fx->depth_buffer, true, false);
			GPU_texture_unbind(fx->depth_buffer);

			/* may not be attached, in that case this just returns */
			if (target) {
				GPU_framebuffer_texture_detach(target);
				if (ofs) {
					GPU_offscreen_bind(ofs, false);
				}
				else {
					GPU_framebuffer_restore();
				}
			}

			SWAP(GPUTexture *, target, src);
			numslots = 0;
		}
	}

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	GPU_shader_unbind();

	return true;
}
Example #20
0
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
                       const float min[3], const float max[3],
                        const float viewnormal[3])
{
	if (!sds->tex || !sds->tex_shadow) {
		fprintf(stderr, "Could not allocate 3D texture for volume rendering!\n");
		return;
	}

	const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame;

	GPUShader *shader = GPU_shader_get_builtin_shader(
	                        (use_fire) ? GPU_SHADER_SMOKE_FIRE : GPU_SHADER_SMOKE);

	if (!shader) {
		fprintf(stderr, "Unable to create GLSL smoke shader.\n");
		return;
	}

	const float ob_sizei[3] = {
	    1.0f / fabsf(ob->size[0]),
	    1.0f / fabsf(ob->size[1]),
	    1.0f / fabsf(ob->size[2])
	};

	const float size[3] = { max[0] - min[0], max[1] - min[1], max[2] - min[2] };
	const float invsize[3] = { 1.0f / size[0], 1.0f / size[1], 1.0f / size[2] };

#ifdef DEBUG_DRAW_TIME
	TIMEIT_START(draw);
#endif

	/* setup smoke shader */

	int soot_location = GPU_shader_get_uniform(shader, "soot_texture");
	int spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
	int shadow_location = GPU_shader_get_uniform(shader, "shadow_texture");
	int flame_location = GPU_shader_get_uniform(shader, "flame_texture");
	int actcol_location = GPU_shader_get_uniform(shader, "active_color");
	int stepsize_location = GPU_shader_get_uniform(shader, "step_size");
	int densityscale_location = GPU_shader_get_uniform(shader, "density_scale");
	int invsize_location = GPU_shader_get_uniform(shader, "invsize");
	int ob_sizei_location = GPU_shader_get_uniform(shader, "ob_sizei");
	int min_location = GPU_shader_get_uniform(shader, "min");

	GPU_shader_bind(shader);

	GPU_texture_bind(sds->tex, 0);
	GPU_shader_uniform_texture(shader, soot_location, sds->tex);

	GPU_texture_bind(sds->tex_shadow, 1);
	GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow);

	GPUTexture *tex_spec = NULL;

	if (use_fire) {
		GPU_texture_bind(sds->tex_flame, 2);
		GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame);

		tex_spec = create_flame_spectrum_texture();
		GPU_texture_bind(tex_spec, 3);
		GPU_shader_uniform_texture(shader, spec_location, tex_spec);
	}

	float active_color[3] = { 0.9, 0.9, 0.9 };
	float density_scale = 10.0f;
	if ((sds->active_fields & SM_ACTIVE_COLORS) == 0)
		mul_v3_v3(active_color, sds->active_color);

	GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color);
	GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx);
	GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale);
	GPU_shader_uniform_vector(shader, min_location, 3, 1, min);
	GPU_shader_uniform_vector(shader, ob_sizei_location, 3, 1, ob_sizei);
	GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize);

	/* setup slicing information */

	const int max_slices = 256;
	const int max_points = max_slices * 12;

	VolumeSlicer slicer;
	copy_v3_v3(slicer.min, min);
	copy_v3_v3(slicer.max, max);
	copy_v3_v3(slicer.size, size);
	slicer.verts = MEM_mallocN(sizeof(float) * 3 * max_points, "smoke_slice_vertices");

	const int num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal);

	/* setup buffer and draw */

	int gl_depth = 0, gl_blend = 0;
	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

	GLuint vertex_buffer;
	glGenBuffers(1, &vertex_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer.verts[0][0], GL_STATIC_DRAW);

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, NULL);

	glDrawArrays(GL_TRIANGLES, 0, num_points);

	glDisableClientState(GL_VERTEX_ARRAY);

#ifdef DEBUG_DRAW_TIME
	printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
	TIMEIT_END(draw);
#endif

	/* cleanup */

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDeleteBuffers(1, &vertex_buffer);

	GPU_texture_unbind(sds->tex);
	GPU_texture_unbind(sds->tex_shadow);

	if (use_fire) {
		GPU_texture_unbind(sds->tex_flame);
		GPU_texture_unbind(tex_spec);
		GPU_texture_free(tex_spec);
	}

	MEM_freeN(slicer.verts);

	GPU_shader_unbind();

	if (!gl_blend) {
		glDisable(GL_BLEND);
	}

	if (gl_depth) {
		glEnable(GL_DEPTH_TEST);
	}
}
Example #21
0
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
{
	GLenum type, format, internalformat;
	void *pixels = NULL;

	GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
	tex->w = w;
	tex->h = h;
	tex->depth = depth;
	tex->number = -1;
	tex->refcount = 1;
	tex->target = GL_TEXTURE_3D;
	tex->target_base = GL_TEXTURE_3D;

	glGenTextures(1, &tex->bindcode);

	if (!tex->bindcode) {
		fprintf(stderr, "GPUTexture: texture create failed: %d\n",
			(int)glGetError());
		GPU_texture_free(tex);
		return NULL;
	}

	tex->number = 0;
	glBindTexture(tex->target, tex->bindcode);

	GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");

	type = GL_FLOAT;
	if (channels == 4) {
		format = GL_RGBA;
		internalformat = GL_RGBA8;
	}
	else {
		format = GL_RED;
		internalformat = GL_INTENSITY8;
	}

	/* 3D textures are quite heavy, test if it's possible to create them first */
	glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);

	bool rescale = false;
	int r_width;

	glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);

	while (r_width == 0) {
		rescale = true;
		tex->w /= 2;
		tex->h /= 2;
		tex->depth /= 2;
		glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
	}

	/* really unlikely to happen but keep this just in case */
	tex->w = max_ii(tex->w, 1);
	tex->h = max_ii(tex->h, 1);
	tex->depth = max_ii(tex->depth, 1);

#if 0
	if (fpixels)
		pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
#endif

	GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");

	/* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
	 * for gooseberry */
	if (rescale && fpixels) {
		/* FIXME: should these be floating point? */
		const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
		float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d");

		GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");

		for (unsigned k = 0; k < tex->depth; k++) {
			for (unsigned j = 0; j < tex->h; j++) {
				for (unsigned i = 0; i < tex->w; i++) {
					/* obviously doing nearest filtering here,
					 * it's going to be slow in any case, let's not make it worse */
					float xb = i * xf;
					float yb = j * yf;
					float zb = k * zf;
					unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
					unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);

					if (channels == 4) {
						tex3d[offset * 4] = fpixels[offset_orig * 4];
						tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
						tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
						tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
					}
					else
						tex3d[offset] = fpixels[offset_orig];
				}
			}
		}

		glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);

		MEM_freeN(tex3d);
	}
	else {
		if (fpixels) {
			glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
			GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
		}
	}


	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

	if (pixels)
		MEM_freeN(pixels);

	GPU_texture_unbind(tex);

	return tex;
}