体积雾?
小弟菜鸟
希望大虾指导一下体积雾是怎么做出来的?
把大概的流程和我说下
[解决办法]
首先根据斯托克斯方程和stam的那篇文章算出每个体素的函数值(浓度值),然后用raycasting光线投射:
从屏幕的每个pixel发出射线,与体积雾相交,沿射线采样再integrate+alphablend,计算出每个pixel的颜色值,具体可以参见siggraph 2004 course note 和2009course note中的olume render部分
[解决办法]
一般都是用的公告板实现的。
[解决办法]
这个代码希望对楼主有帮助
/* * smoke.c * David Blythe, 1997 * * An example of using a texture map to simulate smoke. * */#include <math.h>#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#include "texture.h"#ifdef _WIN32/* Win32 math.h doesn't define float versions of the trig functions. */#define sinf sin#define cosf cos#define atan2f atan2/* nor does it define M_PI. */#define M_PI 3.14159265#endifstatic int texture = 1;static float rot = 0;static float opacity = 1.0;static float intensity = 1.0;static float size = .001, delta = 0;static float scale = 1.;static float transx, transy, rotx, roty;static int ox = -1, oy = -1;static int mot = 0;#define PAN 1#define ROT 2voidpan(int x, int y) { transx += (x-ox)/500.; transy -= (y-oy)/500.; ox = x; oy = y; glutPostRedisplay();}voidrotate(int x, int y) { rotx += x-ox; if (rotx > 360.) rotx -= 360.; else if (rotx < -360.) rotx += 360.; roty += y-oy; if (roty > 360.) roty -= 360.; else if (roty < -360.) roty += 360.; ox = x; oy = y; glutPostRedisplay();}voidmotion(int x, int y) { if (mot == PAN) pan(x, y); else if (mot == ROT) rotate(x,y);}voidmouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) { switch(button) { case GLUT_LEFT_BUTTON: mot = PAN; motion(ox = x, oy = y); break; case GLUT_RIGHT_BUTTON: mot = ROT; motion(ox = x, oy = y); break; case GLUT_MIDDLE_BUTTON: break; } } else if (state == GLUT_UP) { mot = 0; }}void afunc(void) { static int state; if (state ^= 1) { glAlphaFunc(GL_GREATER, .01); glEnable(GL_ALPHA_TEST); } else { glDisable(GL_ALPHA_TEST); }}void bfunc(void) { static int state; if (state ^= 1) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } else { glDisable(GL_BLEND); }}void tfunc(void) { texture ^= 1;}void up(void) { scale += .1; }void down(void) { scale -= .1; }void left(void) { intensity -= .05f; if (intensity < 0.f) intensity = 0.0f; }void right(void) { intensity += .05f; if (intensity > 1.f) intensity = 1.0f; }void help(void) { printf("Usage: smoke [image]\n"); printf("'h' - help\n"); printf("'a' - toggle alpha test\n"); printf("'b' - toggle blend\n"); printf("'t' - toggle texturing\n"); printf("'UP' - scale up\n"); printf("'DOWN' - scale down\n"); printf("'LEFT' - darken\n"); printf("'RIGHT' - brighten\n"); printf("left mouse - pan\n"); printf("right mouse - rotate\n");}void init(char *filename) { static unsigned *image; static int width, height, components; if (filename) { image = read_texture(filename, &width, &height, &components); if (image == NULL) { fprintf(stderr, "Error: Can't load image file \"%s\".\n", filename); exit(EXIT_FAILURE); } else { printf("%d x %d image loaded\n", width, height); }#if 0 if (components == 1) { GLubyte *p = (GLubyte *)image; int i; for (i = 0; i < width*height; i++) { p[i*4+3] = p[i*4+0]; } components = 2; }#endif if (components != 2 && components != 4) { printf("must be an RGBA or LA image\n"); exit(EXIT_FAILURE); } } else { int i, j; unsigned char *img; components = 4; width = height = 512; image = (unsigned *) malloc(width*height*sizeof(unsigned)); img = (unsigned char *)image; for (j = 0; j < height; j++) for (i = 0; i < width; i++) { int w2 = width/2, h2 = height/2; if (i & 32) img[4*(i+j*width)+0] = 0xff; else img[4*(i+j*width)+1] = 0xff; if (j&32) img[4*(i+j*width)+2] = 0xff; if ((i-w2)*(i-w2) + (j-h2)*(j-h2) > 64*64 && (i-w2)*(i-w2) + (j-h2)*(j-h2) < 300*300) img[4*(i+j*width)+3] = 0xff; } } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50.,1.,.1,20.); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.,0.,-5.5); glClearColor(.25f, .25f, .75f, .25f); glAlphaFunc(GL_GREATER, 0.016); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE);}
[解决办法]
光线在雾中传输的距离决定了雾的颜色。
你可以绘制两编深度图,通过求差来算出雾的前后表面的距离,然后得出雾的颜色