Recreating Dune’s Cinematic Color Grade: A Step-by-Step Guide
Attempting to replicate the atmospheric look of Dune is no small feat, but it offers an exciting challenge for both enthusiasts and professionals to enhance their color grading skills. In this guide, we’ll show you how to recreate a simplified version of Dune’s color grade using free LUTs and plugins. While we aim to honor the original work’s beauty, this process is more about creative exploration than direct imitation.
Understanding Dune’s Color Grading Approach
The visual tone of Dune is defined by a unique hybrid process. The film was shot digitally and printed onto 35mm Vision3 negative, a film stock not traditionally used. This analog-digital workflow resulted in a muted yet textured aesthetic—a hallmark of Dune’s visual identity.
Step-by-Step Guide to Recreate the Dune Color Grade
Step 1: Emulating the Film Negative
Begin with a film emulation LUT to replicate the foundational texture and grain of Dune’s film negative. You can download free LUTs from our website to follow these steps:
- Input Color Space Transformation (CST In)
- Use a Color Space Transform (CST) in DaVinci Resolve to match your camera’s profile (e.g., ARRI Wide Gamut 4).
- Set the output to DaVinci Wide Gamut and DaVinci Intermediate.
- Apply Film Emulation LUT
- Use a LUT like to simulate the negative film. In our case we used our own film emulation LUT's that converts DWG signals into a Cineon-like log image - mimicking hue gamut and transfer functions. We don't provide the LUTs anymore but I'm sure you can still find good emulation LUTs online.
Step 2: Bleach Bypass Effect
Achieve the bleach bypass look—a key aspect of Dune’s tone—using Thatcher Freeman’s free DCTL plugin. Ensure your footage is converted to linear space before applying the effect.
Here's Thatcher Freeman's free DCTL Plugin for bleach bypass emulation: https://github.com/thatcherfreeman/utility-dctls/blob/main/Effects/Bleach%20Bypass.dctl
If you are lazy, and you don't want to setup the bleach bypass DCTL in between linear, I have made a custom DCTL that expects DWG and outputs DWG, this can go right after the film emulation Node. Save the following code with ".dctl" extension and restart resolve.
// Adapted from https://github.com/thatcherfreeman/utility-dctls/blob/main/Effects/Bleach%20Bypass.dctl
// Input: DaVinci Wide Gamut & DaVinci Intermediate
// Output: DaVinci Wide Gamut & DaVinci Intermediate
// clang-format off
DEFINE_UI_PARAMS(saturation, Saturation, DCTLUI_SLIDER_FLOAT, 0.9, 0.0, 1.0, 0.01)
DEFINE_UI_PARAMS(gamma, Gamma, DCTLUI_SLIDER_FLOAT, 1.1, 0.0, 2.0, 0.01)
DEFINE_UI_PARAMS(mid_gray, Middle Gray, DCTLUI_VALUE_BOX, 0.18)
// clang-format on
__DEVICE__ float powf(float base, float exp) {
return _copysignf(_powf(_fabs(base), exp), base);
}
__DEVICE__ float3 bleach_bypass(float3 input, float gamma, float amount) {
float highlight_mixture = input.x + input.y + input.z;
highlight_mixture = powf(highlight_mixture, gamma);
return _mix(input, make_float3(highlight_mixture, highlight_mixture, highlight_mixture), amount);
}
__DEVICE__ float dwg_to_linear(float x) {
const float DI_A = 0.0075f;
const float DI_B = 7.0f;
const float DI_C = 0.07329248f;
const float DI_M = 10.44426855f;
const float DI_LOG_CUT = 0.02740668f;
if (x > DI_LOG_CUT) {
return _powf(2.0f, (x / DI_C) - DI_B) - DI_A;
} else {
return x / DI_M;
}
}
__DEVICE__ float linear_to_dwg(float x) {
const float DI_A = 0.0075f;
const float DI_B = 7.0f;
const float DI_C = 0.07329248f;
const float DI_M = 10.44426855f;
const float DI_LIN_CUT = 0.00262409f;
if (x > DI_LIN_CUT) {
return ((_log2f(x + DI_A) + DI_B) * DI_C);
} else {
return x * DI_M;
}
}
__DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) {
float3 curr_color = make_float3(p_R, p_G, p_B);
//to linear
curr_color.x = dwg_to_linear(curr_color.x);
curr_color.y = dwg_to_linear(curr_color.y);
curr_color.z = dwg_to_linear(curr_color.z);
float3 bleach_bypass_color = bleach_bypass(curr_color, gamma, 1.0 - saturation);
// Correct mid gray.
float3 gain =
make_float3(mid_gray, mid_gray, mid_gray) / (bleach_bypass(make_float3(mid_gray, mid_gray, mid_gray), gamma, 1.0 - saturation));
bleach_bypass_color *= gain;
// to DWG
bleach_bypass_color.x = linear_to_dwg(bleach_bypass_color.x);
bleach_bypass_color.y = linear_to_dwg(bleach_bypass_color.y);
bleach_bypass_color.z = linear_to_dwg(bleach_bypass_color.z);
return bleach_bypass_color;
}
Step 3: Split Toning with a Custom Gradient
Mimic Dune’s signature split toning:
- Analyze highlights and shadows to create a 12-step gradient using a Python script.
- Apply this gradient in DaVinci Resolve using the RGB Lift Gamma Gain Tool available in the Lookdev Plugins.
#Split Analyzer - written by Jaideep Panjwani
from PIL import Image
import numpy as np
import os
# Place folder path here
folder_path = "/content/Dune Stills"
# Initialize lists to store the RGB values of the darkest and brightest pixels across all images
all_darkest_rgb_values = []
all_brightest_rgb_values = []
# Loop through all images in the folder
for file_name in os.listdir(folder_path):
if file_name.endswith((".jpg", ".jpeg", ".png")):
img_path = os.path.join(folder_path, file_name)
with Image.open(img_path) as img:
img = img.convert('RGB')
img_array = np.array(img)
min_quantile = np.quantile(img_array, 0.02)
max_quantile = np.quantile(img_array, 0.98)
darkest_pixels = np.where(img_array <= min_quantile)
brightest_pixels = np.where(img_array >= max_quantile)
darkest_rgb_values = img_array[darkest_pixels[0], darkest_pixels[1], :].mean(axis=0)
brightest_rgb_values = img_array[brightest_pixels[0], brightest_pixels[1], :].mean(axis=0)
all_darkest_rgb_values.append(darkest_rgb_values)
all_brightest_rgb_values.append(brightest_rgb_values)
average_darkest_rgb = np.mean(all_darkest_rgb_values, axis=0).astype(np.uint8)
average_brightest_rgb = np.mean(all_brightest_rgb_values, axis=0).astype(np.uint8)
final_width, final_height = 3840, 2160
# Number of steps
num_steps = 12
step_gradients = np.linspace(average_darkest_rgb, average_brightest_rgb, num_steps).astype(np.uint8)
step_width = final_width // num_steps
final_gradient = np.zeros((final_height, final_width, 3), dtype=np.uint8)
for i in range(num_steps):
final_gradient[:, i*step_width:(i+1)*step_width] = step_gradients[i]
gradient_img = Image.fromarray(final_gradient, mode='RGB')
gradient_img_path = "average_shadow_to_highlight.jpg"
gradient_img.save(gradient_img_path)
gradient_img_path, average_darkest_rgb, average_brightest_rgb
Step 4: Compressing Hues
To match Dune’s muted yet rich palette: Use the Filmblade LCH Tetra DCTL plugin to compress hues for a cohesive color scheme
Here's the basic look development tool kit (Filmblade LCH Tetra DCTL & RGB_LGGO DCTLs) that uses tetra transformations to manipulate hue - this is adapted from various tools floating online with minor modifications.
Step 5: Final Adjustments & Exporting LUTs
Fine-tune exposure and color, then export the look as LUTs for use in DaVinci Resolve, Premiere Pro, or Final Cut Pro.
Step 6: Testing on Original Footage
Apply the LUTs to Dune-style shots to evaluate the results. While this process won’t replicate the intricate precision of the original team’s work, it provides a visually similar aesthetic.
Free Resources: Download LUTs & Plugins
I have gone through the above steps and created final LUTs for this. Hope these help :)
A Homage to Cinematic Color Grading
I hope this exploration inspires you to delve into the nuanced world of color grading and to appreciate the meticulous craftsmanship that goes into creating the visual tone of a film like “Dune.” Remember, this journey into color grading is about understanding and appreciation, not just imitation. By exploring these techniques and applying them to your work, you embark on a path of learning and creative growth. Subscribe to our channel and follow us on Instagram at @coloristfoundry for more insights into the art and science of color grading. Until next time, happy grading!