Ray calculation for volumetric spotlight effect

Recommended Posts

Hi,

I want to add a volumetric light effect to my spotslights and because of this I want to do raymarching in a cone volume (the spotlight cone). Is there a handy way for me to distribute rays (basically get a list of origins and directions) evenly inside the spotlight cone? Say I start with 5 rays where the algorithm would give me one ray straight forward and four rays at the edge of the cone (up, down, left and right), but if I increase the number of rays the algorithm would give me more and more rays, essentially giving me a higher detail cone volume.

The algorithm would not have to be real-time as I can very well precalculate the rays based on some quality setting at startup but it would still be nice to not have to calculate them by hand. Any tips?

Share this post


Link to post
Share on other sites

Lets gor now dont use rotation and translation you define a cone as two functions  that one outputs radius given the height. Consider a spotlight as two points one is the cone top (start pos) second is at the bottom center, the line you define points toward the direction of a spotlight. Given distance function that i talked about earlier, you compute closest point on a segment given actual depth vertex pos, and compare how much actual fragment gets the light

 

 

And sorry i didnt even read your question lol

Share this post


Link to post
Share on other sites
struct SamplePattern
	{
		std::vector<vec> dir;
		
		// 5 rings: 98 samples
		// 4 rings: 66 samples
		// 3 rings: 40 samples
		// 2 rings: 21 samples
		// 1 ring: 8 samples

		void Init (const int rings, const float degrees)
		{
			dir.clear();
			if (rings < 1) 
			{
				dir.push_back (vec(0,1,0));
				return;
			}
			float angle = degrees / 180.0f * PI;
			float maxRad = sin(angle);
			//RenderCircle (maxRad+0.01, vec(0,0,0), vec (0,1,0), 1,0,0);

			for (int r=0; r<=rings; r++)
			{
				float rT = float(r) / float (rings);
				//float theta = rT * angle;
				//float rad = sin(theta);

				float rad = maxRad * rT;
				float theta = asin(rad);

				float perim = rad * 2.0f * PI;
				float numRingSamples = perim * (float (rings) / maxRad);
				int num = (int) numRingSamples;
					//RenderCircle (rad, vec(0,cos(theta),0), vec (0,1,0), 1,1,1);
					//RenderCircle (rad, vec(0,0,0), vec (0,1,0), 0.1,0.1,0.1);

				for (int s=0; s<=num; s++)
				{
				
					float phi = float(s) / float(1+num) * PI * 2.0f;
					phi += PI * rT;
					if (r&1) phi += PI;
					if (r&2) phi += PI*0.5;

					vec d;
					d[0] = -sin(theta) * cos(phi);
					d[2] = -sin(theta) * sin(phi);
					d[1] = cos(theta);
						//RenderPoint (3, vec(d[0], 0, d[2]), 1,1,1);
						//RenderPoint (3, d, 1,1,1);
					dir.push_back (d);
				}
			}
		}
	};

I used this code to preprocess meshes, e.g. precompute AO.

I think' its pretty much what you want, but it supports only fixed counts of rays, see comment on top.

 

Couldn't you just make a ray / cone intersection and use the intersection segment to calculate volume instead generating multiple rays to approximate the cone?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now