In case you missed it
you might find it interesting
Hi, thanks for having me. My name is Paweł Kostecki, and I am a self-taught 3D Artist from Poland with about 6 years of studio experience. In 2013, I landed my first industry job at Teyon, where I worked on Terminator: Resistance, which has been released recently. In 2017, I joined the Techland team to support the development of the upcoming game – Dying Light 2.
Though my major (Automatics & Robotics) was not exactly 3D-related, I managed to compose and defend a thesis that explored possibilities of simulating physics in 3DS Max (which I don’t know why I still use). Since then I have been hooked on 3D for good and with time I chose to dig deeper into creating props for video games. Just after graduating I did an internship connected to 3D and at the University of Macau and upon return I gathered and sent out my portfolio pieces to various studios. The first job hadn’t come easy and at some point, I was thinking of looking for employment somewhere outside the video game industry. Then, in November 2013 the first opportunity presented itself and I took it.
The Idea Behind the Project
I started this project a long time ago. I believe the first file reaches the beginning of 2017. I chose Rolf Bertz’s concept ‘Westland Car’ as a base. Back then I just wanted to do some cool prop in my spare time to learn and enrich my portfolio. I also wanted to train myself more in using ZBrush which I wasn’t fully comfortable using. I aimed more at showpiece rather than a super optimized model for a game. Obviously, the project took me definitely too much time and, in late stages, I had a constant struggle between lowering the quality bar and spending even more time on it. Sometimes, it was mentally exhausting but, in the end, I am happy with the result and even more happy that I wrapped this project up. A long-time span was a result of changing jobs, moving house, and vacations. I also admit I did lack systematic work in some time periods. Moreover, I did some changes to the model during texturing that required rebaking (don’t we all love rebaking?). Texturing was for sure the phase that received most iterations due to a substantial deepening of my knowledge in this area while working at Techland. Pretty much from the beginning, I was going for a somewhat stylized look of the car hence bigger thickness of metal plates or size of deep scratches.
As for references, I did not want to get overwhelmed by them. I wanted to pin down the look of specific parts like wheels or dented body details to enhance a base concept. I highly recommend the neat little app called PureRef. It is free and great for keeping all your images organized in one place.
Modeling a part was pretty straightforward. The first goal was to pin down the basic shape of the 2005 Ford Mustang. It’s nice to have accurate blueprints from all the sides to imitate the dimensions, proportions, and main curves of the desired car. At that stage, I didn’t care much for irregularities in a high poly mesh. Those would be fixed later in ZBrush, also, taking into account the post apo style of a car which has lots of dents and bends. It’s not like I was doing a model for industrial visualizations, so making it perfect would be just a waste of time.
I used standard poly modeling, not curves nor nurbs. To speed up the modeling process, I use typical plugins for max like miauu's Work Plane or UniConnector by Nikolay Litvinov. To make quick high poly objects I use a very simple script I called ‘chamferturbo’. You can drag & drop it to your toolbar, and it will create a button, which applies chamfer and turbosmooth modifications to your mesh and smooth it based on its smoothing groups. I often mix this method with classic support edges to add different chamfer size on particular edges. You can grab the script here:
( modPanel.addModToSelection (Chamfer ()) ui:on $.modifiers[#Chamfer].tension = 0 $.modifiers[#Chamfer].smoothingOption = 2 $.modifiers[#Chamfer].minangle = 0 $.modifiers[#Chamfer].selectionoption = 5 $.modifiers[#Chamfer].segments = 2 $.modifiers[#Chamfer].amount = 2 modPanel.addModToSelection (TurboSmooth ()) ui:on $.modifiers[#TurboSmooth].iterations = 2 modPanel.setCurrentObject $.modifiers[#Chamfer] )
From there, I started cutting the body for individual panels (doors, bumpers, etc.) and adding specific post-apocalyptic looking parts and elements. From day one, I knew there was no point in modeling a tire tread and fence/mesh covering windows in 3ds Max. Substance Designer was my pick for that job due to the speed of implementing changes. It also gave me the opportunity to test quickly different patterns. More about that in the section below.
I knew I would have to connect some bigger parts (like metal beam beneath right door) to the main body in order to create some smooth transitions between them to have a nice space for the welds. When you have two elements with a hard connection, it is pretty impossible to add nice weld between them in the texturing suite. I decided to use DynaMesh in ZBrush rather than connect those elements during modeling in 3ds Max.
I also sculpted bigger scratches and tape wrinkles (using alpha generated from photo) in ZBrush but if I would make it again, I would add them in Substance Painter because it is easier to control and change them if the need arises.
As for car body dents and bends, I haven’t really found any good looking alphas on the Internet, so I sculpted them using standard brushes. The bigger ones would later have their representation in the low poly mesh. It was important for me to make them distinguishable by size and shape.
One additional software I used for modeling was Marvelous Designer. I used it to simulate a piece of cloth on the roof. From there, I exported it with thickness to have a nice rounded edge (after smoothing in ZBrush) for baking. It created a feeling that cloth has more thickness. Tears on edges were added later on opacity channel in Substance Painter.
The Workflow in Substance Painter
There is nothing revolutionary in my workflow. In bigger projects like this one, it is very important to organize your layer stack: color code folders, layers and name them. Having dozens of layers, folders, Anchor Points, I would get lost very quickly without organizing them from the beginning.
At the first stage of texturing, I spent quite a lot of time just picking base colors for particular elements of a car (some, of course, were picked from concept art and tweaked a little). When I was happy with basic colors, I started more detailed (but not final) texturing. It is said that you should start with the biggest element. It is certainly true in most cases but, in this particular project, I started with smaller ones like fuel tanks, wheels or metal plates attached to the main body. When I had them textured in around 70%, I switched to the main body because, at that stage, I had more or less a solid idea of how detailed it should be. I did not want to overload every space with detail.
While texturing the main body pretty early on, I added a big dust gradient from bottom to top (based on position map baked in SP) and dust/dirt accumulation in cavities and where attached elements connect to the main body. It helped me visually establish the look and feel of the car and blend elements and material together. Often when you use some kind of dust or dirt (but not only) layers don’t just blend its mask with Perlin Noise at 50% opacity. What I like to do is to erase some parts of its mask completely with nice contrasting alpha or grunge. It makes it easier for viewers to recognize what material they are looking at because they see a vivid contrast between the two materials.
Speaking of dust and dirt. Those not always have to be dark and desaturated! For instance saturation of brownish dirt near the bottom of a car is higher than the base body paint (see it below). I also tried to keep dirt/dust brightness values similar to other surfaces and materials. Let’s say, you have a quite big cavity in your model. When you place dark dirt there, it will be multiplied by AO map, shading from normal map and sometimes shadow. It will be simply black. Try to avoid this unless you have a good reason to do so.
Another rule I was following during this project was that you should use a wide spectrum of saturation in your diffuse textures when there is no artistic decision to do otherwise. It’s even better when you can read what is going on on the asset (or whole scene) looking just at saturation levels. Big shout-out to Michał Kubas (our lead 3D Artist at Techland) for introducing this approach/technique to me.
Here, you have the visualisation of saturation based on the jest diffuse channel. To achieve this in 2D painting software, just put a fill layer with 100% red on the bottom and on the top your desired shot with a blending set to ‘Saturation’.
To illustrate this approach better, check out fame from the latest Ghost of Tsushima trailer:
In a car like this one, which has many foreign elements and is exposed to hard weather conditions or human actions, there will be strong color variations due to splatters of paint, elements with multilayered paint, paint discoloration from the sun, rust leakage etc. In the majority of elements, I was trying to implement some interesting color variations and not just follow the rule: base paint, dirt, scratches, call it done. Rather than differentiating by brightness value, I was changing saturation or hue. A very good method is to use photos with nice color variations and experiment with blending them with your base texture. It can give you a very cool result you wouldn’t end up with using just generators. Another method I used a lot to generate a good texture base was a Gradient filter. It was, for example, great to apply discoloration to base layers of paint. You can check out here how to use it.
Besides the elementary ones, I densely used the Slope Blur filter and Gradient filter. As I’ll describe later Slope Blur is great for adding ‘real-life touch’ to your masks by skewing and warping its edge. Worked like a charm with rust and dirt masks.
As for generators, I don’t have any favorites. A lot of times I pick and choose some generators on the go depending on the situation and if I like the initial result it gives me, I tweak it. One thing I will add is that adding some brush strokes on the top of a procedurally generated mask (or mixing it with grunge map) goes a long way! It prevents viewers from pinpointing instantly: ‘ Ok, those scratches were made by using a generator X or Y’.
Anchor Points. They are powerful for many reasons, one of which is an ability to break the ‘linearity’ of mask stack. Let’s say you are building up your mask and, at a certain stage, you want to ‘save’ current result to use it later, for example, as a subtraction component. I will show it in a trivial scenario:
You want to make a blurred outline for your current layer and every time you change mask of this layer you want a blurred outline to change accordingly. Use Anchor Point!
- Make an Anchor Point for ‘Base Mask’.
- In ‘Outline’ mask place Fill with Anchor your created.
- Blur it.
- Use Levels to strengthen it.
- Use Fill again, only this time set blending to Subtract.
The beauty of it is that it is a non-destructive workflow. You can make changes to the source mask, and it will be passed through Anchor Point. Later on, I’ll describe another cool use of Anchor Points.
Additionally, to make rust on some elements, I used MatFx Rust Weathering. First note: it works only in the Metalness workflow in Painter. Second note: the color of rust generated by this filter is quite dark. To overcome this problem, I placed Anchor Point in MatFx Rust Weathering effects stack (not mask stack), so later I was able to mask out places where the rust was and place whatever rust texture I saw fit.
For the welds, I used a handy tool called ST welds. Again, this works only with the Metalness workflow. Authors made version 1.1 to make it work also in Specular workflow but I found that it doesn’t and, by the way, it breaks some basic functionality so try to get version 1.0.
A Piece of Criticism About SP
SP is nowadays a go-to software in the case of texturing suites. There is really no competition out there right now. But it is far from ideal. I must pour out my regrets about it. The First thing is performance. I have a relatively good graphics card in the form of GF 1080 with 8 GB of VRAM. In this project, I had 5 texture sets including one with 4K textures and dozens of layers, folders, and Anchor Points. As long as I worked with 2K textures things went pretty smoothly, but working with 4K was a disaster. Simple actions like color change or hiding layers could take like 20 seconds! Not to mention regular crashes. It was very frustrating. Another thing is that SP lacks proper color picker with HEX field, so you can copy/paste color between layers (not in every case you can you use ‘pick color function’). Even Google search has this!
And lastly, I really miss a feature that allows you to copy/paste fills/filters/generators from one layer to another. And no, I am not talking about ‘copy mask’ and ‘paste into mask’ which erase everything you had in a mask you are pasting to.
Working on the Materials in Substance Designer
As I mentioned earlier Substance Designer came in handy with some part of the modeling process. For example, I wanted to avoid modeling a tire tread in 3ds Max because at the time I didn’t know what pattern I wanted to use. SD is very flexible and it gave me the opportunity to experiment. I imported low poly mesh of tire and baked normal map just for tire’s silhouette and then I blended it with a normal map I generated in SD. By the way, the height map from SD was later used in Marmoset Toolbag to feed shader with tessellation.
SD also helped me to create normal maps for hex mesh covering windows and broken glass inside mirrors.
For this kind of stuff, I almost always use fill layer with ‘Projection’ set to ‘Tri-planar’ or ‘Planar’ and ‘UV wrap’ set to ‘None’, and then I place it with 3D gizmo (which for me is the last substantial feature added to SP). Let’s say, you found a cool graffiti/label/sticker texture as png with transparency (alpha). When you hook this texture up in Diffuse channel SP seemingly will mask it out but it only Diffuses channel! When you look at the Roughness channel, it will be a flat rectangle because a fill layer doesn’t have proper masking. There is a cool trick fixing it which I learned during this project. You have to add Anchor Point to layer with your texture, then Add a black mask, add Fill to this mask and choose Anchor Point you created and change ‘Alha behavior’ to ‘ Extract Alpha’. That way the layer has proper masking based on texture alpha channel.
When the desired texture doesn’t have alpha information, this method will also work if the texture has enough contrast. You just have to tweak levels in ‘Fill’ parameters.
This trick is great because when you decide to move graffiti to a different place on the model layer mask will automatically follow (thanks to Anchor Point) diffuse texture. That way you don’t have to struggle with fitting additional texture as ‘alpha’ in layer mask with another 3D gizmo.
Working on Details
I wanted to give this piece a rusty look but not flood it with rust. When you look at some rust references, you would see a wide spectrum of colors it has (this does not apply solely to rust). Often it is yellow, orange or even violet. It is not always ginger and dark. Also, I didn’t want my car to have the same type of rust in every element. I believe I prepared 4 base rust textures and then propagated them. Additionally, I applied different roughness and specular values to particular types of rust. Rust doesn’t always have to have roughness value near 1!
On the main body, I applied two sizes of rust spots. Bigger ones in contextual places like wheel arches or near attached metal plates. Smaller ones ‘inside’ to fill the space and to help blend materials together.
Here is the breakdown of rust material for bigger spots:
Firstly, the most important thing to achieve was natural-looking shapes of rust. I experimented a lot with different filters and generators but in the end, it all came down to painting very roughly shapes in desired places and then applying Slope Blur filter. Slope Blur filter generally is great for ‘breaking’ generic-looking shapes. I use it a lot. On the top of the mask stack, I placed Anchor Point which I intended to use later.
With Slope Blur filter applied, I tweaked the Paint mask a little bit until I was happy with the result. Next, it was time to add some rust textures to fill the layer. At the beginning of the texturing process, I prepared 4 base rust texture sets (diffuse, roughness and normal). I found some rust textures on the Internet and generated the rest of the maps in Materialize – super cool free software to do this kind of stuff. You will have to get used to UI though. You can grab it here.
I also set a very small negative amount of height to a layer to give the car paint some thickness. At that time, rust looked quite flat in terms of color, so I added another two layers with different diffuse. To mask them I used Anchor Point I created earlier and ‘grunge_map_007’ (on Subtrack) which by the way is a nice grunge map as it contains sharp and rounded shapes. It gave me nice color variations inside rust.
The last step was to somehow mark the transition (besides height channel) between rusted and non-rusted car paint. Again, I started with creating a mask for this:
1) Layer with Fill with Anchor Point I created earlier.
2) Then to grow mask, I used a custom filter called Matte Erode/Expand by Bradford Smith. Now in SP, there is Bevel filter but I find this custom filter better. You can also use a Blur filter.
3) Again, I used Fill with Anchor Point but now as Subtract.
4) In the end, I added a Slope Blur filter to make this mask cover both paint and rust.
Then, it was time to add some color to the mask I just created. I used gradient filter for this which feeds from ‘grunge_map_007’.
From the beginning, I was aiming at clean studio renders. I didn’t want to overdo them by adding tons of effects. I was hoping that the asset will defend itself. While texturing, I was previewing it in Marmoset, rotating camera and light (what I think is a favorite activity of 3D artists) and, whenever I came across some cool shot, I saved it for later by creating camera from view (Ctrl+K). By the time I was finished with texturing, I had gathered a bunch of shots which I later used as finals.
My camera FOV was pretty low at 15°. I added slight sharpen, vignette, and tweak the contrast curve, so renders will be more punchy but nothing extreme. I avoided adding grain as on bright backgrounds vignetting bug (due to compression) is practically non-existent.
As far as lighting is concerned, I went for one main directional light and around two (depending on the shot) support spotlights. All the lights were white with no tint. Support lights had small ‘Distance’ and, in most cases, didn’t cast shadows. I set them to sell materials better, but remember a contrast or highlight they generate shouldn’t downplay the main light!
For each camera, I created a separate folder with lights and Sky, so I could control them independently for every shot.
I found ‘Lands End’ Sky to be fitting my assumptions because it gave me a pretty natural outdoor look and didn’t alter colors on my textures.
For final renders, I cranked setting in the Render tab up to maximum. The main star here is Global Illumination. It really helps ‘merge’ asset to the scene, especially in a case like this where you have a relatively big object sitting on the ground. Of course, all those options will probably clog your PC, so when you are setting your cameras and light it is convenient to turn them all off at once by using ‘Speedy viewport mode’ (Ctrl+Shift+J).
Piece of Advice
Don’t push ambient occlusion strength too much. If you are trying to rescue your asset with it or any other effect, something is wrong with your textures or model. Also, don’t try to fix your textures with lights. If you feel that they are too dark, tweak them in texturing software.
In my opinion, if your work has nice material definitions and well-balanced textures, you won’t need a ton of work with renders. I would generally say that brighter images sell better but if you have a clear vision of what you want to achieve with a darker scenario, it is completely fine.