Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
How to use ArchiveXL's new material property interpolation
Published: May 01 2024 by Last documented update: May 01 2024 by
ArchiveXL >= 1.13 — this will not work with older versions
You have a general understanding of how materials work (or read up on it under #material-assignment)
You have a Wolvenkit project and a mesh as well as a bunch of .mlsetups
Because it's even lazier: For a mesh with 15 appearances, you need...
legacy | dynamic materials | |
---|---|---|
To be even lazier, check out ArchiveXL: Resource patching and ArchiveXL: Resource linking!
Normally, your materials look like this: a bunch of different appearances with the same .mlmask
, but one .mlsetup
file for each colour:
The more variations you have, the more duplication you have, because you need to register a materialEntry
for each material, and then create a material for each of those. Traditionally, you do that by duplicating the last entry and changing the depot path. Tedious and not fun, right?
This is where the new technique kicks in.
We start by changing our chunkMaterial
names. By appending the suffix @dynamic
, we're telling ArchiveXL to map them to the CMeshMaterialEntry
with the same name.
Instead of 15 materialEntries
, we're down to one.
Now, we need to adjust the material instances. We can delete all but one, since our @dynamic
will contain everything that we need.
Since that one won't change, we can leave the MultilayerMask
alone. For the MultilayerSetup, we need to change both the DepotPath
:
By making the depot path start with a *
, we tell ArchiveXL that this is a dynamic material
The value for {material}
will be passed from the appearance, like this:
... and the rest just works.
You can use dynamic interpolation in pretty much everything — base material paths or material properties. Just remember to set your Flags to Soft
, or it will fail.
But wait, there's more. After using dynamic materials, we've been able to reduce the number of material entries and instances, but there is still a lot of repetition between the appearances - if you've followed this guide so far, each of your appearances has a chunkMaterials
list that looks the same as all the others except for the different material name. It would be great if we could get rid of that repetition, and we can, with Appearance Expansion.
And it's very simple to do. You simply assign empty chunkMaterials
lists to all your appearances except the first one, and ArchiveXL will automatically use the first appearance as a template and generate the chunkMaterials
list by substituting the appearance name:
Now, you only have to maintain one chunk list, and the rest of your appearances are simplified down to a single name and nothing else.
The Flags for any dynamic material must be set to Soft
, and the depot path must start with a *. will warn you about this.
Modify Cyberpunk's visuals
This section contains guides for
the process of modifying Cyberpunk's visuals.
Out-of-date content and guides.
All of these articles are out-of-date. Only use if you really know what you're doing.
How to make a custom MultilayerMask for your mesh
Created & Published: April 12 2023 by @manavortex
This tutorial will teach you how to create your own MultilayerMask for an item and then assign an own MultilayerSetup to it.
Difficulty: You know how to read.
Start by adding any .mlmask file to your WKit project. It doesn't matter which one, but you can start with this (6 white layers):
Then, export it via the Export Tool.
This will give you the following file structure:
Add the mesh that's supposed to hold your material to your project and export it.
Import it into Blender and select the Texture Paint perspective.
Switch into Edit Mode
Select those parts of the mesh that you want to color.
Duplicate them (Ctrl +D, ESC) and split off a new submesh (P -> Split Selection).
Switch back into Object Mode.
Select the new submesh; hide the old one.
Create a new image. It can be 512x512 for now; only upscale if you find that you can't get it un-pixelated in-game. Most CDPR layer masks are really low resolution!
Switch the right viewport into "Texture Paint"
Find the "Texture Slots" dropdown in the menu (you may have to scroll)
Set Mode
to Single Image
Select your new black image from the list below.
In either of the panels, set your brush foreground color to white (or gray). This determines the transparency of the layer. I recommend that you use white and regulate transparency via mlsetup, but if you want to paint e.g. clothing folds or wear&tear, you might want to paint greyscale.
Optional: Set these properties under "Options":
Paint!
Rinse and repeat until all parts of your mesh that should have your material are white on the left-hand image.
Now for the annoying part: On the right side, make sure the mask is more or less smooth, as you will see this in-game.
Now, save the image: overwrite one of the layers from the mlmask that you have exported. If you run out of layers, you can just add them at the end.
The game assumes that layer 1 is white, so start exporting over layers >0
Do this as often as necessary.
Once you're done, open the masklisk and make sure that you have exactly as many entries as you have images in your folder (adding or deleting them as needed). Then, in Wolvenkit, import the masklist via Import Tool.
All images in the multilayer mask need to have the same resolution. Otherwise, it will crash your game.
You can now assign your new Masklisk to your mesh and use it together with custom MultilayerSetups.
An investigation and documentation of several methods of advanced LUT workflows.
This is a complex document meant for experts. Made hastily to finally get the method out there and let others experiment with it. Will be expanded as time goes on.
Lighting in REDengine is complex. Since the conception of it, REDengine has been using a probe-based global illumination system, which requires a single bake of lighting for all times of day. This method is inferior to baked RT, but is suitable for systems with dynamic time of day and weather.
However, this method has its limitation, several, and we see them being corrected with the initial implementation of fullly dynamic semi-global illumination in the form of Psycho RT. Differing from other quality levels, Psycho implements a pseudo-global illumination tech, instead of other RT levels simply tracing lighting for global light sources, such as the sun and the moon.
After patch 1.62, and after the creation of ReSTIR GI, we see now that CDPR has implemented a fully-realized RT pipeline. Each step of the way is handled by rays rather than normal approximations.
The benefits, other than the obvious ability for fully realized global illumination and direct illumination, are numerous. Each light can now cast shadows, use material parameters for nearly-perfect subsurface scattering, ideal light blending and intensity.
I will go further into detail on the new possibilities with PT in another entry, today, we will focus on...
Recently, I have been working on recreating a cinema-accurate and professional-quality workflow for color grading in Cyberpunk, and generally, trying to retrace the steps CDPR took to get such a unique, albeit, polarizing look to Cyberpunk.
Before 2020, while the game was in heavy development, CDPR used a different, more parametrizable method for handling HDR assets and lighting. They would simply running through a TMO (tone mapping operator) to get back to 8-bit range and afterwards apply color grading.
This, while convenient, did make handling HDR display quite difficult. How could you apply a color grade made for SDR on top of HDR without losing precision or missing data? This required a full restructuring of the method.
Eventually, CDPR landed on the method I have been able to reproduce. They used a normal, neutral LUT texture and ran it through ACES (Academy Color Encoding System) transforms to go to a neutral color space, ACES AP1. I do not know the gamma they used (could be ACEScct or ACEScc, maybe even the linear ACEScg), but I do know that eventually, the HDR data was ran through the RRT (Reference Rendering Transform) as a tone mapper, then through the ODT to go to either HDR or SDR.
Unfortunately, I have not been able to single out a method to generate HDR LUTs from scratch, however, I have been able to create a workflow to create tone mapped LUTs for SDR.
DaVinci Resolve Does not matter if it is studio, but studio will be required for the eventual HDR workflow.
Photoshop
WolvenKit
NVTT Exporter and the respective Photoshop plugin. Can be found on NVIDIA developer, does require an account to download.
Right here is where I almost gave up.
DaVinci refused to open. I tried all I could, searched the internet, tried every damn solution. Nothing worked.
BUT, looking at the log files, I was able to deduce the culprit.
SyManager.DeckLink failed to respond due to some USB issue, I even looked that up and well, no dice.
Eventually, I came to think that it may be an issue with the control panels utility for Resolve, as Blackmagic sells some cool decks and accessories for colorists to work faster. But, I'm not rich enough for those, so, I figured, why not just uninstall the entire framework for them.
Boom, DaVinci opened right after.
Some of you who are more familiar with DaVinci may be already going ahead and setting up ACES in the DaVinci color settings, changing and messing with color science and management, etc. Stop. We're gonna be using nodes.
Below are 2 sample pictures captured with the method, we will be getting a grasp with non-destructive color grading this way.
Insert these pictures into your timeline and head into the Color tab. Then, select your clips and add them to a group, the group name doesn't really matter. We'll only be doing this to use pre-clips and post-clips.
Head into the pre-clip level and apply an ACES transform node. Set your input transform to SRGB and output transform to ACEScct (ACEScct behaves better than ACEScc at times, use your preference) and don't forget to turn on the reference gamut compress.
Afterwards, go to the post-clip level and add another ACES transform node. Now set your input transform to ACEScct (or ACEScc) and set the output transform to SRGB.
Your clip level now has full range and fidelity. You can color grade to your heart's content in the clip level, but I won't be going into detail in how to do this. Or you could proceed onwards, if you do so, then ignore anything about importing your color graded LUT.
So, how do we put your grade into the game? Glad you asked. After you're done grading, turn off everything but your effects in the clip level. Generate a LUT from here. It doesn't matter if the image you see doesn't match up with the one you graded with, we'll be correcting for it further on when we generate the LUT.
It's now good to mention that Cyberpunk outputs data with an ARRI LogC3 encoding, but SRGB color space. ACES, on the other hand, expects ARRI LogC3 encoding but ARRI Wide Gamut 3 color space as well. At the end, Cyberpunk expects SRGB data with SRGB gamma too, so you need a TMO to handle this conversion from HDR data encoded in a Log curve to fit in SDR range, but decoded and then put into the display gamut and dynamic range.
ACES is apt for the job.
Take the LUT texture above and add it to your timeline as well, and assign it to another group.
Go to the pre-clip level for your LUT clip and add a Color Space Transform node. Specify the input color space and gamma as SRGB, but output color space as ARRI Wide Gamut and output gamma of SRGB as well.
Subsequently after the CST (Color Space Transform) add your IDT (Input Device Transform) using an ACES transform node. Set the input transform to ARRI LogC3 with an exposure index of 800 and output transform of ACEScct (or ACEScc depending on what your color grade was made in/for). Make sure you enable color gamut compression, or else you will get horrible clipping in higher exposures.
At the post-clip level, add your ODT (Output Device Transform). Set your input transform to ACEScct/cc and output transform to SRGB. Once again, turn on reference gamut compress.
Now, in your clip level, add a corrector node and then drag your generated color grading CUBE LUT atop the corrector node (skip this if you didn't grade)
Once you have done all of this, right click and select "Generate LUT" and export a CUBE.
Congrats! You have now reached the homestretch in the reverse-engineered LUT workflow. This part could be confusing for some, but it's easy enough if you're familiar with visual modding or handling XBM textures on a very high level.
Once your CUBE is done exporting, open the lut.png file you downloaded before in Photoshop. Here, you need to add a "Color Lookup" layer. Select the 3D LUT file to be your generated LUT from when you finished the CUBE LUT in the last step. Once it is applied, apply a channel mixer correction layer and flip the blue and green channels.
After this is done, export using the NVIDIA Texture Tools plugin as a 32x4f DDS with no mipmaps as well as highest quality compression.
Once you are done, put the texture into WolvenKit and import using these settings:
Afterwards, set the depth, height, and with properties to 32, then go to renderTextureResource -> renderResourceBlobPC -> header -> sizeInfo
and set all of the properties there to 32 also. Don't forget to change the texture type to 3D in textureInfo
!
There it is. Your tonemapped LUT from scratch.
This initial revision is messy, very messy. Ideally I would've loved to make a video showing off the process in detail, being able to go on tangents and show you around exactly how I stumbled and developed upon the system, reasoning behind a few of the decisions I made in this entry, but I lack the resources right now (notably a microphone)
Normally I'd try to make the entire thing seem more accessible in general, but really, this is an extremely complex topic that would take some experts press their eyes in frustration. I know it happened to me a ton.
If you're looking for pre-made examples, I have a few right here:
Appearances
15
15
mlmask files
1
1
mlsetup fil,es
15
15
#materialEntries
15
1
#CMaterialInstances
15
1
#chunkMaterials
lists
15
1
In-game, your normal map isn't looking as expected
The texture has to be imported without the isGamma
flag. Import over an already-existing normal map to rule out this as a source of error. See this conversation on Discord for more detail.
Cyberpunk actually considers the UV map's scaling when calculating the weight of the normal maps:
Since the neck part is scaled much larger than the chest, this will make the parts of the mesh visibly distinct.
How to edit images and preserve transparency
Rache Bartmoss once said: the first step to importing a texture is exporting a texture.
For documentation on the Wolvenkit Import/Export tool, see here.
Add the texture you want to overwrite to your Wolvenkit project.
If necessary, move and rename it. You should stick to the game's naming convention.
Find the Export Tool (Tools -> Export Tool) and export the texture.
You can now find a png file in your project's raw
folder.
Editing textures is straightforward: just change them in your image editor of choice. The only hitch for reimport is the transparency.
Wolvenkit supports the .dds file format, but since that is more complex, we won't talk about it here and stick to the .png
format.
If you're using .dds files, you probably know what you're doing anyway :)
Paint.NET is a free image editing software for Windows. It supports PNG transparency out-of-the-box.
To export with transparency in Photoshop, you need an alpha channel. Fortunately, creating one is simple. (For the initiated: The alpha channel is just a layer mask over the entire image.)
Find the Channels palette at the bottom right of your Workspace and add a new channel:
Your image will turn black now, because the selected alpha channel will not have transparency yet.
To get your image back, select "RGB" on the Channels palette — but we'll stay on the Alpha channel for now.
In the layers palette, use your image as selection by ctrl+clicking on the layer's icon:
With the alpha channel selected, fill your selection with white to mark the transparent parts.
The fastest way to do that is to press d, x, delete
You can now save your image as a PNG with transparency. If you have exported a texture in the first section, you should overwrite that file.
Find the Import Tool (Tools -> Import Tool) and select your texture.
If you have stuck to the game's naming convention, Wolvenkit will select the right preset for you. Otherwise, you need to select the right preset:
TexG_Generic_Color
for a diffuse/albedo
TexG_Generic_Normal
for a normal map
TexG_Generic_UI
for anything that you want to use in .inkatlas files
… etc
If your texture is upside-down, uncheck the box for VFlip
.
Click the "import" button. Your .png
will now be imported Into the .xbm
file.
Change Compression
to TCM_None
, then reimport
Your texture must be a square, and its size must be a power of two (512x512, 1024x1024, and so on). If you want to know more about the theory behind this, you can read this external tutorial. Otherwise: just make it a square!
If you are importing a .masklist
, all images for the resulting .mlmask
must be the same size. Cyberpunk will crash otherwise.
Some textures need to be in a certain colour space (theory on wikipedia). For certain types of textures, the game requires certain colour spaces. Here's a list:
If you don't know how to achieve that, google something like
<name of your editor> color space <color space>
e.g. Photoshop color space black and white
Maybe your .mlmask
has gotten corrupted or is simply incompatible. Replace it with any mlmask from the game files and try a reimport.
How to create normal maps (bumpmaps) with Blender
Published January 06 2023 by @manavortex Last documented update: January 20 2024 by @manavortex
This guide will teach you how to create a custom normal map.
For a different guide about this, check this Google Doc by Тима (Teem)#3118
For a guide on Cyberpunk materials in Blender, see Cyberpunk Shaders in Blender
If you want to create a .mlmask
instead, see Textures: Custom MultilayerMask
Otherwise, you can use the wiki's search function — it uses an LLM and is actually quite useful.
If you don't have Photoshop, Photopea offers almost the same thing online for free.
For a free tool for faster normal baking, check out xnormal.
Export your mesh from WolvenKit
Import it into Blender (do not import materials)
Select the object
Make sure your material has exactly one material (see the end result in the screenshot at step 5):
if there are no materials: Awesome, you passed the reading comprehension test! Create one by clicking the +
button.
If there are materials: You failed the reading comprehension test and I am very disappointed. Delete all but one by selecting them and clicking the -
button.
The viewport should already be set to "Solid". Click on the dropdown arrow next to the options and select "Texture" from the list.
As the first step, we create a Displacement Map for our 3d object. This black and white image will turn your mesh into an object with actual (simulated) depth, which we will then "bake" into a normal map.
This tutorial won't cover the process of how to draw such a map in-depth, but there will be a few tips how to do that in Blender.
The displacement image should be saved in 32 bit image depth rather than the usual 8. This will yield better results with the normal maps.
The Texture Paint perspective lets you draw directly on your mesh's surface:
To see how the mesh is projected on your image, you can check out the UV edit mode.
Switch to "Edit" (shortcut: Tab) and select all vertices (shortcut: ctrl+A). You will now see them projected on the texture:
Feel free to change the UV mapping. You can export this back into Cyberpunk!
Once you are done with your displacement map and the UV mapping looks like you want it to, it's time for the next step: projecting!
Take your displacement map and create a slightly blurry version of it. This will prevent artifacts on the normal map, as the algorithm doesn't like perfectly straight edges.
I create a duplicate of my entire armature, just to make certain that I don't accidentally overwrite anything I want to keep. Only work on the new object, since we're getting destructive here.
Make sure that your viewport is in Object Mode
Select all objects that you want to go on the same normal map, then join them together (shortcut: Ctrl+J).
Create a duplicate of this mesh (Ctrl+D, ESC to stop moving), then rename that to "Low Poly".
Select the mesh you duplicated and rename it to "High Poly".
Open the "Modifiers" tab and assign the following modifiers after the armature modifier (check screenshot in Step 6)
Generate -> Subdivision Surface Levels Viewport: 2 or so Render: As many as Blender lets you get away with without crashing, I used 7 Advanced: UV Smooth: Keep Corners, Junctions Boundary Smoothing: Keep Corners
Deform -> Displace Coordinates: UV UV Map: UVMap Direction: Normal Strength: -0.002 (you can play around with this) Midlevel: 0.000
If you hide your "Low Poly" mesh, the modifiers should now let you see creases on your high poly object! Exciting!!
The normal map will only care for relative depth, so keep the creases on your mesh shallow. If you make them too sharp, this can lead to artifacts on the baked normal map.
Switch to the "Shading" perspective again. Add another image texture and create an image with your target resolution. Call it "Bake" or whatever.
Remove the link to your material's normal input - otherwise, it'll bake your normal map into your normal map, and the results won't be pretty.
The high poly mesh needs to be completely covered by the low poly one, like plastic wrap. That will normally not be the case yet, so we need to inflate the poly mesh:
Set the viewport to Object Mode
Select the Low Poly mesh
Switch into Edit Mode (Hotkey: Tab
)
Select all vertices (Hotkey: ctrl+A
)
Optional: Merge by distance (Hotkey: M
)
Fatten (Hotkey: Alt+S
, adjust amount of fattening via mouse or by typing it in directly)
Fix up whatever parts didn't fatten correctly by hand.
Undo your action and select all vertices again.
Put the 3d cursor in the center of the selected vertices:
Right-Click -> Snap Vertices -> Cursor To Selected
Set the Pivot Point to 3D cursor (Shortcut: .
(dot), Numpad 6
)
Fatten again!
If you're unable to shake a normal map from this process, you might have to resort to Photoshop. (If you don't have it, photopea.com offers almost the same features for free).
Switch back to Object Mode.
In Blender, the "active" object is the "previously selected" one. Select your meshes in the following order:
Low Poly
High Poly
Find the "Render Properties" tab.
At the very top, set "Device" to "GPU Compute" (unless you'd rather bake on your CPU)
Scroll down all the way to "Bake". Configure it like this:
Bake Type: Normal
Influence / Space: Tangent
Selected to Active: Checked
Extrusion: 0.04 m If your generated normal map shows artifacts, try tweaking this.
Max Ray Distance: 0.04 m If your generated normal map shows artifacts, try tweaking this.
Output / Target: Image Textures
Clear Image: Checked
Margin / Size: 16px (or whatever suits you)
Save. Your. File.
Baking takes time (several minutes) and most of your PC's free resources. This is normal.
If everything went well, the image editor on the bottom left will change and display your normal map.
You can export the image via the hamburger menu in the image editor (bottom left panel of the screenshot).
If you don't have Photoshop, photopea.com offers almost the same features for free.
So your baking process failed horribly and you're frustrated. Fair, I've been there — 3d edits are finicky. Let's do it in photoshop instead.
Load your black and white image into the photo editor of your choice (Photoshop or Photopea).
From the menu, select Filter -> 3d -> Normal Map (Generate Normal Map) in Photoshop)
Photoshop: Click "OK" on the popup (about the 3d features being outdated)
Tweak the parameters until you have a normal map — you want it to be as sharp as possible without artifacts/tearing! Some blur might be necessary.
Click "OK" to apply the changes.
Congratulations, you now have a normal map.
This troubleshooting section is for the baking process — the one for normal map textures is here.
Make sure to remove the normal mapping from your material.
First of all, make sure that all your normals are pointing the right way. In the viewport editor, click the "Show Overlays" button and select "Geometry -> Face Orientation" near the bottomn. Blue means outside, red means inside.
The baking process works by capturing the rays of light that bounce between the high poly mesh and the low poly mesh. If you have artifacts, then some of those rays bounced off something else first, which makes them register as inverted. That's the reason why steep creases are a problem — a ray of light might get caught in there and be flipped around.
Check the troubleshooting step for artifacts.
Make sure your displacement map (the one used by the modifier) is blurred.
Try lowering the strength of the Displace modifier on the High Poly mesh, making the creases more shallow.
Try changing Extrusion and Max Ray Distance in the Bake settings.
If that doesn't help, you could try a cage, or otherwise hit Google.
Restart Step 4 and make sure that you haven't deleted or altered any vertices, other than scaling/inflating the low poly mesh.
This is a workaround and won't solve the problem. If you know how to fix this for good, please update this page!
Open the UV of your 3D model and select the vertices that are outside on the left of your UV
Now you have two separate submeshes. Export them both into the same .glb file for Wolvenkit.
Open Photoshop, Paint.net or Photopea to invert the green channel. Save your new .png under a name like <name_inverted_n>
Import your inverted normal map in Wolvenkit. Now, you can create a new material for the normal-inverted parts of your mesh!
How to create custom microblends.
This guide was originally written by Halk and imported with their permission. You can find the original.
The easiest/quicker way to make custom microblends is to have access to Photoshop and use ready-to-go seamless patterns. I like to look for these in and .
You can try making your own seamless pattern with the help of (for Photoshop).
After you download or make your pattern, make sure it’s a 1:1 seamless image. I recommend working on at least 1k (1024x1024) to keep the quality.
Turn everything you don’t want as microblend into transparency. You can magic wand if you’d like, but a quick way to do it is using the Color Range tool in PS. In my case, I’ll get rid of the grey areas.
Upper menu: Select > Color Range > Use the eyedropper to select the color you want gone.
Change the Fuzziness to make it as clean as possible.
Lock the transparency on this layer, then fill or paint the pattern with THIS PURPLE (#7f7fff).
If set up like this, it will be a one color microblend. To make two or more colors, separate the elements you want and save multiple files to go into different layers of the mlsetup. For example:
Save the file(s) as .png, and extract the base\surfaces\microblends\scratches_and_flakes_a.xbm microblend from the files. Head over to Noesis and export your custom microblend(s) over the scratches_and_flakes_a. You can also work with .dds by saving it in compression BC7.
Now simply custom-path your microblend(s) while making sure to path them into the µblends window on MlsetupBuilder OR in the microblend path in the .mlsetup on WolvenKit.
IMPORTANT: if you’re adding microblends into a custom port, don’t forget to make the microblend layer in the mlmask a neutral grey, otherwise it’ll screw with the microblend color. For me, the 50% grey (#959595) from PS works perfectly.
A description of a streamlined, refined, accessible, and relatively easy system for creating Cyberpunk 2077 LUT mods from scratch.
This method is for LDR. Little to none is known about HDR LUT creation, so please, do not expect anything on HDR LUTs.
It's imperative to understand what LUT really is before starting. Often, beginners have a misconception caused by other software which often uses different formats for LUTs and different ways to apply them, such as ReShade.
Cyberpunk LUTs are distinctly different from ReShade LUTs due to two things:
They are 3D textures, not 2D textures with tiles describing different parts of the RGB cube, no, Cyberpunk LUTs are full-on 3D textures sampled with trilinear filtering.
They are applied with an input of ARRI LogC3 data with an sRGB color space. This means you can't go and use any ReShade LUTs, as they often do not expect LogC3 output. Along with this, many tools expect ARRI LogC3 data with an ARRI Wide Gamut 3 color space when generating your LUT. If you do not convert to it, you will end up with clipping colors.
But, aside from that, they are similar. Any LUT expects an input of a color, with an output of a new color. That's it. Cyberpunk's implementation is as simple as extracting the pixel out of the LUT texture that matches the input color, and if there isn't an exact match, it interpolates linearly to get a near-perfect approximation of the true output color.
If you're still confused, I recommend looking at .
You only need to complete this section once.
You can check out nullfractal's . It contains NVTT settings, DaVinci Resolve and WolvenKit projects along with LUT file templates to play around with.
You can't download the NVIDIA texture tools from the without an NVIDIA account that participates in the developer program. We've put a backup of the executable on the wiki's — you need to decide which is the lesser evil, yet another account or downloading a random .exe from the internet.
DaVinci's website prompts you to fill out some data before being able to download the software. You can fill this out with fake data, it doesn't really matter.
You can use Fusion Studio just as easily as well for parts of the guide, and DaVinci Resolve Studio is also recommended in general.
The essential tool for all Cyberpunk modding. Nightly is preferred (and what this guide has been made with), but stable works just as well with newer versions (older versions will have errors).
Create a new project in WolvenKit and import the file base\weather\24h_basic\luts\cp2077_gen_lut_nge_v017.xbm
and export to a DDS, then rename it, removing the xbm
file extension. You should have a dummy name with a file path containing that same file in the "raw" folder. You can delete the file in there, we only need the folder set up correctly.
If you have issues getting Resolve to run for the first time, uninstall the panels program. It causes crashes if you don't have any DaVinci panels or sliders.
Create a Resolve project, and head straight over to the Fusion tab, without importing any media. Add a LUT Cube Creator node, change the type to vertical and size to 32, 48, or 64. Remember this number, as you will use it later. Select for the generated Media Out node to output to both sides of the preview by enabling both of the circles below it. On one of the sides, select Views>3D Histogram. You should now have a LUT cube present. If you'd like more accuracy, right click and go to 3D Histogram and select solid with 1:1 sampling.
Right after the LUT Cube Creator node, add a Color Space Transform node, and matching the fact that tools expect ARRI Wide Gamut 3 with ARRI LogC3 data, but the game outputs sRGB with ARRI LogC3 gamma, we need to go from sRGB color space with ARRI LogC3 gamma to an output color space of ARRI Wide Gamut 3 with output gamma of ARRI LogC3
After this, we need to go from this LogC3 data to sRGB, which is what our display expects.
This is the method used by the original game to go from the input LogC3 to sRGB output, so it's what's recommended.
Add an ACES Transform node after the Color Space Transform node. Set the input transform to ARRI LogC3 with an output transform of sRGB and use ACES reference gamut compression.
This method uses LUTs from ARRI themselves, and as such gives us two options: LogC3 and LogC3 "classic". I encourage you to use the normal LogC3 LUT, but experiment with Classic and see if you like it. Though, this method requires a change in the settings that are described later.
In the link above, select LogC wide gamut as the source format and destination format as video. Select your preference of ARRI Classic 709 and ARRI 709 in the conversion parameter. The file type can be either Blackmagic Fusion or Blackmagic DaVinci Resolve, it really doesn't matter.
Add a serial File LUT node and point to your downloaded file.
It may share a name with the LogC3 method, but is distinct from it as it uses a more recent revision of the color science compared to the LogC3 method, but we will need to change things before and after this step if you decide to use this method.
Once you have downloaded it, extract the Rec.709 Gamma 2.4 65-point .CUBE file from the zip file. Add a serial node after the Color Space Transform called File LUT and point the LUT file to your extracted .CUBE file.
We have to make some changes to the Color Space Transform node, change the output color space to ARRI Wide Gamut 4 (instead of 3) and then the output gamma to ARRI LogC4. Your LUT should now look correctly exposed.
You can mess with the Tone Mapping Method, but just select None as a good option.
We need to change an option afterward that will be described later for both the LogC3/4 methods.
This method uses DaVinci's integrated tone mappers to go from the LogC3 input to sRGB output. It produces a neutral and accurate output. It's also very minimal.
For this method to work, we just need to change the settings in the Color Space Transform.
Instead of having an output color space of ARRI Wide Gamut 3, set the color space to sRGB and gamma to sRGB as well. Then, change the tone mapping method to DaVinci, or some other method if you know what they mean.
This method creates a color cube that is very "unbiased"--it has fidelity in all directions, which, while creating a good representation of true color, can result in unnatural saturation. To account for this, the saturation compression gamut compression method can be selected.
After you have used your preferred method, you need to apply gamma correction. If you do not do this, you end up with incorrect gamma, which can mainly be seen on skin tones.
For the ACES method, you need to add another Color Space Transform node, with input color space and gamma of sRGB, with the output color space of sRGB but output gamma of linear.
For both ARRI methods, nearly the exact same steps are taken as the ACES method, but, instead of sRGB input color space and gamma, we use an input color space of Rec.709, but input gamma of Gamma 2.4. Keep the output color space at sRGB and output gamma at linear.
For the Resolve Color Managed method, simply change the output gamma in the color space transform to linear, but turn on Apply Forward OOTF.
This is the final stage. We now just need to output to an image, and use the right format. To do this, use a Resolve FX Transform>Transform node (not any other transform node) and switch on "Flip Vertical" to correctly output.
Right click on the LUT picture and save your image as a TGA or PNG file.
Drag on your exported file onto the NVTT window and tick off "Generate Mipmaps" and select format as 32x4f. Tick off KTX2 compression and tick on DXT10 header as well turn on Highest compression quality.
Turn on "Extract From Atlas" and set "Depth of Volume" to the exact size of your LUT that you set up when first creating it. To verify you got it right, you should see a Z slider on the top right of the NVTT interface. Drag it and see if there is any vertical shift in the texture. If there is not, you got it right.
Save as a DDS file (only DDS) and put it in the folder that was generated after you exported the XBM file at the start of the article.
You should now see it in the import tool in WolvenKit. Change its TextureGroup property to TEXG_Generic_LUT
, turn off IsGamma, VFlip, GenerateMipMaps, IsStreamable, and PremultiplyAlpha. Set compression to TCM_None
. If your file doesn't have RawFormat as TRF_HDRFloat
, then something in the DDS importing went wrong, and you need to re-set the format as 32x4f in NVTT.
Import the DDS. We need to tell the file it is actually a 3D texture in the header (even if the 3D data is already there), so go to renderTextureResource>renderResourceBlobPC>header>textureInfo>type
and change it from TEXTYPE_2D
to TEXTYPE_3D
.
Make a copy of the XBM file and rename it to cp2077_gen_lut_nge_v017
. Our dummy file there is for being able to quickly copy the filename, so, select your LUT XBM, C-c, C-v, select the dummy file, F2, C-c, select your LUT copy XBM, F2, C-v.
Your LUT is now correctly set up. You can install and launch now!
Here we will go over one of the first steps to visual modding, editing LUTs!
The term LUT has its origins in mathematics, where a Look-Up Table would be able to shorten certain math operations by containing readily-calculated values for any input value, or an operation for an input value for a desired outcome. This shortcut was quite efficient and sped up many operations, and was normally designed as a matrix of different numbers and variables. Soon enough, this improvement in speed would be applied in many other fields, and eventually reached computer graphics and film production.
LUTs are essentially a texture or text file containing every single possible color that can be displayed, and the transformation of an input color into an output color through it.
There are many different types of color-grading-related LUTs, such as .CUBE
files and .3DL
files, but video games often use a texture.
Initially, Cyberpunk took an approach like many other games, and encoding the LUT as an unwrapped 3D texture:
Afterwards, Cyberpunk would repackage LUT textures with the blue and green channels inverted to get higher quality, as the human eye values green more than other colors and is more efficient to get all gradients laid on top of green instead of blue. Here we can safely assume is where the switch to using true 3D textures was also made, but we will not show a 3D texture due to redundancy and inability to do so, so just assume from now on all textures are actually just a 3D cube.
To get even more odd, Cyberpunk would then put the image tone mapping, the process in which HDR colors are processed into SDR, inside of the LUT! This came with the conversion from using a normal sRGB transform, which is industry standard, to using an input of ARRI LogC1 and outputting a linear color which is afterwards processed into normal sRGB gamma by the linear tonemapping.
With all that backstory done--how do we start?!
Create a new WolvenKit project and call it whatever you want.
After that, import the file base\weather\24h_basic\luts\cp2077_gen_lut_nge_v017.xbm
into your project.
Then open it, and change depth
to 1
, height
to 32
, and width
to 1024
. After that, navigate to renderTextureResource/renderResourceBlobPC/header/sizeInfo
and apply the same edits as before.
Export the file into a DDS...
Open it up in Photoshop and... voila!
We now successfuly have the 32-bit HDR LUT imported into Photoshop. You can do any color correction here, or do some ReShade edits in-game and then put that into a LUT image and then use a Photoshop plugin to import it and apply it ontop of this LUT. Make sure you DO NOT simply replace this image with your exported LUT from ReShade or some other editing app, as you will completely ruin the tone mapping the base-game does. I recommend DaVinci Resolve as well and then exporting as as .CUBE
file from inside of it.
When you edit your LUT, make sure you flip the vertical axis (make it upside down) inside of Photoshop!
Let's say I just did some curves tweaking and contrast, etc., etc. Maybe make the green saturation lower and other saturation higher to get rid of the green tint. Now what?!
Save back your DDS using NVTT and apply these settings:
Format: 32x4f RGBA 128bpp | floating-point
Generate Mipmaps: OFF
Image Options - Compression Quality: Highest
If you forgot to flip your image inside of Photoshop, turn on the Image Options - Flip Vertically option inside of NVTT.
Open the Wolvenkit project where you have the original LUT of the game in .xbm
Take your newly made LUT and name it the same as the original LUT, so: cp2077_gen_lut_nge_v017.dds
.
Move it to the folder where you exported the original LUT from the game in .dds
format, and overwrite that one with yours.
The folder in question is: yourwolvenkitprojectname\source\raw\base\weather\24h_basic\luts
.
You can also open the exact location from the 'Project explorer' in Wolvenkit. Under 'raw' folder dropdown you should see the exported .dds
file. If you hover over it, it will show a yellow folder button that you can click to open its location.
Now to import it, hover over 'Tools' at the top left in Wolvenkit, and select 'Import Tool'.
Select the LUT and make sure the import settings are correct
Changing the settings back:
When your LUT imports, double click on the .xbm
file to open it in an editor.
Then change: depth and width in both sections that we modified, back to the default of 32.
Under renderTextureResource>renderResourceBlobPC>Header>mipMapInfo>0>layout
change 'rowPitch' to '512'.
Under renderTextureResource>renderResourceBlobPC>Header>textureInfo
change 'type' to 'TEXTYPE_3D'.
That's it, now either use 'Pack mod' to pack the mod and have .archive file in the Wolvenkit project folder, or 'Install Mod' to preview it in game!
This will replace the sdr LUT for the base game (Night City).
If you want the LUT to also apply to Dogtown, or HDR: cp2077_gen_lut_nge_hdr_v017
is HDR lut. cp2077_gen_lut_ep1_sdr_v02b
and(?) cp2077_gen_lut_ep1_sdr_v002
is Dogtown.
If you want to change these as well, before importing you have to have the paths for these LUTs correct, along with the names.
To achieve this with ease, I suggest exporting the LUTs you want replaced, as they will create paths and give you the names by default.
Then you can go over to their locations, copy your LUT .dds
file, copy the name of the LUT you want to replace, delete the original and overwrite it with yours while making sure it retains the name from the original. Rinse and repeat. Process for importing and adjusting the settings afterwards will be the same as before.
File type | required colour space |
---|---|
Assign a material to the only remaining slots:
Switch to the "Shading" perspective and add an "Image Texture". Select your image by clicking the corresponding button:
For the "Displace" Modifier, create a new picture, then click on the two sliders to show this texture in the textures tab
Load your blurred texture:
Here is an example of the issue :
Follow the same link described in the section until you reach this part. Download the "ARRI LogC4 LUT Package".
You'll need , , and we also require Adobe Photoshop CS4 or later. Photoshop CC is preferred.
Before | After |
---|
.mlmask / .masklist
Black and White / Non-Color
Version
Blender>= 3.6 (working on 4.0)
Assumed skill level
You know what a normal map is
You're able to draw stick figures
You are not afraid of Blender
You know how to read.
As you can see, vanilla's red saturation leaves more to be desired. | After our edits the red saturation is a lot better and the contrast is more satisfying! |
Importing textured items (and creating an AMM prop set in the process)
Published: February 11 2023 by manavortex Last documented update: Mar 18 2024 by manavortex
This guide will walk you through importing 3d objects into Cyberpunk 2077, which can then be spawned via Appearance Menu Mod.
Level of difficulty: You know how to read.
Check Porting 3d objects to Cyberpunk for an import guide, but don't forget to come back here once you're done!
You can learn more about materials under Textures, Materials and Shaders.
If you want to understand material assignment, check 3d objects: .mesh files-> #material-assignment
If you only want to know how to apply Cyberpunk materials to parts of your mesh, check "Splitting off submeshes" below.
For a guide about changing materials, check Changing materials, colors and textures
If you just want to use a textured material, check Using a textured material
Find a look-up list of cool materials under Cheat sheet: Materials
For a more detailed guide about prop creation, check AMM: Custom Props
Or maybe you wonder #where-to-find-models
Appearance Menu Mod (> 2.0.2)
This section is already covered in the guide for custom props, using the source folder variant, or directly download this archive and extract it into your Wolvenkit project.
Optional: Complete the creating another prop section from the custom props guide, or alter one of the two existing template items.
This guide will assume that you are editing template_no_variants.mesh
, as our focus is on mesh import and material assignment. You can delete the folder amm_props\template
, since we won't need it.
Delete obsolete files (Windows Explorer or WKit):
amm_props\template
amm_props\template_no_variants\template_no_variants_multilayered.mesh
textures\6_layers.mlmask
textures\6_layers.mlsetup
The first step to importing a mesh is exporting a mesh
We can't create .mesh files from scratch, so we'll overwrite an existing file. Here's how:
This will create the following files under the project's raw
section:
Optional: Download this archive - I have prepared it for import. It contains both the original glb from sketchfab and the version I prepared for import:
Use the Windows Explorer to copy these .glb files and textures into the same folder as the ones you exported in the previous step.
Replace the files from your export with the files from your download. The names need to be exactly the same.
Use baseball_02_d.png
, as the other one doesn't have transparency.
The import/export process has its own guide. There's also a troubleshooting page if you're stuck.
The next step is to assign materials to the object.
Good! You've been paying attention! Step 2 is to prepare the downloaded 3d asset to work with Cyberpunk. Depending on your target file, this can be any level of difficult, but the steps below should be enough for most meshes.
All of these steps will be taking place in Blender.
If this is your first time and you're lost, check out Blender: Getting Started
The files you download will have all sorts of structures. In the end, you want to end up with a flat hierarchy of object(s):
LOD_1 indicates the level of detail. You only care for LOD_1.
The submesh numbers are important for material assignment in Wolvenkit.
The easiest way to get there is by running this python script (source: manavortex's github) in Blender after import: - Switch to the "Scripting" perspective - Create a new file - Paste the contents of the script into the file - Hit the "play" button
A mesh that I imported with 9 simultaneously visible submeshes made the game crash with a likelihood of ~ 80% when I spawned or de-spawned it (scaling was fine). You might want to create two separate files if you have too many objects.
Since it clearly works for e.g. the body mesh with ten submeshes, make of this what you will.
Sketchfab meshes often use dozens of submeshes, but we want to split by cyberpunk's logic:
Every submesh can have its own material assigned in the mesh, and can be hidden or displayed via chunkmask. This is how you assign Cyberpunk materials to parts of your imported asset.
I've always found it easiest to join all meshes into a single one:
In Object Mode, select all meshes but one (Hotkey: A
, then Ctrl+
click a mesh to deselect it)
Select the last mesh (hold Shift
or Ctrl
)
Press Ctrl+J
to merge everything into that last mesh
Switch to Edit Mode
Select everything (Shortcut: A
)
Optional, but recommended: run the script again to get properly numbered submeshes.
This will let us assign one material per "section" of your mesh.
Especially when exporting meshes from sketchfab, there are often duplicate materials. Feel free to fuse everything that you want to e.g. slap black plastic on.
I usually join everything into one object that'll have the same material in the game, unless I want to hide parts of it to make variants.
But the opposite is also possible: You can split off parts from the original object, putting them into their own submeshes. I have done this in the baseball example: the seams will get a texture, and the rest of the mesh will be coloured with a cyberpunk material.
You do that by changing into the edit mode, then selecting everything that you want to split off ("Select Linked" or "Select More" is your friend here), and splitting it (P -> Split Selection).
You can duplicate your selection first (Shift+D
, ESC
)
Now, switch back to Object mode and select your new mesh before going back to Edit Mode. Make sure to scale your new mesh, so that it is slightly above the surface of the old one - otherwise, you will have two things in the same place, which will look like shit.
Make sure to correctly name your new submesh, or run the script again.
You can complete unparent + apply transformations via Blender script: Switch to the Blender "Scripting" perspective, create a new file, paste the code from mana's github, and click the play button.
Select everything (click the viewport and press A), then unparent the objects by pressing Alt+P. Select "Clear and Keep Transformation".
Since those are saved relatively and Wolvenkit will ignore them, your objects might end up larger or smaler than you expect them, or be in different places.
Select your objects in the viewport, then press Ctrl+A
and choose "All Transforms".
Scale your 3d object in Blender until it has the size you expect it to be in-game.
If you do this in the object mode, you need to apply transformations afterwards. Alternatively, you can scale the vertices in edit mode.
If your mesh still scales weirdly in Wolvenkit / the game, you can create a new mesh in Blender, delete its vertices in edit mode, and then join your original object on top of it.
If you need a reference object, you can use this lightsaber from my props.
Keep in mind that your prop will rotate around the world origin, and position it accordingly.
Once you are done, import the glb file over your original mesh (you can consult the troubleshooting section below).
Your import has been successful when the preview in Wolvenkit changes (you might have to select another file first).
For an overview of materials that you might want to use for something, check here.
You can check a material's properties by opening the file inside of Wolvenkit and checking the last entry of the "parameters" array, or search for "files using this" and looking at how they're doing things.
You can find explanation and documentation about materials here.
Select the entry "texture" inside the array materialEntries
Duplicate it
Select the new entry
Change the name to mlsetup
Change the index to 1
Open the array appearances
, select the first appearance (default
) and select the array chunkMaterials
. Create a new entry, or duplicate the existing one. Make sure the list order shows
Open baseball_textured.mesh
Find the CMaterialInstance "texture" inside localMaterialBuffer.materials
.
Select it, then copy it via right-click (Copy (Selection) from Array/Buffer)
Switch to baseball_tml.mesh
Select localMaterialBuffer.materials
Paste the textured material (Right click, Paste (Selection in) to Array/Buffer)
You can now delete the second mesh, as you don't need it anymore.
Let's update paths and values. Still inside of localMaterialBuffer.materials
, change the following properties:
For the leather texture, I've just picked a random mlsetup from the game files (which I found by searching Wolvenkit for leather > .mlsetup
). If you want to make your own mlsetups, see here.
Save the mesh. You can check the "Mesh Preview" tab if the materials show up. If the mesh turns invisible, you'll want to double-check your paths, though!
Open the baseball's entity file (your_name\your_prop_pack\baseball\baseball.ent
).
Open the components
array.
Select the second component (amm_prop_slot1
)
Change the mesh -> depotPath to the path of your baseball mesh (your_name\your_prop_pack\baseball\baseball_ml.mesh
).
Leave meshAppearance
on default
, unless your mesh has multiple appearances: This is where you select which entry in the mesh's appearance array will be used.
Delete the other amm_prop_slot
components. (These are where you would add more mesh files to your prop - but keeping them makes your prop be full of glowing cubes).
Save the entity file.
If you have more than four mesh files assigned to your entity's components, the prop will no longer be scaleable (as of AMM 2.0.2). You can get around this limitation by making meshes with more submeshes instead of individual files.
Open the lua file under resources\bin\x64\plugins\cyber_engine_tweaks\mods\AppearanceMenuMod\Collabs\Custom Props\your_prop_pack.lua
.
Set modder to your name and unique_identifier to anything, e.g. your_name_your_props
. Now, adjust the first entry in the "props" list to point to your entity file:
The "path" parameter is the relative path to your entity file, but every backslash has to be doubled.
"name" is what you'll search for in AMM. "distanceFromGround" is pretty self-explanatory, but I prefer it if my objects are floating.
Save the lua file, install your mod, and launch the game. Time to test!
For an explanation how materials are assigned to a mesh, check this page - this guide will just tell you what to do.
You can copy entire materials between meshes: select one, right-click, and pick one of the "copy from…" entries.
Open template_no_variants_textured.mesh in WKit. All of the following operations will take place in that file.
Open appearances/default/chunkMaterials
. You need to have one per submesh.
For a more detailed explanation/guide, see the next section. If you don't care, you can skip straight to the next section and fix up the material entries.
chunkMaterials
are where you assign materials by submeshes. The identifier here is the name.
Before changes, the first (and only) submesh will use the material mat_textured
. Our newly imported mesh (the baseball) has two.
Add a new chunkMaterial to the array by either
right-click the existing chunkMaterial and select duplicate
select the array chunkMaterials
and then click the yellow (+) button int he side panel
then change the name of the first entry to mat_ingame
:
You can name your materials whatever you like, as long as you stick to the following rules:
You need one chunk material per submesh
chunkMaterials needs to be in the same order as your submeshes — if you're uncertain, check the "Mesh Preview" tab
The names should be lower case without spaces and special characters. Numbers are fine!
Find the array materialEntries
at the root level of the mesh and open it. It will have two entries:
Select the second entry and change its name to the one from your chunkMaterial (mat_ingame
). Numerical order does not matter here.
MaterialEntries are a lookup map between the material names in the chunkMaterials and the actual materials (see here for an explanation). You can have local or external materials or a mix of both; check this page for an explanation.
Now, we adjust the materials — we'll just change a few properties to show you how it works, and then you can go play.
For another guide on how to edit materials in detail, check here.
Find the array localMaterialBuffer/materials
and open it. It contains two materials. Wolvenkit will display the names corresponding to the material entries so you can see which is which.
For an explanation of material parameters, see this page.
The first one, mat_textured
, is the one that we will use for the seams. If you imported your textures by overwriting the original export, you shouldn't need to do anything here.
Instead, we will change the second material, mat_ingame
.
If you rather want to make your own mlsetups, see here.
Select mat_ingame
Expand the material and its values
array
Delete the parameter MultilayerMask
GlobalNormal: Re-use the same as your textured material (by default: tutorial\amm_props\template\textures\template_01_n.xbm
)
MultilayerSetup: Set it to base\characters\garment\gang_nomad\legs\l1_021_pants__cargo_computer\textures\leather_red_basic.mlsetup
Select mat_ingame
Delete all parameters from the values array
Set the baseMaterial to base\environment\decoration\containers\cases\coffin\textures\m_z_gold.mi
The possibilities are basically endless, so go and explore them already! For a nifty list with materials to get you started, check here. For a guide on creating AMM props, see here.
This section will only cover troubleshooting steps for this guide. For general 3d model troubleshooting (including import errors), see here.
AMM can't find your .ent file. Check the paths in the lua.
This can be one of the following issues:
the path from .ent to .mesh is wrong
the mesh appearance in the .ent file can't be found (check spelling in both .ent and .mesh)
the mesh appearances's chunk materials can't be found (check spelling in the .mesh, both in the chunkMaterial assignments and the CMaterialInstance in localMaterialBuffer.materials
)
Check your mesh's face orientation in Blender — inside-facing meshes are usually transparent.
Check your mesh's chunkmasks in the .ent file: maybe you have accidentally hidden a submesh?
If that doesn't help as well, try assigning a default game material (search for anything ending in .mt and put the path in your material's baseMaterial.DepotPath
).
Try assigning a default game material by searching for
Check the scaling in Blender and make sure that you have applied transformations.
Use engine\textures\editor\normal.xbm
These ones will have a blue normal map as opposed to a yellow one. Invert the blue normal texture before importing it.
In Wolvenkit, open the (Tools -> Export), and export everything in your folder: the mesh(es) you want to use and the textures.
Now that all files are in place, open the in Wolvenkit (Tools -> Import), and re-import the files. The Wolvenkit preview should show your new imported mesh.
optional: You can now and spawn the prop.
Separate (Shortcut: P
) and select "By Material"
Material | name of KeyValuePair | value |
---|---|---|
textured
Normal
your_name\your_prop_pack\baseball\baseball_n01.xbm
BaseColor
your_name\your_prop_pack\baseball\baseball_d01.xbm
mlsetup
GlobalNormal
your_name\your_prop_pack\baseball\baseball_n01.xbm
MultilayerMask
delete it
MultilayerSetup
base\characters\garment\gang_nomad\legs\l1_021_pants__cargo_computer\textures\leather_red_basic.mlsetup