Charlie Foreman expanded on the topic of texturing in the game industry, shared the breakdown of his materials and some tips for texture artists working in SD.
Hello readers! My name is Charlie Foreman. I’m an Environment Texture Artist from Highland Park Illinois, a suburb located north of Chicago. I graduated in June 2018 from Savannah College of Art and Design with a BFA in Interactive Design and Game Development. I’ve always had an interest in video games since I was about two or three years old where I sat on the computer drawing squiggles in Kid Pix. Afterward, I moved onto Super Mario Advance 2 and later Super Mario Sunshine, Sly Cooper, the list goes on as I get older.
While I had taken 3D Animation and Graphic Design throughout High school and had an enjoyment for drawing silly comics, I felt becoming a game designer and telling an enriching story was through gameplay was what I wanted to do. I entered SCAD not knowing how to do much-advanced stuff and recall bitterly stuffing my head against a keyboard when I was learning Maya. However, I found I was excelling far more so in my art classes than in my coding and design classes, and I slowly transitioned back into 3D after a hiatus post High School.
It wasn’t until GDC 2018 where I attended a talk by Daniel Thiger (see the video below) where I found my first facet of art that I found I was truly passionate about. I had gotten Substance Designer on a whim because it wasn’t taught at my school at the time and had fooled around with some videos but hadn’t really gotten too deep into it. After that talk, I went home after the conference and made some terrible “Stylized” Substances, and after about 2-3 months of fooling around post-graduation, I started posting my work on Artstation. We all start somewhere!
(Credit to Substance Youtube for posting this).
As for my work experience, my senior year for our capstone we had to create a small indie studio for six months (Jan to June 2018). I was our Product owner and one of our Environment Artists. Our full team was ten people. My responsibilities including texturing, modeling, level design, particles, optimization, and creating agile scrum sheets. I was basically a swiss army knife and the one people reported to record their tasks. Our web domain for the site has since expired but the old project is viewable on The Rookies from last year.
I’ve also done some Material work for a studio called Snack Pack Studios which is run by some friends of mine from SCAD. Currently, they’re involved in the school’s startup program, SCAD+ which funds them as a full-fledged company. They’ll be dropping their first game, Parking Lot Royale on Steam sometime later in Spring 2019.
Outside of these projects, I spent the summers of 2018 and 2017 teaching at iD Tech Camps as an instructor where I taught Maya to kids and teenagers between ages 8-17. I was a camper there myself for 8 years which was some of my first exposure to 3D software and vouch for it as an amazing place to learn if you have kids interested in game design or coding.
Nowadays, when I’m not hunting for a job, I spend most of my free time in Substance Designer. I’ve continuously been teaching myself more and more about the program, and it’s been gratifying to drift away from tutorials to create my own work. Speaking of my work, I’m going to be sharing some tips with you all today and a few breakdowns of techniques I use in my workflow.
The State of Texturing in the Game Industry
I haven’t worked in the game industry as I’m still rather fresh out of school, but I have been doing a lot of research on what techniques are utilized per company. In May 2018 I attended a talk from Turn 10 where they went deep into their Photogrammetry Pipeline. For large scale realistic worlds, the benefits are great, but it is highly expensive monetarily.
Substance Designer has been making its way into more and more studios over the last few years. Josh Lynch has provided some great insights over time about how he’s incorporated it into his own pipeline s well as some great resources for others.
The benefit of the program is the fast iteration. Being able to create a non-destructive workflow where you can make fast iterations of material is amazing. For how I like to work in UE4, having the Substance plugin makes things a breeze. You want programs that help you work smart and make some awesome end products, and I believe Designer lets you do that nearly effortlessly. Bungie, Monolith, Insomniac, Ubisoft, Naughty Dog, and many more have incorporated Substance Designer into their pipelines (Just check out texture artists portfolios from those studios!). The scale of these studios speaks volumes to the program’s usefulness.
At the end of the day, it will always depend on the studio. The game industry adapts fast, and right now I feel Designer is the way it’s heading and should head for the future.
Work smarter, not harder!
When I’ve been working in 3D I’ve always worked with Height/Normal/AO at the same time to start. You want to spend time on the Height Map because it’s going to be where you derive all your information from. It’s a commonly known work tactic but having a bit of AO and Normal information will help you redefine how your shapes are going to look.
This is the setup that I use when I work. An alternative is the Base Material node which is included in Substance, but I drifted away from using it due to personal preference. For my materials, I always start with a flat white and black for color, roughness, and metallic. This is because I have my normal, height, and AO all hooked up to an Invert Grayscale set to false, which essentially acts as my “Master Node” that I eventually delete when my shapes are blocked out. With these three nodes, I’m able to get a good idea of how my shadows and shapes will be declined without any sort of lighting information. Below is an example of my setup with a Normal, and without one.
The shape definition reads a lot less flat and gives me a better idea of form definition. Something I’ve been working on however is relying less on Substance and Marmoset’s tessellation slider to help create accurate height information. When working in a game engine, textures are far more expensive than geometry, so it’s important to make sure the detail can come through the normal map and isn’t reliant on height since you won’t be able to use tessellation to fall back on getting your material’s shapes to come through.
Height is like the brain of your material. You’d work with it just like you would work with a model in 3d. You do a blockout of the macro shapes and then you slowly start to add micro details. I was surprised when I first picked it up just how much my knowledge of the 3D pipeline came into play when using Designer.
In addition, working in Designer also helps with transferring over to Painter. Allegorithmic uses a lot of the same nodes in both programs so there’s a lot of overlap.
Speaking of nodes, this is a library of nodes that I find myself using most often in my graphs. I omitted some for sure like Non-Uniform Blur, Dust, and I’m sure several more that don’t come to mind. Every one of them has its uses. I’d say out of the bunch of default grunge textures that come with the software I find myself drifting to Grunge Map 02 because I like the streaky patterns and when combined with most other grunge maps it can give you a type of subtle vertical directionality. Of course, the beauty of this program is that you can experiment with all the nodes and find the combination that works properly for you.
(Whites are the highest points of your heightmap, while blacks are the lowest!)
Here I quickly threw together an example of how different nodes can be used to achieve similar results but can affect you further down the line. Here I have a shape that I decreased the values of using a levels node. Now in the right image, I used three different nodes to get the values back up to their original state. However, if you’ll notice in the example on the right when I went back to decrease the value, even more, my Histogram Scan and Levels nodes didn’t match the result of my Auto Levels.
But why is this? Well, this is because Substance Designer works in a chain. When you affect one node, you affect the entire chain. This is what I referred to earlier when I mentioned how Designer works as a totally non-destructive workflow. When you work with materials, creating your height map involves constantly tweaking your histograms range. So, at certain points white to black values can be clamped to cause you to get pure black and pure white. Most of the time you’ll never want these pure values as they cause peaking.
(Left/Middle – Levels Nodes/Histogram Scan Before and After adjustments above, Right – Auto Levels)
If you’ll notice the example, the Auto Levels node keeps the values the same in both examples, while my Histogram Scan and Levels nodes darkened with my level’s node. This is because Auto Levels is a node that will always give you the full range of your histogram. Whenever I feel like I’m hitting too close to grey overall with my height map, the Auto Levels node gives me that entire range back, and then I can make changes to some of my values which can affect blending later down the line. It’s a very simple example, but even though I get a similar result with all 3 nodes, If I adjusted this levels node coming off my Polygon and then made an adjustment down the line I didn’t like, I’d have to go back and tweak every node in the chain and that’s a lot of work.
When I set up my materials, it’s important for me to think ahead about how I’m going to be setting up my shapes and how I’ll be blending them together. You’ll be able to create masks from any part of your material for Roughness and Albedo maps but making the wrong adjustment can mean you’re adding an extra node or two. When I first started out I used whatever nodes I wanted to get my result, but recently I’ve been working to make my materials have fewer nodes and thus more effective as a result.
Again, always think of Height among all else. You can think about a general scheme, but if your Height Map is put together sloppily without a wide range of values it will be a bit difficult later down the line. You’re building a brain for your material with it remember?
I can’t stress enough as well, gather reference! Never go without your references. Build a mood board or find one image you really like and break it down to its core.
At the end of the day, if you’re just getting started, experiment! Find combinations that work best for you!
A quick Segway into how I choose what Materials I want to do. Most Material portfolios have moss, rocks, bricks, wood, etc. I have a few of those in mind, but this was the first material where I thought about doing something unique that people haven’t seen before. I was sitting in the library one day having a protein bar when a crumb fell between my laptop keys. Inspiration strikes on a whim, as it does with most artists!
When I first finished this graph, it looked intimidating even to me, but looking at it now after all these months it’s not that complex. A lot of the shapes are made of only a few nodes, and every mask easily blends into the next. There are lots of things I would do differently now in the months since I first made this material since I’ve learned so much, but it gets the job done.
Let’s break down the reference first.
When I found this, a few things stuck out to me. The caps themselves were missing which provided an interesting shape for my eye to rest on. I noticed between the keys that there was some visual disturbance in the form of hair and dust. Since I had dropped that crumb on my own keyboard, I figured I’d add it as an extra component.
So now that I have my components listed, I can break down each one and work on them all individually.
I start with two Shape nodes (Square and Paraboloid) and a Blend. I’ll be using the square down the line for another component, which is where that line is traveling up towards. Blending these together with a multiply and then running it through a bevel. Bevel eliminates any nonwhite values and clamps them while creating a nice edge. This is how I achieve the shape I desire. All the extra grey is erased, and we get this nice edge.
In the reference, I notice the keys have some curving, so I invert a second Paraboloid and layer it on top. Since the black value is being subtracted from the white, it pushes down gently and starts to give the form some more definition. However, the edge is a bit sharp where the circle meets the key, so I blur it and use a Histogram Scan to clean up the harsh edge
Start > Blur > Multiply over clamped Histogram Scan
Lastly, I run a Highpass Grayscale through a Fractal Sum Base to normalize the values to a more middle tone greyscale, and then gently blend it over to get some pitting. The value is only 0.01, just because it needs to be subtle variance in the normal map. If you look back up at the reference, the keys aren’t entirely smooth, and this helps to scatter the light information across the tops.
Next segment is the spots where the keys are missing. I use a single Shape node with a Square and adjust it with Transform 2D to get the base shapes. Then I add the pure whites together to get the cross shapes, but in the reference, they have a bit of slope to them.
If I take one of the default Gradient Linear nodes, I can clamp it with a Levels node and then multiply it over the shape. The levels node gives me a lot of control of singular gradients and it’s a technique I often use to flesh out my shapes whether its hard surface or organics.
Afterward, I simply manipulate my shapes with Transform 2D and add a Histogram Range to help lower the overall value of the buttons. Since the orange segment as shown in the reference where the key clicks on is taller, its value needs to be greater than the rest of the segment, since it’s the tallest portion. For this, I used the Blend node with a combination of Add, Multiply, and Subtract. For hard surface shapes like this, this kind of workflow is very common, as you don’t need to rely on creating organic shapes.
And don’t forget, for this section, all the information aside from the screw hole was derived from a singular Shape node!
Here’s the final segment of the actual keys, in which we take our previous Shape Nodes from before and simply bring them down to manipulate. The reason I want to use the shapes from before is that they already are the correct size, so I hardly need to do much adjustment to them. I run an Edge Detect through to get the little grooves and then subtract the cross from it using multiple Blend and an Invert Grayscale node, which is a cheap alternative to inverting a levels node.
Now that all our keyboard pieces are done, we’re going to put them all together. I use Levels to lower the white values of the key section and then use Max Lighten to blend them together.
Next, I use some Tile Sampler nodes. This is an incredible node with a plethora of options available. You can manipulate the colors, rotation, offset, position, scale, and even the number of times you want your object to tile. I run my uncapped keyboard Keys through one Tile Sampler and my actual keys through another. I then create a third instance of Tile Sampler and set the shape value to Square, and the Color Random to the maximum. I then run it through a Histogram Scan to create a mask and get rid of all the black values. Now whatever value is left will give me a nice random mask.
While Not present in this graph, something I learned just about a week after making this material is this awesome node called Histogram Select which allows you use to clamp random grayscale values to create a variety of different masks. I threw these into my graph real quickly derived from the Tile Sampler above to show some examples.
With this mask in hand, we can invert it to remove keys from the Tile Sampler that contains them while also removing an un-inverted version in the instance that contains or capless spots. By using the same mask and inverting it, we’re guaranteeing that only the sections where we will want the keys not to have caps will overlap with our capless key segments.
Finally, I run our two Tile Samplers through a Height Blend which is a handy node that lays height on top of each other. I like it, particularly because it can create a mask for you rather than having to create the mask yourself, alongside giving you the freedom to adjust each segment’s height rather than just one with a Blend node.
With our keys done, we can move onto the smaller components. Next up is the hair.
Nothing too complicated here. I take a Shape node, Warp and Directional Warp it a few times by a modified Cells 1 node and then run make a second, edited instance of it to add some variety. Then I run both hairs through a Splatter Circular node which helps to keep them clumped together and can be adjusted with a Random Seed for different results. Afterward, I have 3 different clumps of hair that I run through a Tile Sampler. I use our Keys as a mask so that the hair wouldn’t show up where there would be caps. If a human being would be using this keyboard, hair would fall between the keys. The reason I only invert instead of clamping with a Histogram is so that the small section of the capless builds can build up hair clumps.
I also use a Gaussian Noise to scatter the hair. Tile Samplers can take different maps and allow you to cause objects to be distributed based on the value. They can do half the work for you!
The Crumbs were the simplest part. Since I only want them to show up between the keys, I make a little more defined mask since I don’t want them appearing on the tips of the capless parts. I take a Dirt 5 node and clamp out most of the information with a Histogram Scan, and then use a Transformation 2D node to make the clumps bigger. I use the same trick I used back when we clamped the side of the Keyboard keys to cut off the smoothing of the edges using a Blend node. Afterward, I make a mask and run it through a Blend node to cut off bits where the crumbs shouldn’t be, leaving me with my result.
The final component is dust. Most of this is just creating a Mask. I use a simple Dust 2 node and a Bevel node to creep up the sides of my keys. Dust would slide down the slope of the key and then get stuck and collect, so that’s the spot that makes the most sense for the mask to take up. I use a Cells 1 node again, clamped with a Levels to erase some of the masks so the dust doesn’t collect so uniformly, and run a Clouds 3 through the mask to add some more variation.
Finally, I take all three components and use Blend set to Max Lighten set to lower values, so they’re subtly implemented into the height map. If you use Add, your white values will add to one another which can cause peaking, but if you use Max Lighten, then the values won’t pass their highest states, thus giving you a better blend.
Here’s the final height map! Don’t forget due to our masks, we have a lot more control of where the keys can be rearranged, thus giving us different looks and thus able to generate several different types of maps for the situation.
For my Normal, AO, and Height, since I was working with all 3 at once, I don’t have to do anything more due to my setup and we can just ignore them. Keyboard keys are also a flat plastic, so I took the Metallic Output and filled it with a Uniform Color set to Black.
The best part is now that we’ve made all these different masks for our different parts, we can get right into the albedo and roughness without much delay.
I switch off on occasion depending on the material, but most of the time you’ll want to determine your roughness first. It’s much easier to find out how light will react to your material I block out how light will shine off every part of it without color information interrupting the feel of the material. I recommend setting your Uniform Color for the base color to Black for this step, as you’ll get the most reflection.
I start by taking a Blend node and two different greyscale Uniform Color nodes. I use my Keys as a mask and then Blend it with another Uniform Color this time using my capless portions as another mask. Now if I adjust these Uniform colors, I can adjust how my mask shade will change. The plastic itself isn’t extremely glossy but does have a bit of shine to it, so I try to keep close to .65 to .9 for my color values.
By taking a Normal of my keys and run it through a Curvature Smooth. I absolutely adore this node for color and Roughness. It creates a curvature map of your material which is super helpful for creating edge detail. I then run it through a Levels node and decrease my white values by quite a bit to clamp out most of the highest part. I then Warp it by a Gaussian Noise and Blur HQ Grayscale it and finally blend it on top using my mask from my Height Blend which will overlay the colors over. Now where the keys are, the edges will have some blurred smudges, since a human’s fingers would be constantly touching the keys, the top would be glossier than the sides or the base of the keyboard.
Then, I take a Uniform Color and set it all the way to white, and blend it overtop using the hair as a mask, so that the light information would bump over the clusters of hair.
Next, I imported a Bitmap of a fingerprint, something I rarely do, and ran it through an Invert Grayscale to convert it to a node. Afterward, I spread it around a Tile Sampler, while using a mask of my keyboard keys and inverting the fingerprint output. Then it was a simple Blend with Multiply to make sure the fingerprints were on only the top of the keys. You would want a bit of a bevel to the mask, so the fingerprint doesn’t run down the side of the key, which isn’t pictured in this example graph.
Afterward, we get to the final step, grease. Your fingers have natural oils which accumulate on your keys over time. Plus, since we have the crumbs and can assume whoever used the keyboard was eating, whatever oils of the bar they’d be eating from are transferred onto their fingers. This is how we tell a story through our materials, by including visual cues that showcase. Even if we excluded the crumbs, we could assume that the keyboard was being used from the oils and fingerprints on the keys. The fingerprints could be a bit more smudged unless he made very quick taps.
To make this grease, I get a Grunge Map 01 because the streaks of Grunge 02 don’t make much sense to use for this. Grunge Map 01 has a better more random assortment of colors. I run it through a Directional Warp using the Randomized Tile Sampler I made back for the master blend with all the different colors to warp it.
Finally, I mask in the dust with a Blend set to Screen which eliminates all the black values and then a Grunge Map 01 that’s broken up by a mask of all my components, so it only hits the floor of the keyboard. This is to simulate humidity or oils that might have strewn down onto the keyboard. The final Blend is with a Uniform Color set to white with the crumbs as a mask.
Now that our roughness is done, we can move onto the final output, our Albedo.
Our Albedo is going to be set up the exact same way as our Roughness. Since we already have all the pieces masked out for the roughness map, we can use those same outputs to generate our colors. Don’t forget all this information is from our height map, which is why getting our individual forms down is so important.
I take my two key components and run each of them through a Gradient Map node. This allows me to map their individual white and black ranges to whatever colors I choose. I use my Height Blend mask again to combine them, using an HSL node for color correction.
I then extract the individual hair mask and run it through another Gradient map, masking those on top as well. I make sure to keep the blending to a very low opacity to keep the transition between the colors subtle.
To finish up the keys, I take the same Curvature Smooth I used for my roughness and Blend it on top using Overlay. Most times you’d want a low opacity, but for this material, I found a higher one got me a better result. You would use this for your edge detail if you wanted to chip or the like, just like using a mask in Substance Painter.
For the final segment of the graph, I use the Text node (I think the only time I ever have) and create letters. Since Tile Samplers can only hold up to 6 inputs, I cheekily choose the letters of my website name (Chair) and smudge the 6th one with a Directional Warp and Perlin Noise, since after a while the paint would wipe away from constant use, like how my a and s keys on my keyboard have been obliterated.
Afterwards, I run it through a Gradient Map to convert the grayscale information to color information and then blend it into the chain, along with a little bit of my Ambient Occlusion to get some extra shadow information. This step is skippable, but I like to add less than .1 Opacity just to for a bit more definition.
I then run a Dust node from an Ambient Occlusion of just the capless segments, lightly running a white color through them to add a bit of buildup inside of the crevices. It’s merely for plastic coloration. The Dust node is incredibly useful and for organics is a must for color variation since its variable through both your normal and AO and can get you nice natural looking buildups whether its dirt, dust, pebbles, sand, or any fine material.
I also run my fingerprint mask through a Gradient Map and reduce the opacity on it as well, since the roughness should carry out most of the work. Unless the paint was smearing away from your finger.
We repeat the same process for the dust and crumb components, running them both through Gradient Maps and masking them out respectively.
And with that, we’re done! The next thing I like to do is take the material into Marmoset for renders.
Marmoset is a powerful tool that I love using for presenting my portfolio pieces but bear in mind that you should be showing them off inside of a game engine too. Material Artists need to show that they can stay within engine limits and not just put materials on balls.
I usually render on a ball (Despite what I just said) since it shows how light can hit at a 360-degree angle, and on a plane. I keep a sky with a fill light, a rim light, and a cool light to counteract it. Depending on the material, my lighting setup would change.
I usually like to go with a little bit of a horizon gloss on my material and a small amount of Depth of Field to help make the render look a bit fancier. You don’t want to overexpose your material. An SRGB value of 117 is the benchmark for over and underexposure.
This Nintendo DS was also done in Designer, using almost the exact same workflow I used for my Keyboard keys. The best part about art is looking back at it after a few months and seeing how you’d change things and do them differently. The plastic of the bottom screen needs some more scuffs, and the buttons could have little divots that they’d push into.
Silly projects like these aren’t practical because it’s much cheaper to model them instead use god knows how much tessellation on them, but they’re still good exercises. I highly recommend checking out Phil Liu’s Iron Throne that he made in Substance Designer. It’s really cool, and crazy.
Remember, think of your reference, think of where you’d find the material and light accordingly. Create your height map in a smart way so you have masks to make the rest of the project easier. The possibilities are endless!
I think the biggest problem I see with a lot of artists who use Substance Designer is their overreliance on certain tools. A lot of projects often abuse Cells and Slope Blur to get these very inorganic results or suffer from flat colors, roughness, lighting, or a combination of the three.
Materials help to elevate models and landscapes. They cause the player to feel immersed in the game’s reality. Everything must tell a story or pop out in a stylish way. I have several Materials that I was once proud of but now I’ve been slowly pushing them out for better work. As you make more art, you always will get better. I’m still learning too. We all are.
Here are some tips I’ve learned that will help you guys out in working in Designer.
More often then not I see some people struggle with strange artifacting in Designer. This is because chains in Designer follow the Bottom node. Here I’ve plugged in two nodes, one set to 8 bit and one set to 16-bit. Even though they’re being blended together, the Blend node retains its 16-bit channel. The same goes for image resolution. I always work in 2k but will downscale certain nodes to save memory when I need to.
To fix it, go to your parameters and click the button shown and change the Output Format to Absolute. This will allow you to change the bitmap size and eliminate the strange artifacting.
When using grunge maps, often times I’ll also see people just slap it right onto their material and call it their roughness or albedo. While that’s fine most of the time, it doesn’t feel very natural. If you have cracks or breaks in your material, then the lines would be broken up or wouldn’t travel straight through. Using a Directional Warp, this is what I did for my keyboard keys. See how the Grunge Map 01 gets broken up according to the grayscale? You can pump the value of the directional warp up as high as you want I usually will use this to break up cracks formed by cells.
Speaking of cells, I think they’re one of the most misused nodes in Substance Designer. While they are great and used for a variety of different things, if you wanted to get full control of them for organics, then the setup shown above shows how you can get any of the four included cell patterns but with more control of your pattern. I take a Tile Sampler and fiddle with the options Scale Random, Mask Random, and Color Random the options.
Afterward, I take a Histogram Scan and set the position all the way up to 1, to make all the values clamped at pure white. Then by using a Distance node, we can create the first two cells patterns. To cap it off, we use an Edge Detect to get the other two patterns, changing the width and roundness to match.
Though our Cells patterns have options to change the scale and disorder within them, using our Tile Sampler and Edge Detect Setup, we get more control of the pattern Scale, Direction, and overall can add more randomness than just changing the disorder and how magnified it is. If a material was going to be in a game, you’d want to be able to make tweaks as easily as possible. I find this process especially useful for rocks.
The last tip I have for you guys is involving edge wear. If you simply blend a slope blur over whatever shape you’re blurring, you can decrease the intensity of the edge damage. This can be nice for smoothing out where you want the most clipping to be, without having to adjust the actual blur, and the best part is it only adds one blend node, so it’s super inexpensive!
I used this technique on these bricks below, using the Histogram Select method I explained earlier in my breakdown to get different variations for certain bricks.
The goal I would say in making the most organic looking materials is to avoid repetition. All textures tile, that’s just the nature of the beast, so try to add as much visual interest while working with a nice detail-oriented skill as possible. You want to break up the pattern as much as you can to get interesting results that will get people’s eyes to wander. If I wanted to push these bricks, even more, I could add ivy growing down, or spray paint decals. There’s never an end to what you could do.
I’m very excited to be able to work in a program like Substance Designer. It has become even more fun for me to work in it for five hours than it has been for me to open some video games recently. All I look for is to evolve as an artist and continue to learn new techniques.
I’m always open to talk about art! Below are my social media links you guys can contact me at. I’ll also be present at GDC 2019 all week long! If you guys like my work, my Portfolio is among these links:
Thanks to Kirill Tokarev & 80 Level for allowing me to have this opportunity to write this article. I visit 80 Level frequently and it’s been a blast seeing what other knowledge bombs have dropped. I’m glad I get to be a part of that as well!
I hope you all learned something from this, and have a fantastic day!
Charlie Foreman, Environment Texture Artist
Interview conducted by Kirill Tokarev