**0**

# Beginner Question: 3D to 2D projection of a point in pixel shader

###
#1
Members - Reputation: **497**

Posted 13 July 2012 - 06:05 AM

I've got a very basic question (I'm really bad in math, so please no introductions into vector geometry):

In my pixel shader I want to draw a point whose 3D world-space coordinates I have onto the screen. How do I calculate its correct 2D screen-space coordinates, given the camera/view direction and the field of view angle (83 degrees) of the screen?

Thanks in advance!

###
#3
Members - Reputation: **497**

Posted 13 July 2012 - 06:13 AM

You need to setup the projection matrix, that is all. Both, OpenGL(glut) and DirectX , provide according utility methods to calculate the projection matrix for you.

Thanks. I'm using DirectX, so what utility methods would I need here and what parameters to feed them?

EDIT:

I'm in a pixel shader, so I can only use HLSL code, no D3d... functions!

**Edited by Meltac, 13 July 2012 - 06:15 AM.**

###
#5
Members - Reputation: **497**

Posted 13 July 2012 - 06:36 AM

uniform half3x4 m_W; uniform half3x4 m_V; uniform half4x4 m_P; uniform half3x4 m_WV; uniform half4x4 m_VP; uniform half4x4 m_WVP;

But which one do I have to use here, and how to apply it?

###
#6
Members - Reputation: **126**

Posted 13 July 2012 - 12:20 PM

float4 someVertexShaderFunc(float3 worldPos) : SV_POSITION

{

float4 outPos = mul(float4(worldPos, 1), m_WVP);

...

return outPos;

}###
#7
Members - Reputation: **497**

Posted 14 July 2012 - 12:23 PM

If I understand you correctly, you are in a vertex shader that likely has a world space position as input and you are trying to output the appropriate position. To do this you will need to do something like the following:

float4 someVertexShaderFunc(float3 worldPos) : SV_POSITION

{float4 outPos = mul(float4(worldPos, 1), m_WVP);

...

return outPos;

}

No, as mentioned in my first post I'm in a pixel shader, so how would I do it then?

###
#8
Crossbones+ - Reputation: **12267**

Posted 14 July 2012 - 02:03 PM

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.

###
#9
Members - Reputation: **497**

Posted 17 July 2012 - 01:28 AM

You can't do it in a pixel shader - the projection has already been done a coupla stages in the pipeline before that and can't be modifed. You need to use a vertex shader instead.

Sorry but I disagree. It might be true that I'm

**not supposed**to do this in a pixel shader, as it's normally part of the vertex shader's work. But that doesn't necessarily mean that it's

**not possible**to do in a pixel shader - only the required approach would be different.

I can do all math I want in my pixel shader, so what I just need here is the

**correct geometric transformation formula**. That's a purely mathematical issue, not one of any GPU pipeline thingy.

So are there any other ideas here? One alternate option that came into my mind was if I have the actual

**angle between the view direction and the location vector of the spot**in question (which can simply be calculated with the dot product as I've learned), then it might be possible to calculate the

**horizontal distance from that spot to the screen center**when its projected to screen space by some formula. However that formula is not linear, it's likely to involve some circle calculation or something, so I've not been able to figure it out so far.

Any help here?

EDIT:

I guess I'll need some like kind of Azimuthal Projection: See here: http://www-history.m...s/Hoyer/S3.html

For a start it would already be great to know which kind of projection needs to be done here:

- Gnomonic Projection, or
- Stereographic Projection, or
- Orthographic Projection?

EDIT 2:

Apparently what I need is perspective projection, so probably none of the above. But still this is pure math, isn't it? So there must be some formula!

**Edited by Meltac, 17 July 2012 - 06:38 AM.**

###
#10
Members - Reputation: **126**

Posted 17 July 2012 - 08:28 AM

###
#11
Members - Reputation: **497**

Posted 17 July 2012 - 09:22 AM

You can certainly do whatever math you want in a pixel shader, but you can't change what pixel is being defined at that point in the pipeline. The math I posted for the vertex shader would work in a pixel shader if you have the right data, but the pixel being processed has already been defined.

That wouldn't be the issue. I don't need to

*change*any pixel's position either in world nor in screen space. I just need want to do the following:

- Take the world space sun position and mirror that spot on the axis of the camera to get a virtual world point opposite to the sun
- Calculate the screen space coordinate of that point with perspective projection
- Check whether the currently processed pixel is within some screen-space distance (in 2D) range to that projected spot.
- If so, output some color blended into the original pixel color.

When done this would result in a rainbow being drawn as some sort of post process effect from within my pixel shader.

So, is this possible with that code snippet above, and if so, why does the mul(float4(worldPos, 1), m_WVP) result in an incorrect screen position?

EDIT:

I have tested several different projection approaches and matrices. The overall result is always the same: When I turned the camera to the left or right, the calculated screen position is not accurate.

More precisely, I "moves" over the screen while turning in the correct manner as long as near the screen center. Then, when about 1/4 of the screen away from center, it starts moving "faster", meaning the calculated position is further away from the center than it should be. Then, when coming to some 3/4 of the screen (i.e. near the left or right border), the calculated point moves too slow, i.e. is not enough right/left positioned.

This happens not abruptly but fluently, like some roller coaster movement, first the calculated position wanders too much left/right, then too few left/right. Seems to depend on the circular movement of turning, but I couldn't figure out how to express this in a formula or what adjustments must take place to correct this.

**Edited by Meltac, 17 July 2012 - 02:36 PM.**

###
#12
Members - Reputation: **497**

Posted 18 July 2012 - 02:28 AM

I've tried building my own projection matrix both with the above approach and with this one:

http://www.geeks3d.c...trix-in-opengl/

Both didn't help. Strange thing is, in both cases

**only changing the value of FOV changes the result, while near and far plane values seem to be ignored at all.**

Why this? Is this kind of matrix / projection the thing I need here at all? Looks to me very much as if I'm missing something incredibly basic, but somehow I couldn't figure out what's wrong here.

EDIT: typos.

**Edited by Meltac, 18 July 2012 - 02:30 AM.**