读书人

体积雾?解决方案

发布时间: 2012-03-18 13:55:38 作者: rapoo

体积雾?
小弟菜鸟
希望大虾指导一下体积雾是怎么做出来的?
把大概的流程和我说下

[解决办法]
首先根据斯托克斯方程和stam的那篇文章算出每个体素的函数值(浓度值),然后用raycasting光线投射:
从屏幕的每个pixel发出射线,与体积雾相交,沿射线采样再integrate+alphablend,计算出每个pixel的颜色值,具体可以参见siggraph 2004 course note 和2009course note中的olume render部分
[解决办法]
一般都是用的公告板实现的。
[解决办法]
这个代码希望对楼主有帮助

C/C++ code
/* *  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);} 


[解决办法]
光线在雾中传输的距离决定了雾的颜色。
你可以绘制两编深度图,通过求差来算出雾的前后表面的距离,然后得出雾的颜色

读书人网 >网络游戏

热点推荐