Skip to main content
gamedev.net
🔒 Locked

Shader precision problems...

Started by Bucky32 4 replies 850+ views
Original Post
Bucky32
Bucky32
We're currently doing raycasting on the gpu and, more precisely, volume rendering. Our big problem right now is the precision, the volume is jumpy when rendering upclose (more specifically inside it) and has strange ring-like artefacts (apart from the normal and expected sampling artefacts when volume rendering). We're rendering several passes storing intermediate results into RGBA16F textures, FLOAT_RGB32_NV don't really work since it does not support GL_LINEAR. Our shaders are all using floats and where possible, the data sent from vs to fs is stored in texCoords (we've seen somewhere that this gives you higher precision than sending stuff as color). The data is stored in 3D textures and it's quite big so we've settled for 16F, but that should be enough and not produce the artefacts that we're getting. We're using both a gf6800 and a quadro fx4500. So.. we are wondering what general things can be done to improve overall precision in gpgpu? Thanks in advance! [Edited by - Bucky32 on April 6, 2006 10:26:54 PM]
taby
taby
The mach banding is unavoidable, even when using a floating point render buffer. I think some type of dithering algorithm may work, but I haven't had time to implement one.

This screen shows the banding problem from my volumetric renderer. It sounds like we are using the exact same techniques:
http://cwiki.org/uploads/e/e0/Untitled-1.jpg
taby
taby
If you would like to have me test it and see what I can conclude, I'd be more than happy. I've definitely gone through my share of dead-ends on this project.

Alternatively, you can check out my shader source at:
http://cwiki.org/index.php/Image:Gpuvol4.rar

Also, the most current C++/shader source is at:
http://cwiki.org/index.php/Image:Gpuvol-04-06-06.zip

I'm currently developing an IR-ROYGBIV-UV colour system for use with the Fresnel equations and Cauchy's equation. Once I've got that finished, I'll flip you a copy of the source if you like.

BTW, this is all OpenGL 2.0 code.
Bucky32
Bucky32
Thats a really nice project you got going there taby!

We had a look at you code. It seems like we arent calculating the ray directions in the same way. But we saw that you have a look_at vector in the shader thats updated via the color attribute. How do you actually calculate this vector?

This is the shader code we use for our two pass direction calculations. First pass we render a cube with front faces and the second pass using back faces.

First pass:
struct vertex {	half4 position : POSITION;};struct fragment{	half4 position	: POSITION;	half4 color	: COLOR;	half4 texCoords	: TEXCOORD0;};fragment main(vertex IN,			  uniform half2   screenResolution,			  uniform half4x4 modelViewProj){	fragment OUT;	//Transform position coordinates	OUT.position = mul(modelViewProj, IN.position);	//Create textureCoords, (remapping of position)	OUT.texCoords = (OUT.position.xyzw + OUT.position.wwww) * 0.5;	//Rescale texture coords after window size	OUT.texCoords.xy *= screenResolution;	//Per-vertex color	OUT.color = IN.position;	return OUT;}


Second pass (same vertexshader as above also active):
struct fragment{	half4 color		: COLOR;	half4 texCoords	: TEXCOORD0;};struct pixel{	half4 color	: COLOR;};pixel main(fragment IN,		   uniform samplerRECT entryTexture){	pixel OUT;	//Difference between back and front of cube = somewhat a ray-direction	half4 ray  = IN.color - texRECTproj(entryTexture, IN.texCoords);	OUT.color.xyz = normalize(ray.xyz);	//W-component is the length of the ray through the cube	OUT.color.w	= length(ray);	return OUT;}


As our volume renderer is a part of a larger application we cant upload it here. Here are instead some screenshots showing some of the artefacts problems.

Outside
Inside volume
Another volume
taby
taby
The method that I used is fairly common, and is modeled after classic image plane construction.

The uv_rig.cpp camera is essentially an orbit camera which is always looking at 0, 0, 0. To calculate the image plane corners, I do the standard tan() ratio with the assumption that the length from the eye to the image plane is 1.0.

I then rotate and translate the camera's 4 look at vectors to achieve the final camera position. Since I'm calculating the 4 look at vectors before they are rotated, the math stays extremely simple.

Once I have the rotated/translated 4 corner vectors, I draw a fullscreen quad, using the respective corner xyz direction as the rgb colour value. Since the image plane is planar (duh), the linear colour interpolation that occurs then generates the appropriate ray direction for each fragment.

I hope that makes sense?

Those screenshots are amazing!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.