Passing custom information to material from procedural mesh

I’m working on a terrain-type component and I’m having trouble working out some of the details for applying materials to it. I’m able to generate arbitrary shapes based on the code from the Procedural Mesh Generation wiki tutorial and have now managed to apply single materials to the rendered mesh in UnrealEd.

What I’m trying to work towards is a terrain where there are, for example, 3 possible materials (rock, grass and sand for example). Each vertex in the procedural terrain can provide a set of three weights for how much of each material should be present. These weights should then be smoothly interpolated across the triangle so the fragment shader can mix the components together to create a smooth transition between texture types.

In order to do the blending I will use something like the layered materials or the landscape materials. However, in those examples the blending is done on a per-pixel level in the texture UV space and use either alpha masks or the RGBA components of a mask texture. I want the material information to be passed from the procedural mesh to the material, possibly via a custom component in the buffer (like an OpenGL ‘in’ parameter).

Does UE4 support this sort of information passing (via a custom FLocalVertexFactory/FVertexBuffer/FDynamicMeshVertex combination maybe?) for each vertex or am I on the wrong track for this first step?

Thanks for any help you can provide.

Hey milliams,

This is pretty much where vertex colors should come into play - my reply to you about copying vertex color info in the main Procedural Mesh thread was a result of work along very similar lines to what you’re describing.

Apologies if you already know the following, but I wanted to clear up what appeared to be a misunderstanding from that thread: the most important thing to remember is that vertex colors are an intrinsic property of the vertices - they don’t directly affect the rendered color of an object by default. Traditionally they’re used for passing per-vertex lighting information or for driving lifetime-varying variables in particle fragment shader (ie R channel 0->1.0 lerping the color of the fire/smoke particles in a rocket’s trail from (1.0, 0.8, 0.3, 1.0) to (0.1, 0.1, 0.1, 0.0) or something like that).

At any rate, you can setup a simple lerp between textures based on vertex color like so (ignore the stuff outside the red box unless you’re using a texture atlasing system like Minecraft’s):

Which in practice can look something like this (top row intentionally omits blending for comparison):

Just so it’s clear, the above isn’t strictly Minecraft-style cubes but rather 5x5 heightmaps with sides, which in addition to slopes/half-height blocks allows you to blend textures with neighboring tiles, since there’s intermediary vertices between the top-center and the top-edges.

This is a super-naive 10-minute implementation with straight lerps and in practice you wouldn’t really want to do it this way - rather you’d want vertex colors to be weighting content-aware blending masks so that sand fills in the cracks between rocks, grass blades don’t suddenly “fade out” into the dirt texture, etc.

Hopefully this helps get you where you’re going.

–Ryvar

That’s very useful, Ryvar. Thanks.

I understand that the colour attribute of the vertex is nothing more than a vec4 of floats and I was starting to think that this might be the simplest way of passing the information from the mesh to the material. I managed to get something working last night using two of the colour channels to blend between two materials. Scaling this up to use all four channels to get four possible materials (or five if I do “1 minus sum of channels”) would work well in the medium-term.

However, I was hoping for the possibility of a more direct and flexible system. When I implemented the system I have in mind in pure OpenGL, I do a glVertexAttribIPointer() (it labels part of the vertex buffer) and then bind that to one of the input locations in the vertex shader. This means I can pass arbitrary data into the shader. For example I could pass in 8 int values (two uvec4), one for each material weight.

I was hoping that it might be possible to do something similar in UE4 where foe example I could make a custom vertex type and use it instead of FDynamicMeshVertex (I’ve seen custom vertex types exist such as FModelVertex, FLandscapeVertex and about 10 others). I guess I would then need a custom vertex buffer class and vertex factory class in which I could do some custom STRUCTMEMBER_VERTEXSTREAMCOMPONENT type calls and assign it to appropriate members of MyVertexFactory::DataType (however that would be defined) like you do in the procedural generation tutorial. I can kind of work out how all that would work as it is all a sort of direct wrapper over OpenGL/Direct3D (STRUCTMEMBER_VERTEXSTREAMCOMPONENT seems to mirror glVertexAttribIPointer conceptually) as long as I’m not on the wrong track with my idea. However, even if I got that working I don’t know how I would then be able to use that information in a UE4 material. Is it possible to make custom material editor nodes (like the ones specific to the landscape editor)?

Thanks for all your help so far. I appreciate you taking the time.

Was this ever solved? I am also looking for a way to pass in shader information, as i’de like to use the ColorComponent for color tinting and not for material differentiation…

Hey Deus0 - sorry for the delayed response, haven’t been checking the forums lately.

To use ColorComponent for tinting you need two things:

  1. The line of code I gave in the other thread (now in the procedural mesh wiki entry) that copies the Color data for each vertex to the vertex buffer:
  1. The material for your procedural mesh needs to pass that value to Base_Color or Emissive.

I actually use this pretty heavily while debugging mesh generation routines, myself. Here’s a typical screenshot, with the material editor open showing the Vertex Color routed to emissive:

Here’s the code generating vertex colors:

Hope this helps!

Hey!! Thank you very much for your reply. Sorry I ended up solving it also, but your blending description helped me understand my problem was not in code, but in the material.

I was curious, is there any way you can pass in other information, from the processor to the gpu, other then vertex colour? As I’ve been thinking a good solution is to pass in another variable for which texture I want to use, and keep vertex colour for tinting :smiley:

OpenGL had vertex attributes, im looking for something similar:
https://www.opengl.org/wiki/Vertex_Attribute
I will try to post the information if I find the answer for others!

Ryvar, does ProceduralMesh Component already pass vertex color information? Or is it currently still broken and needs a recompile with your code fixes?

FWIW I already tried generating geometry with vertex color data and using it as base color and the data does not get passed correctly. From BluePrints the ProceduralMeshComponent only accepts a Color struct however BPs can only use Linear Color struct arrays as variables and there’s no way to convert from one array type to another, even with iteration.