Lens distortion2

Started by
8 comments, last by prux 14 years, 5 months ago
hey there, this kind of problem was already discussed here: http://www.gamedev.net/community/forums/topic.asp?topic_id=543188 with the last post, but I need something else. I quote the solution:
Instead of solving it mathematically, you could also use a "DU/DV" map:
float4 PixelShaderFunction(float2 texCoord: TEXCOORD0) : COLOR0
{
        // Get offset
        // Use the quad texcoords ( [0,0]..[1,1] )
        // Convert the offset contents red/green from [0..1] to [-1..+1]
        float2 offset 2 * tex2D( dudvMap, quadTexCoord.xy ).rg - 1;

        // Apply distortion strength with a custom parameter
        offset.xy *= distortionScale.xy;

        // Apply offset on the quadTexcoords
        float2 offsetTexCoords = quadTexCoord.xy + offset.xy;

        // Grab result
	return tex2D( ScreenSampler, offsetTexCoords.xy );
}
The DU/DV map uses 2 colors, red and green. Red is the x offset, green the y. Since you might want it bi-directional, you need to rescale it from [0..1] to [-1..+1]. If you do so, also keep that in mind when drawing the DU/DV map. Pixels with ZERO offset have the values {red:128, green:128}. As a side-note, be carefull when grabbing pixels from your screenSampler at the borders. The offset might put the texcoords outside the [0..1] range. This could generate strange effects at the borders of your screen. You could prevent this by simply smoothing the offsets towards zero, either in the texture itself, or shader-wise. Greetings, Rick the only missing thing is, the offset values are byte-byte only. This -128..127 range isnt enough for me, I want more. I know how to build a "bigger" bumpmap but how to modify this example?
Advertisement
Just use a surface format with more precision, like D3DFMT_R16G16F. You wouldn't even need to modify that shader code, although with a floating-point format it's not necessary to rescale to the [0, 1] range.
and if I use D3DFMT_X8R8G8B8 format? Sorry but I trust in these format better than your "exotic" one =)

EDIT: unfortunatly, it doesnt work, in the old solution, when I set "10" to each element of the matrix, it really offsetted the picture by 10 pixel right-down, but now I have to give a very big value to something even happen....
Quote:Original post by prux
the only missing thing is, the offset values are byte-byte only. This -128..127 range isnt enough for me, I want more. I know how to build a "bigger" bumpmap but how to modify this example?


Quote:Original post by prux
and if I use D3DFMT_X8R8G8B8 format? Sorry but I trust in these format better than your "exotic" one =)


Is it the floating point in the texture that you don't like or the not being rgba8? if its floating point you could use D3DFMT_G16R16 since you only need the x/y offset, the texture would be the same size bit give you 16 bit precision for x/y

another option would be to use the mathematical model presented beforehand where you will get the better precision without a texture and if you want to modify the distortion you only have to modify the shader not a texture.
-Matt S.
Quote:Original post by prux
and if I use D3DFMT_X8R8G8B8 format? Sorry but I trust in these format better than your "exotic" one =)

EDIT: unfortunatly, it doesnt work, in the old solution, when I set "10" to each element of the matrix, it really offsetted the picture by 10 pixel right-down, but now I have to give a very big value to something even happen....

What exactly were you expecting? Two-channel 32bpp formats are hardly 'exotic,' and there's no magic ImprovePrecision() function in HLSL-- 8 bits is 8 bits.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
Quote:Original post by prux
and if I use D3DFMT_X8R8G8B8 format? Sorry but I trust in these format better than your "exotic" one =)

EDIT: unfortunatly, it doesnt work, in the old solution, when I set "10" to each element of the matrix, it really offsetted the picture by 10 pixel right-down, but now I have to give a very big value to something even happen....


G16R16F is anything but exotic. 16-bit floating-point was well supported on the earliest D3D9 GPU's.

There's no reason switching the format shouldn't work for you, at least based on the code you've shown. I would suggest doing some debugging in PIX to see what kinds of values you're writing to the texture, and what's happening in your shader.

thx the replies,

I forgot to tell that I need to do it in 1.4, DX8. I found out that the code works under DX9 2.0 PS and not with the DX8 one. The HLSL code:

sampler2D input0 : register(s0);sampler2D input1 : register(s1);float4 main(float2 uv : TEXCOORD0, float2 uv2 : TEXCOORD1) : COLOR{    float4 Color = tex2D(input1, uv2);    uv2.x = uv.x + (Color.r * 256);    uv2.y = uv.y + (Color.g * 256);    Color = tex2D(input0, uv2);    return Color;}


and this is how the compiler compiled:

2.0

//// Generated by Microsoft (R) D3DX9 Shader Compiler 9.08.299.0000////   fxc /nologo /Tps_2_0 /Emain shader.ps////// Parameters:////   sampler2D input0;//   sampler2D input1;////// Registers:////   Name         Reg   Size//   ------------ ----- ----//   input0       s0       1//   input1       s1       1//    ps_2_0    def c0, 256, 0, 0, 0    dcl t0.xy    dcl t1.xy    dcl_2d s0    dcl_2d s1    texld r0, t1, s1    mad r0.x, r0.x, c0.x, t0.x    mad r0.y, r0.y, c0.x, t0.y    texld r0, r0, s0    mov oC0, r0// approximately 5 instruction slots used (2 texture, 3 arithmetic)


1.4

//// Generated by Microsoft (R) D3DX9 Shader Compiler 9.08.299.0000////   fxc /nologo /Tps_1_4 /Emain shader.ps////// Parameters:////   sampler2D input0;//   sampler2D input1;////// Registers:////   Name         Reg   Size//   ------------ ----- ----//   input0       s0       1//   input1       s1       1//    ps_1_4    def c0, 256, 256, 256, 0    texcrd r0.xyz, t0    texld r1, t1    mad r2.x, r1.x, c0.x, r0.x    mad r2.yz, r1.y, c0, r0.y    phase    texld r0, r2// approximately 5 instruction slots used (3 texture, 2 arithmetic)


and it also says: "shader.ps(9): warning X4704: literal values outside range -1 to 1 are clamped on all ps_1_x shading models"

what is the difference here between 1.4 and 2.0? I know 1.4 is outfashioned but I really need it.
The main issue causing that warning in 1.4 for that shader is that pixel shader 1.4 used fixed point integers, where 2.0 uses floating point (minimum of 24 bit precision).

However I'm not sure why you want to multiply your colours by 256 before adjusting the UVs with them - UVs go from 0-1 across the whole texture. I'd suggest multiplying them by something much smaller than 1.0
Sadly, now everything is that simple. Lets see this picture (I modified to G16R16 format):

http://prux.uw.hu/bm.gif

and the source.

sampler2D input0 : register(s0);sampler2D input1 : register(s1);float4 main(float2 uv : TEXCOORD0, float2 uv2 : TEXCOORD1) : COLOR{    float2 Color = tex2D(input1, uv2).rg;    Color.x = 0.5; Color.y = 0.5;    return tex2D(input0, Color);}


the result now is RED.

the Color.x = 0.4; Color.y = 0.8; results BLUE as it's expected.

but Color.x = 0.5; Color.y = 0.5; is somewhat yellow and brown - which is not in the picture. Is it somehow resized the base image?
okay it solved, maybe some of you interested in that.
Texture format is D3DFMT_R16G16 it works under PS 1.4 too.
The matrix coordinates need to be recalculated

texX = 65536 * (XVALUE * (1 / PICTUREWIDTH))
texY = 65536 * (YVALUE * (1 / PICTUREHEIGHT))

sorry for a lot of stupid post I didnt see the things clearly.

This topic is closed to new replies.

Advertisement