Download

Converting CG/HLSL to UE4's Material Format

Hi there folks,

Since this is my first post on the forum I feel the obligation to briefly introduce myself.

INTRODUCTION
Let me start by confessing that I am new to game programming all together (if you don’t count some fiddling around with OpenGL about 15 years ago) and that’s why I am here. Being a veteran C# programmer, I initially started with Unity and spent some time with it in the past few months. During that time, I worked on a procedurally generated game which was a great learning exercise. However, in the end, I feel like I can do more with UE4 since it allows me to use C++ end-to-end by avoiding data marshaling and massive garbage collection overhead, while doing explicit vectorization. Given the fact that procedural generation I am doing is CPU bound, the performance gain I am hoping to get from this transition, from MONO (which is what Unity uses underneath) to C++, is substantial. And the first tests are quite encouraging; with explicit vectorization (AVX2) I achieved between 4x to 18x increase in performance in different parts of the game. And keep in mind that I am just learning C++ and SIMD programming whereas I am really, really good at C#. Moreover, these are not micro-benchmark style measurements but they reflect the gains in certain aspects of the actual game. To be more specific, generating noise for a 32x32x32 volume was 18 times faster on C++ after vectorizing the exact same noise function I am using in Unity. I did not modify the logic in the algorithm, it was just vectorized and the output from C++ and C# versions match one-to-one. As you can tell, I am really excited about the possibilities UE4 and C++ provides…

THE QUESTION:
I created a custom shader which works fine in Unity but I am having difficulty with translating it to UE4’s material format. The part that I couldn’t figure out is accessing the non-interpolated UV values within the Material Editor. The sample below shows how I do this in the custom shader I created;



		void vertex(inout appdata_full v, out Input o) 
		{
			...
			o.texcoord1 = v.texcoord1; // Store the non-interpolated UV values.
		}

		void pixel(Input IN, inout SurfaceOutputStandard o)
		{
			// Grab the non-interpolated UV value from IN.texcoord1 and do some stuff with it.
			...
		}


I simply capture the non-interpolated UV values in the vertex shader and pass them to the pixel shader for consumption. However, I couldn’t find out how to access vertex shader data within the Material editor…

Any help would be greatly appreciated.

TL;DR: How do I access non-interpolated UV values in the Material Editor?

Note: Not sure if it makes a difference but the UV values I am trying to access are stored in the second UV channel, UV1, which I am able to pass to the vertex buffer after modifying the UProceduralMeshComponent class.

Not entirely sure what you mean by non-interpolated but to get the UVs you use the TextureCoordinate node.
If you select that node there are a few parameters that you can set such as xy tiles and UV channel.

Material editor basically hide concepts of vertex/pixel shader. But everything in CustomizedUV output is done at vertex shader also world offset is done there. Everything else is done at pixel shader level except constant/uniform math that is done at cpu.
You can get texture coordinates with TextureCoordinate node and there are coordinate index parameter that allow you to choose which you want to use. But I don’t think there are [nointerpolate] tag for interpolants.

Thanks for sharing the CustomizedUV documentation Jenny. It’s very close to what I was trying to achieve but doesn’t quite get me there… I was trying to manipulate texture tiling for each vertex by passing the scale factor in the second UV channel, which requires me to have both the interpolated UV and the non-interpolated scale factor values. And I couldn’t find a way to have both through the CustomizedUVs.

Luckily, after some digging around, that doesn’t seem to be necessary in UE4. Coming from Unity, I assumed that the same principles would apply here but apparently some internal mechanism in UE4 takes care of the required math when you just provide the pre-scaled UVs the regular way (or maybe some internal mechanism in Unity messes up the pre-scaled UVs…).