- Home /
Vertex Position to Screen Space and Back Again.
Hi Shader Pros,
I wrote a complex Fragment shader recently that modified the vertex positions relative to screen space. I'm trying to see if I can do the same thing in a Surface Shader. I understand the different spaces and how to use the built-in matrices to move up the chain e.g. M*V*P. What I struggle with is moving in the other direction.
here's the example scenario:
Let's say I want to move every vertex 5 screen-space pixels to the right. In a Fragment shader since my end goal is to convert the vertex position from object space to clip space (1 to -1 on the screen), i simple get the vertex screen position bump it to the right and I'm on my way:
float offset = 5;
float4 scrnSpacePosit = mul( UNITY_MATRIX_MVP, currVertex );
scrnSpacePosit.y = scrnSpacePosit.y*_ProjectionParams.x;
scrnSpacePosit.xy = float2(scrnSpacePosit.xy/scrnSpacePosit.w);
float4 clipSpaceOffset = float4(offset/_ScreenParams.xy, 0, 0);
float4 vectorRight = float4(1,0,0,0);
o.pos = scrnSpacePosit + (vectorRight * clipSpaceOffset);
However, for a Surface Shader it appears that vertex modification is done in Object Space. So my question is: How can I reverse the ScreenSpace Position back into Object Space. Or alternatively, I need to pass my (vectorRight * clipSpaceOffset) back into objectSpace.
Any Help is much appreciated.
-Mike
Answer by mtalbott · Jun 18, 2014 at 02:45 PM
This might not be the best answer but here's my strategy for now... I figured that If I could get a value for the "MetersPerPixel" at the current Vertex then I could use that to offset the vertex by a given number of pixels.
here's my code for finding the metersPerPixel. Please correct my method if there is a more efficient way to do this.
float4x4 projectionMatrix = UNITY_MATRIX_P;
float d = projectionMatrix[1][1];
float distanceFromCameraToVertex = mul( UNITY_MATRIX_MV, v.vertex ).z;
//The check here is for wether the camera is orthographic or perspective
float frustumHeight = projectionMatrix[3][3] == 1 ? 2/d : 2.0*-distanceFromCameraToVertex*(1/d);
float metersPerPixel = frustumHeight/_ScreenParams.y;
Hi man!!! can you share your fragment shader that modify the vertex pos relative to screen space? it will be a great help to understand how this work!!
$$anonymous$$any thanks this is exactly what I needed. I'm using it to render star constellations in 3D.