How to render 3d smoke using PovRay


#1

Hi guys,

I have been working on simulating smoke by adapting Jos Stam’s Stable Fluids. As as result of putting all code together, what I am left with is a 3d array of density and velocity values that I have absolutely no idea how to use them to render a nice 3d smoke on to my screen. Then after doing some research I learned about volumetric rendering. I just know the concept at a very abstract level and I am very new to all this. I also came across PovRay and I think a lot of people use this software for exactly this purpose. Is there anyone out there who could give me a direction in this? I have absolutely no idea as to what to do with my density values in the arrays. If someone could give me a brief step-by-step approach to take my work to the next step in rendering on to the screen, I’d really appreciate it!

Thanks much!


#2

So you have your fluid, and the next thing you want to do is get it rendered?
It sounds like you need to move into shader development territory.
Get a rendering engine with custom shader capabilities (the largest majority of them), and start writing what will probably end up being a volume shader.

Get familiar with just rendering the raw info, so you get used to the framework, and then you can start looking at shading models for fluids.

I know this is horribly vague, but to some extent so is the question.

What did you do all the dynamics work in? Most packages come with a rendering engine with shader facilities, MRay being the most prominent in terms of availability I guess.

I’m not familiar with POV-Ray, past knowing it by fame, to even know if it has a shader API, sorry.

You could also consider a free RMan compliant engine, 3Delight offers the first license for free, and is an excellent fully featured and production proven platform.
You will need to get your data output to some RMan friendly format though, which if you worked completely outside any DCC package, might lead to you having to learn the RMan platform to at least the level where you can output a rib container for your volume, and maybe ptc files if you want to take some advantage of the point cloud facilities to help parts of the process.

Short version: figure out a viable shading and rendering platform, and pursue the rest of your bridge in that.


#3

also if you are used to work with maya or some other 3d package there are always commands to directly write to your fluid container. in maya for example you can use mel to get your data written into the container. this would be a very easy way to get your data visualized but maybe not the most efficient one.

volume render can get very expensive especially when it comes to shadows or even worse volume scattering. having a rendering package that is capable of such features could help you getting nice renders without spending too much time on writting your own rendering system. i personally prefer Prman because its support for deep shadows, motion blurred fluids, volume scattering and extremely useful quality controls which allow you to handle rendertime well.
however prman is unfortunately not freely available. 3delight offers a free license for 2cores only but is a fantastic renderer aswell. MRay comes with maya and in combination with writing to the maya fluid container through MEL or API commands is what i would suggest you as long as you don’t have acceess to prman or similar

grs
Patrik


#4

@ ThE_JacO…thanks for the direction. I took your advise and did a quick exploratory research on how to write shaders. It looks like RenderMonkey supports OpenGL Shading Language and so, that might be my pick for this project because my code is entirely built on C++ and OpenGL. FYI, I use Visual Studio as a platform for running my solver.

I would still need more direction on this. I saw some simple tutorials to write a basic shader with a simple illumination model with a light source etc. But i have no clue as to how can I even start thinking in terms of rendering a smoke with a custom shader? Let me briefly explain what I am currently doing to display my smoke on the screen (just so you have some idea about what I am talking about)…


void draw_density ( void )
{
	int i, j, k;
	float _x0, _y0, _x1, _y1, hh, 
        float d000, d010, d100, d110, d001, d011, d101, d111; //to store density values

	hh = 1.0f/150.0f;

	glBegin ( GL_QUADS );

		for ( i=0 ; i<W ; i++ ) {
			x = (i-0.5f)*hh;
			for ( j=0 ; j<H ; j++ ) {
				y = (j-0.5f)*hh;

				for(k=0; k<D; k++) {

					d000 = S->St->gridCell[i][j][k];
					d010 = S->St->gridCell[i][j+1][k];
					d110 = S->St->gridCell[i+1][j+1][k];
					d100 = S->St->gridCell[i+1][j][k];
				
					d001 = S->St->gridCell[i][j][k+1];
					d011 = S->St->gridCell[i][j+1][k+1];
					d111 = S->St->gridCell[i+1][j+1][k+1];
					d101 = S->St->gridCell[i+1][j][k+1];
					
					_x0 = i*hh;
					_y0 = j*hh;
					
					_x1 = _x0 + hh*k*0.3f; //X transformed from 3D to 2D
					_y1 = _y0 + hh*k*0.3f;//Y transformed from 3D to 2D

				glColor4f ( d000, d000, d000, d000 ); 
				glVertex2f(_x0, _y0);

				glColor4f ( d010, d010, d010, d010 ); 
				glVertex2f(_x0,_y0+hh);

				glColor4f ( d110, d110, d110, d110 ); 
				glVertex2f(_x0+hh,_y0+hh);

				glColor4f ( d100, d100, d100, d100 ); 
				glVertex2f(_x0+hh,_y0);


				glColor4f ( d001, d001, d001, d001 ); 
				glVertex2f(_x1, _y1);

				glColor4f ( d011, d011, d011, d011 ); 
				glVertex2f(_x1,_y1+hh);

				glColor4f ( d111, d111, d111, d111 ); 
				glVertex2f(_x1+hh,_y1+hh);

				glColor4f ( d101, d101, d101, d101 ); 
				glVertex2f(_x1+hh,_y1);
				}
			}
		}

		glEnd();


Basically, I have all the scalar (density) values stored in a 3D array, which I am using as color values to draw the quads. Also, I am transforming X and Y values from 3D to 2D by a simple projection formula (_x1 = _x0 + hhk0.3f), although this conversion doesnt seem to have that big a difference. I still only see a 2D flat image. My guess is if I could somehow use these scalar values in my custom shader ( which I am yet to learn to write :-p), will they be able to render properly as a 3D smoke? If I sound too vague, well, that’s how my understanding of shaders and rendering is still. If you need any other specific information about my code, I can provide that. But please please, help me with this part. I would highly appreciate it!

Thanks again.


#5

google for “raymarching”, maybe this would be of help.

you can render your container as a box and let the shader march through your volume and accumulate opacities to get the final color. this should work well for previsualization. for final render however you’d need to get your shadows working. raytraced shadows could be implemented pretty easily since this would be just another “raymarched”-ray per sample per ray resulting in quite some additional drop in performance but with nice shadows. deep shadows would be much more complex to implement but the performance boost is significant.

grs
Patrik


#6

thanks patrik…but assuming I have literally no background in rendering, where do I start? I did read about raymarching, volumetric raytracing, and other possible ways to render but since I have no background in these, I have no clue where to start. Do I need to install any tool? Learn any language?, and how do I make my program (in C++) talk to this part of the implementation? Do I need to export the scalar values to some compatible file format before I do anything? So I am looking for some sort of a step-by-step walk-through for these simple and very basic questions.

Any help is appreciated!


#7

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.