Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Camera distances from a pixel  (Read 787 times)
serial
Customers
Community Member
*****
Posts: 299


« on: March 21, 2008, 08:47:02 PM »

How do I find out how far the camera is from a UV?  So like if the camera is over a certain distance away I can use one technique if it under then I can use another.
Logged
JukkaKevät
Customers
Community Member
*****
Posts: 182


« Reply #1 on: March 23, 2008, 07:27:18 AM »

I did a texture to world space transformation half a year ago.

http://www.truevision3d.com/forums/tv3d_sdk_65/convert_texturespace_to_worldspace_coords-t16089.0.html

Pictures no longer available since I cleansed up my server, but hopefully this helps. You basically give it a triangle's vertices and a needle for UV and you get world coordinates which you can use normally. The technique can become quite unhandy for tiled textures so you might want to add couple of functionalities by yourself.
Logged
Zaknafein
Customers
Community Member
*****
Posts: 2669


WWW
« Reply #2 on: March 23, 2008, 03:10:43 PM »

(Revised, the first version spoke nonsense!)

Hmm... Since he asked in the Shader Development forum I suppose he was looking for an HLSL answer to his problem Tongue

So the most intuitive way of getting the distance from the eye/camera/view to a vertex in the vertex shader is :

Code:
float4x4 worldViewProjectionMatrix : WORLDVIEWPROJECTION;
float4x4 worldMatrix : WORLD;
float3 viewPosition : VIEWPOSITION;

float4 VS(float4 inPosition : POSITION) : POSITION {
float4 outPosition = mul(IN.position, worldViewProjectionMatrix);
float3 worldPosition = mul(IN.position, worldMatrix).xyz;

float distanceInWorldUnits = length(viewPosition - worldPosition);

return outPosition;
}

But there's a bit of redundancy here, two matrix multiplications where there could be one... And it limits you to world unit distances, which is annoying if you need to write it to a texture or compute anything using it. A normalized, 0-1 version is usually preferred.
The outPosition variable contains all the information you need for depth :

Code:
float4x4 worldViewProjectionMatrix : WORLDVIEWPROJECTION;

float4 VS(float4 inPosition : POSITION) : POSITION {
float4 outPosition = mul(IN.position, worldViewProjectionMatrix);

float distanceInWorldUnits = outPosition.w;
float distanceOnOne = 1 - outPosition.z;

return outPosition;
}

Also, to get it interpolated per-pixel, just map the result to an output TEXCOORD vertex shader semantic and use it from the pixel shader.

(for more info on why and where this comes from, check my post below)
« Last Edit: March 23, 2008, 10:44:05 PM by Zaknafein » Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
Raine
Customers
Community Member
*****
Posts: 1189


« Reply #3 on: March 23, 2008, 08:50:17 PM »

What the hell is the .w subscript anyway? Tongue
Logged

Zaknafein
Customers
Community Member
*****
Posts: 2669


WWW
« Reply #4 on: March 23, 2008, 09:12:11 PM »

(I've re-written this post like 3 times, sorry for the update confusion... Now it should make sense.)

Every DirectX coordinate is a homogeneous coordinate to allow stuff like translation and perspective transforms, and allow transformations matrices that "stack" by multiplying them even with translation & perspective inside them.

Before the perspective transform, the "w" component is obligatorily 1. So for example, this allows the 3 first components of the 4th row of the 4x4 world matrix to represent translation in 3D space. This probably sounds confusing, but the "Translation" part of this page explains it better.

Following the perspective transform (or after multiplying by the Projection matrix), the Z component holds the INVERSE distance to the camera, between 0 and 1. An object at near-plane distance has a Z of 1, and at far-plane distance has a Z of 0.
The W component then has the original Z distance, before perspective transformation, so the actual distance to the eye in world units.
In short, Z = 1 - (W - NearPlane) / FarPlane

After leaving the vertex shader, D3D does another transformation before writing to the depth buffer, which does not really matter to you unless you want to change the distribution of depth values to a W-Buffer manually. Kind of off-topic...

My sources...
http://www.mvps.org/directx/articles/linear_z/linearz.htm
http://en.wikipedia.org/wiki/Homogeneous_coordinates

Proof : I made a little test app with 10 planes that go from z=1 to z=11, where the near plane is 1 and far plane 11. That causes the first and tenth planes to be clipped.
Then I made a simple shader that takes the depth of every vertex and send it to the pixel shader, which then writes it into the blue channel. Either with 1-Z, or (W-Near)/Far, I get linear distribution of blue color values from 10% to 90% by steps of 10%.

« Last Edit: March 23, 2008, 10:39:36 PM by Zaknafein » Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
Raine
Customers
Community Member
*****
Posts: 1189


« Reply #5 on: March 23, 2008, 09:15:56 PM »

Thanks, Zak Smiley
Logged

newborn
Customers
Community Member
*****
Posts: 2437


WWW
« Reply #6 on: March 23, 2008, 09:29:07 PM »

Ladies and gents, the matrix-shader master is back!

Glad to have you around Zaknafein! Smiley
Logged

Zaknafein
Customers
Community Member
*****
Posts: 2669


WWW
« Reply #7 on: March 23, 2008, 09:43:44 PM »

Ahah, okay. Shocked
But it appears the shader master has been speaking out of his ass. I read a proper article written by a DirectX MVP that made me see I've made a couple of mistakes in my interpretation.

Update : Both posts are now corrected, tested and true!
« Last Edit: March 23, 2008, 10:44:41 PM by Zaknafein » Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks