Getting the Best Texturing Outcome in CE

1771
3
03-03-2021 06:19 AM
by Anonymous User
Not applicable
1 3 1,771

I spent a little time yesterday thinking about how to get the best texture outcome for my buildings and I came up with this method.  Some pieces of it are borrowed, which I will point out.    I hope this will help someone new to the programs code, or newer to 3D modeling like myself, or maybe has over-looked this topic.  I hope this isn't replicating a tutorial I missed.  [code snippet at bottom]

First off,  I really liked the texture path creation snippet (which I found at the Complete Streets code) that I broke it off into a new snippet that I use over and over by copy/paste.    This segment uses the file name/path of the colormap to find and replace the associated materials of the same kind.  You might have to change the code to adjust to your personal texture file naming structure, or to add textures not being called.   The great thing about this method is that when you change the file path of the colormap using the @File method, that it changes all the associated material maps (metallic, roughness, normal, etc.) automatically.  This is a real time saver for people who want to use the @File file selector for textures.

Secondly,  I really like the texture results I get from using the setupProjection (world.xyz) over the (scope.xyz) because it lines up a seamless tiled (in my case brick) texture just right across different shapes.  My goal is a texture map result similar to "tri-planar" material in UE4, and I think this achieves this result.    At first, I was getting inconsistent results with the sides of the building who's normals didn't face the in the cardinal direction (world.xy) of the  initial face.  To adjust for this, I think it's worth putting a code to apply the cardinal directions to the normals to simulate the effect of tri-planar projections  (e.g.  comp(f){world.north: <texture for world.xy>, and so on, see code below}. 

Also, I played around with the setupProjection's uwFactor and I think the 0 works better in this method.    

Seamless Tiled Texture.PNG

 

Furthermore,  I like how this method can texture inserted objects without premade UV maps.  This method created the best result on this inserted model, the cable awning below.  It's not perfect ( making a UV map in the program the object was created in would be best), but this is a good and fast shortcut.

Insert Object Texture.PNG

@File
attr brick_tex_file = "/KitBash/assets/Brooklyn/KB3D_BRK_BrickWallStandard_basecolor.png"
@File
attr ledge_tex_file = "/KitBash/assets/Brooklyn/KB3D_BRK_ConcreteBeige_basecolor.png"
@File
attr awning_tex_file = "/KitBash/assets/ArchVogue/KB3D_ARV_SteelRoughDark_basecolor.png"

_Construct_PBR_Path(color_map_path,type) =
	case type == "col":		color_map_path
	case type == "norm":	replace(color_map_path,"_basecolor","_normal")
	case type == "roug":	replace(color_map_path,"_basecolor","_roughness")
	case type == "meta":	replace(color_map_path,"_basecolor","_metallic")
	case type == "bump":	replace(color_map_path,"_basecolor","_height")	
	else:					print("No correct type specified for path.")
	
ApplyPBRTextures(path)-->
	set(material.colormap,_Construct_PBR_Path(path,"col"))projectUV(0)	
	set(material.normalmap,_Construct_PBR_Path(path,"norm"))projectUV(5) 
	set(material.roughnessmap,_Construct_PBR_Path(path,"roug"))projectUV(8) 
	set(material.metallicmap, _Construct_PBR_Path(path,"meta"))	projectUV(9)
	set(material.bumpmap, _Construct_PBR_Path(path,"bump"))	projectUV(1)		

brick_tex-->
	set(material.name,"BrickWall")
	comp(f){world.north: brick_tex_XY
		   |world.south: brick_tex_XY
		   |world.west: brick_tex_ZY
		   |world.east: brick_tex_ZY
		   |world.up: brick_tex_XZ
		   |world.down: brick_tex_XZ}

brick_tex_XY-->  //north and south
	setupProjection(0,world.xy,3,3,0,0,0)
  	setupProjection(5,world.xy,3,3,0,0,0)
	setupProjection(8,world.xy,3,3,0,0,0)
	setupProjection(9,world.xy,3,3,0,0,0)
	setupProjection(1,world.xy,3,3,0,0,0)
	ApplyPBRTextures(brick_tex_file)

brick_tex_ZY-->   //east and west
	setupProjection(0,world.zy,3,3,0,0,0)
  	setupProjection(5,world.zy,3,3,0,0,0)
	setupProjection(8,world.zy,3,3,0,0,0)
	setupProjection(9,world.zy,3,3,0,0,0)
	setupProjection(1,world.zy,3,3,0,0,0)
	ApplyPBRTextures(brick_tex_file)

brick_tex_XZ-->   //normal up and down
	setupProjection(0,scope.xy,3,3,0,0,0)
  	setupProjection(5,scope.xy,3,3,0,0,0)
	setupProjection(8,scope.xy,3,3,0,0,0)
	setupProjection(9,scope.xy,3,3,0,0,0)
	setupProjection(1,scope.xy,3,3,0,0,0)
	ApplyPBRTextures(brick_tex_file)

Also, I think this code could be further parameterized to avoid repetitive code.  

One last note, I am using the height maps in the bump material.maps for now.  I plan to use this in UE4 for a bump-offset material.

If you made this far, thanks for looking!  Comments and questions welcome,  I'd love to have more discussions with enthusiastic CityEngine users and to learn more myself. 

3 Comments