Assignment Goals

The primary goals of this assignment are:

  1. Learn to use the shader and C++ scripting built into UE4.
  2. Create 3D materials
  3. Start getting experience hunting down information in a large codebase.

Details

2D materials for assignment 2

Shader code

  1. Create a new level, Maps/assn2
  2. Make a new material and reimplement your first, computed, material from assignment 1 in shader code as a single "Custom" node taking TexCoord[0] as input
    • You have to give the input pin a name to be able to access it in your shader code.
    • The internal editor for custom nodes sucks. It is easiest to edit somewhere else then paste it into the "Code" box.
    • You are writing an HLSL function body. It can be multiple lines as long as it ends with a return statement.
      • HLSL is a C-like language with operators, data types, and functions for graphics. Microsofts reference pages can be a useful resource for HLSL
    • You can see the HLSL code generated by any material graph from the "HLSL Code" window or by setting r.DumpShaderDebugInfo to 1 before compling the shader.
      • But your code should look like a human wrote it, since the point is to get you ready to write more complicated shader code. You will not get credit if you just cut-and-paste the machine generated code.
      • If you add a wierd and unique constant, it'll make it easier to search for the generated code.
      • The HLSL Code window gives a version of MaterialTemplate.ush with the template parts filled in, but still has some #includes to other files and some that are actually auto-generated on the fly during final compilation.
      • r.DumpShaderDubugInfo puts the actual final shaders into Saved/ShaderDebugInfo. This includes many variants that are all compiled from the single material.
    • Use base the noise functions from the engine, found in Shaders/Private/Random.ush.
      • These are called in the auto-generated code using functions in Common.ush. Both Common.ush and Random.ush are included in every material and available for use.
    • Stick this material on a labeled plane somewhere in your scene next to another labeled plane using the original material-node based material (to show they match).

Baking from C++

  1. C++ code has to be attached to an actor. Create a dummy actor and add a C++ actor component to it.
  2. This will give you two C++ files with some boilerplate code filled in. The actual baking code will go in the TickComponent function on the first tick.
    • We use TickComponent rather than BeginPlay because, though graphics is initialized in the editor when BeginPlay runs, it is not yet initialized in a standalone game until later.
    • You can hit the UE4 "Compile" button to compile and hot-load any changes within the UE4 editor.
    • Debugging actor code
      • To enable debugging of your actor code, just run your project from Visual Studio if you are using Windows or Xcode if you are using Mac
      • Even without the debugger, you can print from your actor. Either send it to the log window with UE_LOG, or to the screen with GEngine->AddOnScreenDebugMessage
    • In general, your job will be to find C++ functions, add their #includes to the .cpp, and figure out how to get the inputs you need to feed them.
    • This page gives examples of adding both internal and editor-visible state to a C++ component.
      • You'll want the texture and material to be editor-visible so you can set and/or change them without recompiling
    • This one has loads a texture from CPU-side data, so shows how to get at some of the other data you might need.
    • This tutorial is way overkill, but gives samples of much more complex C++ behavior.
    • Finally, it should be super-helpful to know that Blueprint nodes are C++ functions!
      • You can make new ones by adding the right macros in front of any C++ function in the engine. The Blueprint node name is constructed by adding spaces to the function name (so "MyFunction" in C++ becomes a "My Function" blueprint node).
      • You can call any of these from regular C++ code.
      • There are also mechansims to call blueprint networks from C++ code (look for function and function_implementation in some of those samples)
    • Search the engine source to find the C++ name and parameters for blueprint nodes.
      • Even the binary build of UE4 includes the engine and editor source. It's mostly missing build files, external programs, and third party software
      • Even so, it's 18K files and almost 2M lines of C++ code and 72K lines of shader code. Search is your friend!

3D Material

  1. Make a new noise material, but taking the 3D LocalPosition instead of TexCoord.
    • The UE4 noise functions are all already 3D, so this should "just work"
  2. Put it on a sphere in your scene.
    • The default sphere is 100x100x100, while TexCoord ranges 0-1, so you may need to scale down the LocalPosition down by about 1/100 for a similar look.

691 students

64x64x64 tiling
32x32x32 tiling

Tiled Texture

  1. Bake the 3D material into slices packed into a 2D texture, assuming the tile sizes are a power of 2. The texture should either be square (for even powers of 2) or twice as wide as it is tall (for odd powers of 2).
    • You can do the unfolding of texture coordinates into the 3D coordinate in your baking material, to fill in a single pass using the same bake actor as for 2D
    • To save memory and bandwidth, the texture render target should be set to R8 format.
    • The HLSL function Texture.GetDimensions(Width, Height) will return the size of Texture in the Width and Height variables. Use this to adapt your tiling for the size of the render target provided.
  2. Create a material to use this tiled texture, turning the 3D position into 2D texture coordinates for the lookup
    computed and texture-based 3D noise
  3. The texturing hardware will automatically blend texels within an x/y tile, but will not blend between z slices. Modify your material to lookup in both slices and use lerp to blend between them.
    noise with z-stepping to noise without z stepping
  4. The filtering between texels can still break on tile borders, where it blends between two tiles. Fix this by shrinking the tiles (and z-range) slightly, so rather than cover a range of 0 to 1, each tile covers -0.5/tilesize to 1+0.5/tilesize. If you do this when generating the tiles and using them, you should now get a seamless texture
    noise with tile seam to noise without tile seam

Submission

Add an "assn2.txt" to describe your test computer (at least OS and CPU) and engine version (e.g. 4.17.0, 4.17.1, etc.). Document where/how you found any C++ functions you used. Report the timings for both unbaked and baked 2D materials. For 691, also report timings for your unbaked and baked 3D materials.

For full credit, you must commit multiple times during development. We'll be looking for your development process, so make sure the commit messages are somewhat meaningful. Also, by the due date, you'll also need to do at least one push ("git push") of your changes to your repository on github so we can see your work.