⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sph_render.c

📁 游戏编程精粹6第中关于粒子的实时流体仿真系统,对入门的游戏开发者很有帮助.
💻 C
字号:
#include <memory.h>
#include "sph_render.h"
#include "gpu_util.h"
#include "sph_surf.h"

#include <GL/glut.h>


#ifdef NO_NVCG
static GLuint water_fp;
static GLuint water_vp;
#else
static CGprogram water_fragment;
static CGprogram water_vertex;
#endif


#ifdef SHADER_EMBEDDED
#include "embedded/fp_water_fragment.h"
#include "embedded/vp_water_vertex.h"
#endif

void sph_render_init_shaders()
{
}

void sph_render_create(sph_render* r)
{
	r->volume = NULL;

	r->pp = vec3_alloc(150000);
#ifdef SPH_ALPHA_REFRACT
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

#endif

#ifdef SPH_SHADER
#ifdef NO_NVCG
	glGenProgramsARB(1, &water_fp);
	glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, water_fp);
	glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
		GL_PROGRAM_FORMAT_ASCII_ARB,
		strlen(fp_str_water_fragment),
		(const GLubyte *)fp_str_water_fragment);
	gput_printf("Water fragment program initialized\n");

	glGenProgramsARB(1, &water_vp);
	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, water_vp);
	glProgramStringARB(GL_VERTEX_PROGRAM_ARB,
		GL_PROGRAM_FORMAT_ASCII_ARB,
		strlen(vp_str_water_vertex),
		(const GLubyte *)vp_str_water_vertex);

	//set parameters for fresnel reflection
	//glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 13, 2.0f, 2.0f, 0.1f, 0.0f);

	gput_printf("Water vertex program initialized\n");

	check_gl_error();

#else
	LOAD_FRAGMENT_PROGRAM(water_fragment, "water_fragment.cg");
	LOAD_VERTEX_PROGRAM(water_vertex, "water_vertex.cg");


	check_cg_error();
#endif
#endif
}

void sph_render_destroy(sph_render* r)
{
}

void enable_water_shader()
{
#ifdef NO_NVCG
	glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, water_fp);
	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, water_vp);
	glEnable(GL_FRAGMENT_PROGRAM_ARB);
	glEnable(GL_VERTEX_PROGRAM_ARB);
	gput_printf("enable water shader\n");
#else
	cgGLEnableProfile(FP_PROFILE);
	cgGLEnableProfile(VP_PROFILE);
	cgGLBindProgram(water_fragment);
	cgGLBindProgram(water_vertex);
	check_cg_error();
#endif
	check_gl_error();
}

void disable_water_shader()
{
#ifdef NO_NVCG
	glDisable(GL_FRAGMENT_PROGRAM_ARB);
	glDisable(GL_VERTEX_PROGRAM_ARB);	
#else
	cgGLDisableProfile(FP_PROFILE);
	cgGLDisableProfile(VP_PROFILE);		
#endif
}


/**
 * Set the configuration such as resolution for Marching Cubes
 */
void sph_render_set_config(sph_render* r, float stride, int range, float iradius)
{
	float iso_radius;
	
	free(r->volume);

	r->iso_radius = iradius;
	iso_radius = iradius;
	r->mc_stride = stride;
	r->mc_range = range;

//	volume = (float*)malloc(vol_width*vol_width*vol_depth*sizeof(float));
	r->volume = (float*)malloc(100*100*100*sizeof(float));
	if (r->volume == NULL)
		printf("Volume couldn't be allocated\n");
}

void sph_render_create_implicit(sph_render* r, float k, const vector3* pos, int n_particles, const matrix4* m, cpu_sph* sph)
{
	int i;
	float inv_stride;
	float stride;
	float stride2;
	//float v;
	int x;
	int y;
	int z;

	float fmin_x;
	float fmax_x;
	float fmin_y;
	float fmax_y;
	float fmin_z;
	float fmax_z;

	int min_x;
	int max_x;
	int min_y;
	int max_y;
	int min_z;
	int max_z;
	
	int vol_width;
	int vol_height;
	int vol_depth;

	
	//vector3 volpos;

	vector3 piv; /* position in volume */

#ifdef LIMIT_VOLUME
	vector3 x_obs;
	vector3 y_obs;
	vector3 z_obs;
	vec3_set(&x_obs, 1.0f, 0.0f, 0.0f);
	vec3_set(&y_obs, 0.0f, 1.0f, 0.0f);
	vec3_set(&z_obs, 0.0f, 0.0f, 1.0f);
		mat4_mulvec3_as_mat3(&x_obs, m, &x_obs);
		mat4_mulvec3_as_mat3(&y_obs, m, &y_obs);
		mat4_mulvec3_as_mat3(&z_obs, m, &z_obs);
#endif

	stride = r->mc_stride;
	stride2 = stride*stride;
	inv_stride = 1.0f/stride;

	fmin_x = fmin_y = fmin_z = 1000;
	fmax_x = fmax_y = fmax_z = -1000;
	for (i = 0; i < n_particles; i++)
	{
		const vector3* p = &pos[i];
		if (fmin_x > p->x)
			fmin_x = p->x;
		if (fmax_x < p->x)
			fmax_x = p->x;
		if (fmin_y > p->y)
			fmin_y = p->y;
		if (fmax_y < p->y)
			fmax_y = p->y;
		if (fmin_z > p->z)
			fmin_z = p->z;
		if (fmax_z < p->z)
			fmax_z = p->z;
	}

	//printf("%.4f, %.4f, %.4f\n", fmax_x, fmax_y, fmax_z);
	vec3_set(&r->volpos, fmin_x - r->mc_range*stride, fmin_y - r->mc_range*stride, fmin_z - r->mc_range*stride);
//	vec3_set(&r->volpos, fmin_x, fmin_y, fmin_z);
	min_x = 0;
	min_y = 0;
	min_z = 0;
	inv_stride = 1.0f/stride;
	max_x = (fmax_x - fmin_x)*inv_stride;
	max_y = (fmax_y - fmin_y)*inv_stride;
	max_z = (fmax_z - fmin_z)*inv_stride;

	if ((min_x < 0) || (min_y < 0) || (min_z < 0))
		printf("min_x=%d, min_y=%d, min_z=%d\n", min_x, min_y, min_z);

	
	vol_width = max_x + r->mc_range*2+ 6;
	vol_height = max_y + r->mc_range*2 + 6;
	vol_depth = max_z + r->mc_range*2 + 6;
	


	memset(r->volume, 0, vol_width*vol_height*vol_depth*sizeof(float));
	
	r->im_vol.density = r->volume;
	r->im_vol.width = vol_width;
	r->im_vol.height = vol_height;
	r->im_vol.depth = vol_depth;
	r->im_vol.voxelsize = stride;


	//printf("\n---------------------------\n");
	for (i = 0; i < n_particles; i++)
	{
#ifdef LIMIT_VOLUME
		vector3 pos_obs;

#endif
		float bias = 1.0f;

		vec3_sub(&piv, &pos[i], &r->volpos);
		vec3_scale(&piv, 1.0f/stride, &piv);


		for (z = -r->mc_range; z <= r->mc_range; z++)
		{
			//vindex += vol_width*vol_height;
			for (y = -r->mc_range; y <= r->mc_range; y++)
			{
			//	vindex += vol_width;
				for (x = -r->mc_range; x <= r->mc_range; x++)
				{
					int vindex;
					float v;
					float h2_r2;

					float dx;
					float dy;
					float dz;


					dx = ((int)piv.x)*stride + r->volpos.x - pos[i].x + stride*x;
					dy = ((int)piv.y)*stride + r->volpos.y - pos[i].y + stride*y;
					dz = ((int)piv.z)*stride + r->volpos.z - pos[i].z + stride*z;

					h2_r2 = max(r->iso_radius*r->iso_radius - (dx*dx + dy*dy + dz*dz), 0.0f);

					v = k*h2_r2*h2_r2*h2_r2;

					
					vindex = (int)(piv.x + x - min_x + 2) 
						+ ((int)(piv.y + y - min_y + 2))*vol_width
						+ ((int)(piv.z + z - min_z + 2))*vol_width*vol_height;
						
					if ((vindex < 0) || (vindex > vol_width*vol_height*vol_depth))
						continue;

					r->volume[vindex] += v;
				}
			}
		}
	}
	r->vol_width = vol_width;
	r->vol_height = vol_height;
	r->vol_depth = vol_depth;
}

/**
 * Draw the fluid surface
 */
void sph_render_draw_surface(sph_render* r, float threshold)
{
			
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glTranslatef(-0.01f, -0.01f, -0.01f);
	glTranslatef(r->volpos.x, r->volpos.y, r->volpos.z);


//	glColor3f(1.0f, 1.0f, 1.0f);

#ifdef SPH_SHADER
#ifdef NO_NVCG
	glEnable(GL_FRAGMENT_PROGRAM_ARB);
	glEnable(GL_VERTEX_PROGRAM_ARB);
#else
	cgGLEnableProfile(FP_PROFILE);
	cgGLEnableProfile(VP_PROFILE);
	cgGLBindProgram(water_fragment);
	cgGLBindProgram(water_vertex);
	check_cg_error();
#endif
#endif	
	
#ifdef SPH_ALPHA_REFRACT
	glEnable(GL_BLEND);
	glColor4f(1.0f, 1.0f, 1.0f, 0.4f);
#endif

	//glDisable(GL_CULL_FACE);
	//glutSolidTeapot(0.05f);
	
	render_marching_cubes(&r->im_vol,
		0, r->vol_width,
		0, r->vol_height,
		0, r->vol_depth,
		threshold);


#ifdef SPH_SHADER
#ifdef NO_NVCG
	glDisable(GL_FRAGMENT_PROGRAM_ARB);
	glDisable(GL_VERTEX_PROGRAM_ARB);	
#else
	cgGLDisableProfile(FP_PROFILE);
	cgGLDisableProfile(VP_PROFILE);		
#endif
#endif

#ifdef SPH_ALPHA_REFRACT
	glDisable(GL_BLEND);
#endif
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	//glMatrixMode(GL_TEXTURE);
	//glPopMatrix();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -