Sign in to follow this  
Dragon_Strike

problems with conestep mapping

Recommended Posts

well ive been trying to implementent something like conestepmapping... dunno if its the same thing but as far as ive read its pretty similar... it works great on non steep viewing angles.. but with steep viewing angles it gets all messed up... i also have some problem of "holes" in certain objects... first i calculate the highest horizon for every point in 4 directions and save it to a texture...

void CSTEPMAP::CalculateHorizonSlope(vec2 dir)
{
	for (int  z = 0; z < size; z++)
	{
		for (int x = 0; x < size; x++)
		{
			step[(x+z*size)*4+0] = max(GetHorizonSlope(vec2(x,z), dir), step[(x+z*size)*4+0]);

		}
	}
}


float CSTEPMAP::GetHorizonSlope(vec2 pos, vec2 dir)
{
	dir = normalize(dir);
	vec2 rpos = pos;

	float maxSlope = 0;
	for (rpos = pos+dir; rpos < size && rpos > 0; rpos+=dir)
	{
		float slope = 0;
		slope = float(GetHeight(rpos)-GetHeight(pos))/(length(pos-rpos)*1.0/size);

		if (slope > maxSlope)
			maxSlope = slope;
				
	}
	return sqrt(maxSlope);	
	
}

	float GetHeight(int x, int z)
		{
			x = clamp(x,1,size-1);
			z = clamp(z,1,size-1);
			return HeightMap.GetAlpha(x,z)/255.0f;
		}

		float GetHeight(vec2 pos)
		{
			int x = clamp(int(pos.x),1,size-1);
			int z = clamp(int(pos.y),1,size-1);
			return HeightMap.GetAlpha(x,z)/255.0f;
		}

		float Interpolate(float a, float b, float x)
		{
			float f  = ( 1.0f - (float)cos ( x * PI ) ) * 0.5f;

			return ( a * ( 1.0f - f ) + b * f );
		}

		float GetInterpolatedHeight(vec2 pos)
		{
			int x = pos.x;
			int z = pos.y;

			int ix1 = (int) x;
			float fx1 = x - ix1;

			int iz1 = (int) z;
			float fz1 = z - iz1;

			float v1 = GetHeight(ix1, iz1);
			float v2 = GetHeight(ix1+1, iz1);
			float v3 = GetHeight(ix1, iz1+1);
			float v4 = GetHeight(ix1+1, iz1+1);

			float v12 = Interpolate(v1,v2,fx1);//(1.0f-fx1)*v1 + fx1*v2;
			float v34 = Interpolate(v2,v3,fx1);//(1.0f-fx1)*v2 + fx1*v3;

			float v1234 = Interpolate(v12,v34,fz1);//(1.0f-fz1)*v12 + fz1*v34;

			return v1234;
		
		}




and then in the fragment shader i skip raytracing the volume given by the horizons... i trace until the "skip step" reaches a certain value...
vec2 parallax(vec3 V, vec2 TexCoord)
{
	float acc = 4.0/256.0; // accuracy
	
	vec2 dt = -V.xy * 0.08 / (V.z);
	vec2 CurTexCoord = TexCoord;
	
	float curheight = 0.0; // heightmap height
	float rheight = 1.0; // rayheight

	float offset;	
        float slope; // horizonslope
        float dy; // ray height above heightmap
	
	for(int i = 0; offset > acc; i++)
	{		
		CurTexCoord = TexCoord+(1.0-rheight)*dt;
		curheight = texture2D(NormalMap, CurTexCoord).a;	
		slope = pow(texture2D(StepMap, CurTexCoord).r,2.0);
		dy = rheight-curheight;		
		offset = (slope*dy)/(slope+V.z/length(V.xy)); // skip distance
		
		rheight -= offset;				
	}	


	return CurTexCoord;	 
	
}

mat3 GetTBN()
{
	vec3 Normal = vec3(0.0, 1.0, 0.0);		
	vec3 Tangent = cross(Normal,vec3(0.0,0.0,1.0));
	vec3 Binormal = cross(Normal,vec3(-1.0,0.0,0.0));
	return mat3((Tangent), (Binormal), (Normal));	
}

void main()
{	
	vec2 TexCoord = gl_TexCoord[0].st;
	
	mat3 TBN = GetTBN();	
	
	vec3 nViewVec = normalize(ViewVec)*TBN;
	
	vec2 NewTexCoord = parallax(nViewVec, TexCoord);			
		
	vec4 Color = texture2D(TextureMap, NewTexCoord).rgba;
	
	gl_FragColor = Color;
}





Share this post


Link to post
Share on other sites
i wouldnt mind

Image Hosted by ImageShack.us

as far as ive got with finding the fault... dy which is the rays height over the heightmap is negative at several places... but this means that the ray has alrdy intersected the heightmap.. which shouldnt be possible with the defined hrozion volumes (cones)

Share this post


Link to post
Share on other sites
The image definitely suggests you are overshooting the cones (as you suspected). The code for the (cone) slope generation looks correct. In the main portion of your shader, however, I got slightly different results. (note, in the preview function at least this forum code seems to be swallowing my plus signs, hence the "{plus}" instead of a "+") Here's your code:


offset = (slope*dy)/(slope {plus} V.z/length(V.xy)); // skip distance


and mine would have been something like:


offset = (slope*dy)/(length(V.xy) - V.z*slope); // skip distance


we do some different things to prepare the initial vector, though, so the transformation may just not be obvious to me. One other note: I don't know the behavior of your shader compiler, but you may want to initialize offset to:


float offset = acc {plus} 1.0;

Share this post


Link to post
Share on other sites
ive rewritten the code using some of the code from ur shaders... and it works fine with the cone-ratiomap that u sent with the demo...

but when i try to use my preprocessing code it doesnt seem to work properly...

what do u do differently in the preprocessing? (GetHorizonSlope)

id like to get this working so i can try using ellips and directed cones... and also double cones

Share this post


Link to post
Share on other sites
I believe the source for the pre-processor is included in the demo, if not I'll post it. From memory, though, there are 2 things:

1) I invert the height values in the texture: i.e. red = 255 - red, or whatever
2) I do a pass at the end of the computation (i.e. once all the cone values have been computed) for the following reason: during the linear interpolation that happens on the GPU during the sampling of the texture, sometimes the sampled value will have a cone that is too wide. So I do 1 pass over all the data and for each texel I find the narrowest cone-ratio of all the original pixels surrounding it, then keep that value.

here is the source:

// All of the 3D rendering API's will do
// interpolation of the cone_ratios. This
// can be *BAD*
cout << " <Safety>";
unsigned char *safeCR = new unsigned char [width * height];
// for each pixel, find the lowest nearby ConeRatio value
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
{
int main_idx = y*ScanWidth + chans*x;
unsigned char LowestCR = Data[main_idx + OFF_CONERATIO];
unsigned char TheHeight = Data[main_idx + OFF_HEIGHT];
for (int dy = -1; dy < 2; ++dy)
for (int dx = -1; dx < 2; ++dx)
{
int idx = xy2index (x+dx, y+dy, width, height, chans);
{
// this is a valid comparison point
if ((Data[idx + OFF_HEIGHT] <= TheHeight) &&
(Data[idx + OFF_CONERATIO] < LowestCR))
{
// this is the lowest CR of interest so far
LowestCR = Data[idx + OFF_CONERATIO];
}
}
}
// OK, I have the replacement CR value, just hold on to it for a while
safeCR[x+y*width] = LowestCR;
}
// now I've done all the computing, update my walues
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
{
Data [y*ScanWidth + chans*x + OFF_CONERATIO] = safeCR[x+y*width];
}
delete [] safeCR;

Share this post


Link to post
Share on other sites
thx for the answers...

i dont quite understand what you mean... and i havent been able to figure out your code yet...

but i calculate the coneratio by finding the horizon in four direction and then save the sqrt(sqrt( of the horizon with the highest slope... what do u do differently?

EDIT:: and im plannig to solve the problem u described by sampling more direction when calcualting the conestepmap... since cthe clac is done one time it might as well be as accurate as possible

EDIT2:: ok now i see what u mean.. u store the heightmap inverted in the the texture... now im getting descenet results... works fine with the stepmap u supplied but it doesnt work well when i use my own preproccessing... it overshoots the cones still...


void CSTEPMAP::CalculateHorizonSlope(vec2 dir)

for (int z = 0; z < size; z++)
{
for (int x = 0; x < size; x++)
{
step[(x+z*size)*4+0] = GetHeight(x,z);
step[(x+z*size)*4+1] = max(GetHorizonSlope(vec2(x,z), dir), step[(x+z*size)*4+1]);
;
}
}
}


float CSTEPMAP::GetHorizonSlope(vec2 pos, vec2 dir)
{
dir = normalize(dir);
vec2 rpos = pos;

float maxSlope = 0;
for (rpos = pos+dir; rpos < size && rpos > 0; rpos+=dir)
{
float slope = 0;
slope = fabs(GetHeight(rpos)-GetHeight(pos))/(length(pos-rpos)*1.0/size);

if (slope > maxSlope)
maxSlope = slope;

}
return (sqrt(maxSlope));

}
float GetHeight(vec2 pos)
{
int x = clamp(int(pos.x),1,size-1);
int z = clamp(int(pos.y),1,size-1);
return HeightMap.GetAlpha(x,z)/255.0f;
}






[Edited by - Dragon_Strike on March 20, 2007 5:09:46 PM]

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

Sign in to follow this