Sunday, August 11, 2013

Blend shaders within the UDK

Quick post here, just wanted to talk about some shader work I've been doing within the UDK.  Recently I finished up a multimaterial blend shader that support 3 full materials, each with Normal, Spec, Diffuse. The 3 materials are painted with the R and G channels of vert colors for meshes, and blend based off of height maps.



While I was doing this shader (for a friend) I wanted to push the tech even farther. I optimized texture usage by storing Gloss and Height within the Diffuse and Spec, and added support for ambient spec and diffuse through the emissive channel. Recently I figured out how to blur cube maps within the UDK based on Gloss, and I used the surface gloss values to define the sharpness of the ambient spec. I also used the lowest level of the mip chain of the environment cube map for the ambient spec.  All of this is entirely artist controlled.

Another feature I chose to include was a puddle that blended off of the Blue vert color. All the vert blending was set up on a tier of priority, with puddles at the top, allowing artists to paint whatever material they want, then have puddles on top.  The puddles darken the diffuse, have optional ripples, and have their own spec and gloss values. The puddles also dampen the normals of the underlying material, but even that can be controlled allowing artists to create the illusion of both wet, or full puddles.

For a last trick I used the same blurring technique for the cube maps to blur any of the hightmaps from the other materials and the puddles.  This was a super effective technique, since some height maps can come across super harsh, and blurring them adds realization.  It also allows for texture re-use to save on memory.

The biggest problem I ran into executing this last trick was the same problem I ran into blurring the cubemaps: To go down a mip chain on a texture in UDK, you have to use a custom HLSL node and the tex2dBias intrinsic function (or texCubeBias for the environment map).  The catch is the input for those commands are a texture sample, which is not accessible by placing a texture node in the UDK. However, if you connect a texture node up to a chain (and have it impact nothing, ie multiplying it by 0 then adding it back into the chain) you can pull up the source code, and track down the procedural tex2d Sample that the UDK generates, then use that for the actual tex2dbias command. It is a bit of a hack, but it works very well.



For performance, the final texture count was relatively low. The packing the gloss and height, meant that for 3 materials, only 3 textures were needed for each, bringing the total to 9, plus 1 texture twice for the ripples, and 1 for the environment map. The instruction count came in at 160, which is a bit on the high side, but can be lowered by turning off the ripples. I also made a lower instruction count version that only supports the puddle painting, which came in at 100. Not a bad price for something that supports ambient lighting but still works well with UDK's lightmass.

Overall it was a great experiment and will be useful in the weeks to come :)

No comments:

Post a Comment