x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Get world position in Vertex shader (HLSL)

I'm using Temaran's UE4 Shader Plugin demo to write a custom Shader in HLSL purely from within C++ / engine code. (but I guess the question should also apply to the custom shader node)

When I try to multiply my vertex position with Primitive.LocalToWorld the result is always a zero vector.

Am I doing it wrong? How do you go from one space to another in the vertex and/or pixel shader in HLSL in UE4?

OutWorldPos= mul(float4(InPosition.xyz,1), Primitive.LocalToWorld);

I read this into the pixel shader and set it as the output color, and the result is pure 0 (black). If I set OutWorldPos = float4(0,0.5,0,1); that works and the pixel shader gets green.


Note: I am using the shader by rendering a quad: DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, Vertices, sizeof(Vertices[0]));

So I guess I have to manually create a world matrix in c++ and a float4x4 attribute on my shader and set it every frame?

I'm amazed how far Unreal has managed to get with such a cumbersome and undocumented graphics programming system.

Product Version: UE 4.13
Tags:
more ▼

asked Nov 08 '16 at 11:12 PM in C++ Programming

avatar image

Tudor
53 4 10 13

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

I figured something out. I'm not accepting my answer because I haven't figured out how/when any of the built in matrices work.

As everyone probably knows, UE4 is really hard to customize. UE4 Graphics programming using the engine code, is not only harder, it's also undocumented.

I tried all matrices both on the HLSL usf side and on the c++ side to no avail. So I made my own matrix from scratch every frame and uploaded it to the shader as a 4x4 FMatrix to a shader via the UE4 DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER() macro system.

I render the camera to a quad. This means that in my Vertex shader I can treat it as if it is already in View space (instead of object space aka local space) to make it be exactly the size of the camera. So to get a ray in worldspace from that, I have to multiply by the Inverse Transpose View matrix.

Here's how to construct an Inverse Transpose View matrix in UE4 in c++:

First get the Viewport of the client (the game running on your machine):

     APlayerCameraManager* Manager = World->GetFirstPlayerController()->PlayerCameraManager;
     ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController();
 
     FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
         LocalPlayer->ViewportClient->Viewport,
         World->Scene,
         LocalPlayer->ViewportClient->EngineShowFlags)
         .SetRealtimeUpdate(true));
     FVector ViewLocation;
     FRotator ViewRotation;
     const FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport);

 

We need the ViewLocation (the current player's rendering camera's position in world space) and the ViewRotation.Vector() which is the camera's forward vector. You can get these directly from the camera manager without CalcSceneView, but I added the SceneView code for reference because it provides a lot of matrix resources (none of which I could get working).

Now just make a simple reverse View Matrix:

 FMatrix FPixelShaderUsageClass::GetViewMatrix(FVector eye, FVector target, FVector up) 
 {
     FVector forwardX = eye - target; 
 forwardX.Normalize();
 FVector rightY = FVector::CrossProduct(forwardX, up); 
 rightY.Normalize();
 //upZ is already  normalized because it's a cross product of two normalized vectors
 FVector upZ = FVector::CrossProduct(forwardX, rightY);
 
 //The inverse and transpose of the View matrix. 
 return *(new FMatrix(
     *(new FPlane(forwardX.X, rightY.X, upZ.X, eye.X)),
     *(new FPlane(forwardX.Y, rightY.Y, upZ.Y, eye.Y)),
     *(new FPlane(forwardX.Z, rightY.Z, upZ.Z, eye.Z)),
     *(new FPlane(0, 0, 0, 1))
     ));
 }

From this you can get a float4x4 matrix in your hlsl shader which you can mul with your vertex pos to go from "viewspace" to world space.

more ▼

answered Nov 13 '16 at 12:08 AM

avatar image

Tudor
53 4 10 13

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question