Eevee Wavelength Node Support
This patch adds wavelength node support to Eevee, similar to how Eevee Blackbody node works, thus it is a little off from Cycles. Reviewed By: #eevee_viewport, fclem, brecht Differential Revision: https://developer.blender.org/D11326
This commit is contained in:
parent
b18d5dac53
commit
a43c7538b8
|
@ -143,6 +143,7 @@ MINLINE void rgba_uchar_args_test_set(unsigned char col[4],
|
|||
MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack);
|
||||
|
||||
void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max);
|
||||
void wavelength_to_xyz_table(float *r_table, int width);
|
||||
|
||||
/********* lift/gamma/gain / ASC-CDL conversion ***********/
|
||||
|
||||
|
|
|
@ -713,3 +713,75 @@ void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, fl
|
|||
r_table[i * 4 + 3] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* ****************************** wavelength ******************************** */
|
||||
/* Wavelength to RGB. */
|
||||
|
||||
/* CIE colour matching functions xBar, yBar, and zBar for
|
||||
* wavelengths from 380 through 780 nanometers, every 5
|
||||
* nanometers.
|
||||
* For a wavelength lambda in this range:
|
||||
* cie_colour_match[(lambda - 380) / 5][0] = xBar
|
||||
* cie_colour_match[(lambda - 380) / 5][1] = yBar
|
||||
* cie_colour_match[(lambda - 380) / 5][2] = zBar */
|
||||
|
||||
static float cie_colour_match[81][3] = {
|
||||
{0.0014f, 0.0000f, 0.0065f}, {0.0022f, 0.0001f, 0.0105f}, {0.0042f, 0.0001f, 0.0201f},
|
||||
{0.0076f, 0.0002f, 0.0362f}, {0.0143f, 0.0004f, 0.0679f}, {0.0232f, 0.0006f, 0.1102f},
|
||||
{0.0435f, 0.0012f, 0.2074f}, {0.0776f, 0.0022f, 0.3713f}, {0.1344f, 0.0040f, 0.6456f},
|
||||
{0.2148f, 0.0073f, 1.0391f}, {0.2839f, 0.0116f, 1.3856f}, {0.3285f, 0.0168f, 1.6230f},
|
||||
{0.3483f, 0.0230f, 1.7471f}, {0.3481f, 0.0298f, 1.7826f}, {0.3362f, 0.0380f, 1.7721f},
|
||||
{0.3187f, 0.0480f, 1.7441f}, {0.2908f, 0.0600f, 1.6692f}, {0.2511f, 0.0739f, 1.5281f},
|
||||
{0.1954f, 0.0910f, 1.2876f}, {0.1421f, 0.1126f, 1.0419f}, {0.0956f, 0.1390f, 0.8130f},
|
||||
{0.0580f, 0.1693f, 0.6162f}, {0.0320f, 0.2080f, 0.4652f}, {0.0147f, 0.2586f, 0.3533f},
|
||||
{0.0049f, 0.3230f, 0.2720f}, {0.0024f, 0.4073f, 0.2123f}, {0.0093f, 0.5030f, 0.1582f},
|
||||
{0.0291f, 0.6082f, 0.1117f}, {0.0633f, 0.7100f, 0.0782f}, {0.1096f, 0.7932f, 0.0573f},
|
||||
{0.1655f, 0.8620f, 0.0422f}, {0.2257f, 0.9149f, 0.0298f}, {0.2904f, 0.9540f, 0.0203f},
|
||||
{0.3597f, 0.9803f, 0.0134f}, {0.4334f, 0.9950f, 0.0087f}, {0.5121f, 1.0000f, 0.0057f},
|
||||
{0.5945f, 0.9950f, 0.0039f}, {0.6784f, 0.9786f, 0.0027f}, {0.7621f, 0.9520f, 0.0021f},
|
||||
{0.8425f, 0.9154f, 0.0018f}, {0.9163f, 0.8700f, 0.0017f}, {0.9786f, 0.8163f, 0.0014f},
|
||||
{1.0263f, 0.7570f, 0.0011f}, {1.0567f, 0.6949f, 0.0010f}, {1.0622f, 0.6310f, 0.0008f},
|
||||
{1.0456f, 0.5668f, 0.0006f}, {1.0026f, 0.5030f, 0.0003f}, {0.9384f, 0.4412f, 0.0002f},
|
||||
{0.8544f, 0.3810f, 0.0002f}, {0.7514f, 0.3210f, 0.0001f}, {0.6424f, 0.2650f, 0.0000f},
|
||||
{0.5419f, 0.2170f, 0.0000f}, {0.4479f, 0.1750f, 0.0000f}, {0.3608f, 0.1382f, 0.0000f},
|
||||
{0.2835f, 0.1070f, 0.0000f}, {0.2187f, 0.0816f, 0.0000f}, {0.1649f, 0.0610f, 0.0000f},
|
||||
{0.1212f, 0.0446f, 0.0000f}, {0.0874f, 0.0320f, 0.0000f}, {0.0636f, 0.0232f, 0.0000f},
|
||||
{0.0468f, 0.0170f, 0.0000f}, {0.0329f, 0.0119f, 0.0000f}, {0.0227f, 0.0082f, 0.0000f},
|
||||
{0.0158f, 0.0057f, 0.0000f}, {0.0114f, 0.0041f, 0.0000f}, {0.0081f, 0.0029f, 0.0000f},
|
||||
{0.0058f, 0.0021f, 0.0000f}, {0.0041f, 0.0015f, 0.0000f}, {0.0029f, 0.0010f, 0.0000f},
|
||||
{0.0020f, 0.0007f, 0.0000f}, {0.0014f, 0.0005f, 0.0000f}, {0.0010f, 0.0004f, 0.0000f},
|
||||
{0.0007f, 0.0002f, 0.0000f}, {0.0005f, 0.0002f, 0.0000f}, {0.0003f, 0.0001f, 0.0000f},
|
||||
{0.0002f, 0.0001f, 0.0000f}, {0.0002f, 0.0001f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f},
|
||||
{0.0001f, 0.0000f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, {0.0000f, 0.0000f, 0.0000f}};
|
||||
|
||||
static void wavelength_to_xyz(float xyz[3], float lambda_nm)
|
||||
{
|
||||
float ii = (lambda_nm - 380.0f) * (1.0f / 5.0f); /* Scaled 0..80. */
|
||||
int i = (int)ii;
|
||||
|
||||
if (i < 0 || i >= 80) {
|
||||
xyz[0] = 0.0f;
|
||||
xyz[1] = 0.0f;
|
||||
xyz[2] = 0.0f;
|
||||
}
|
||||
else {
|
||||
ii -= i;
|
||||
const float *c = cie_colour_match[i];
|
||||
xyz[0] = c[0] + ii * (c[3] - c[0]);
|
||||
xyz[1] = c[1] + ii * (c[4] - c[1]);
|
||||
xyz[2] = c[2] + ii * (c[5] - c[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void wavelength_to_xyz_table(float *r_table, int width)
|
||||
{
|
||||
for (int i = 0; i < width; i++) {
|
||||
float temperature = 380 + 400 / (float)width * (float)i;
|
||||
|
||||
float rgb[3];
|
||||
wavelength_to_xyz(rgb, temperature);
|
||||
|
||||
copy_v3_v3(&r_table[i * 4], rgb);
|
||||
r_table[i * 4 + 3] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,6 +275,7 @@ data_to_c_simple(shaders/material/gpu_shader_material_anisotropic.glsl SRC)
|
|||
data_to_c_simple(shaders/material/gpu_shader_material_attribute.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_background.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_bevel.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_wavelength.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_blackbody.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_bright_contrast.glsl SRC)
|
||||
data_to_c_simple(shaders/material/gpu_shader_material_bump.glsl SRC)
|
||||
|
|
|
@ -47,6 +47,7 @@ extern char datatoc_gpu_shader_material_anisotropic_glsl[];
|
|||
extern char datatoc_gpu_shader_material_attribute_glsl[];
|
||||
extern char datatoc_gpu_shader_material_background_glsl[];
|
||||
extern char datatoc_gpu_shader_material_bevel_glsl[];
|
||||
extern char datatoc_gpu_shader_material_wavelength_glsl[];
|
||||
extern char datatoc_gpu_shader_material_blackbody_glsl[];
|
||||
extern char datatoc_gpu_shader_material_bright_contrast_glsl[];
|
||||
extern char datatoc_gpu_shader_material_bump_glsl[];
|
||||
|
@ -191,6 +192,11 @@ static GPUMaterialLibrary gpu_shader_material_bevel_library = {
|
|||
.dependencies = {NULL},
|
||||
};
|
||||
|
||||
static GPUMaterialLibrary gpu_shader_material_wavelength_library = {
|
||||
.code = datatoc_gpu_shader_material_wavelength_glsl,
|
||||
.dependencies = {NULL},
|
||||
};
|
||||
|
||||
static GPUMaterialLibrary gpu_shader_material_blackbody_library = {
|
||||
.code = datatoc_gpu_shader_material_blackbody_glsl,
|
||||
.dependencies = {NULL},
|
||||
|
@ -593,6 +599,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
|
|||
&gpu_shader_material_attribute_library,
|
||||
&gpu_shader_material_background_library,
|
||||
&gpu_shader_material_bevel_library,
|
||||
&gpu_shader_material_wavelength_library,
|
||||
&gpu_shader_material_blackbody_library,
|
||||
&gpu_shader_material_bright_contrast_library,
|
||||
&gpu_shader_material_bump_library,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
void node_wavelength(float wavelength,
|
||||
sampler1DArray spectrummap,
|
||||
float layer,
|
||||
vec3 xyz_to_r,
|
||||
vec3 xyz_to_g,
|
||||
vec3 xyz_to_b,
|
||||
out vec4 color)
|
||||
{
|
||||
mat3 xyz_to_rgb = mat3(xyz_to_r, xyz_to_g, xyz_to_b);
|
||||
float t = (wavelength - 380.0) / (780.0 - 380.0);
|
||||
vec3 xyz = texture(spectrummap, vec2(t, layer)).rgb;
|
||||
vec3 rgb = xyz * xyz_to_rgb;
|
||||
rgb *= 1.0 / 2.52; /* Empirical scale from lg to make all comps <= 1. */
|
||||
color = vec4(clamp(rgb, 0.0, 1.0), 1.0);
|
||||
}
|
|
@ -332,3 +332,17 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data)
|
||||
{
|
||||
const float *xyz_to_rgb = IMB_colormangement_get_xyz_to_rgb();
|
||||
data->r[0] = xyz_to_rgb[0];
|
||||
data->r[1] = xyz_to_rgb[3];
|
||||
data->r[2] = xyz_to_rgb[6];
|
||||
data->g[0] = xyz_to_rgb[1];
|
||||
data->g[1] = xyz_to_rgb[4];
|
||||
data->g[2] = xyz_to_rgb[7];
|
||||
data->b[0] = xyz_to_rgb[2];
|
||||
data->b[1] = xyz_to_rgb[5];
|
||||
data->b[2] = xyz_to_rgb[8];
|
||||
}
|
||||
|
|
|
@ -95,6 +95,11 @@ typedef struct ShaderCallData {
|
|||
int dummy;
|
||||
} ShaderCallData;
|
||||
|
||||
typedef struct XYZ_to_RGB /* Transposed #imbuf_xyz_to_rgb, passed as 3x vec3. */
|
||||
{
|
||||
float r[3], g[3], b[3];
|
||||
} XYZ_to_RGB;
|
||||
|
||||
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
|
||||
|
||||
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns);
|
||||
|
@ -113,6 +118,7 @@ void node_shader_gpu_tex_mapping(struct GPUMaterial *mat,
|
|||
void ntreeExecGPUNodes(struct bNodeTreeExec *exec,
|
||||
struct GPUMaterial *mat,
|
||||
struct bNode *output_node);
|
||||
void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -60,11 +60,6 @@ typedef struct SkyModelPreetham {
|
|||
float radiance[3];
|
||||
} SkyModelPreetham;
|
||||
|
||||
typedef struct XYZ_to_RGB /* transposed imbuf_xyz_to_rgb, passed as 3x vec3 */
|
||||
{
|
||||
float r[3], g[3], b[3];
|
||||
} XYZ_to_RGB;
|
||||
|
||||
static float sky_perez_function(const float *lam, float theta, float gamma)
|
||||
{
|
||||
float ctheta = cosf(theta);
|
||||
|
@ -119,20 +114,6 @@ static void sky_precompute_old(SkyModelPreetham *sunsky, const float sun_angles[
|
|||
sunsky->radiance[2] /= sky_perez_function(sunsky->config_y, 0, theta);
|
||||
}
|
||||
|
||||
static void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data)
|
||||
{
|
||||
const float *xyz_to_rgb = IMB_colormangement_get_xyz_to_rgb();
|
||||
data->r[0] = xyz_to_rgb[0];
|
||||
data->r[1] = xyz_to_rgb[3];
|
||||
data->r[2] = xyz_to_rgb[6];
|
||||
data->g[0] = xyz_to_rgb[1];
|
||||
data->g[1] = xyz_to_rgb[4];
|
||||
data->g[2] = xyz_to_rgb[7];
|
||||
data->b[0] = xyz_to_rgb[2];
|
||||
data->b[1] = xyz_to_rgb[5];
|
||||
data->b[2] = xyz_to_rgb[8];
|
||||
}
|
||||
|
||||
static int node_shader_gpu_tex_sky(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData *UNUSED(execdata),
|
||||
|
|
|
@ -30,6 +30,33 @@ static bNodeSocketTemplate sh_node_wavelength_out[] = {
|
|||
{-1, ""},
|
||||
};
|
||||
|
||||
static int node_shader_gpu_wavelength(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData *UNUSED(execdata),
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
const int size = CM_TABLE + 1;
|
||||
float *data = MEM_mallocN(sizeof(float) * size * 4, "cie_xyz texture");
|
||||
|
||||
wavelength_to_xyz_table(data, size);
|
||||
|
||||
float layer;
|
||||
GPUNodeLink *ramp_texture = GPU_color_band(mat, size, data, &layer);
|
||||
XYZ_to_RGB xyz_to_rgb;
|
||||
get_XYZ_to_RGB_for_gpu(&xyz_to_rgb);
|
||||
return GPU_stack_link(mat,
|
||||
node,
|
||||
"node_wavelength",
|
||||
in,
|
||||
out,
|
||||
ramp_texture,
|
||||
GPU_constant(&layer),
|
||||
GPU_uniform(xyz_to_rgb.r),
|
||||
GPU_uniform(xyz_to_rgb.g),
|
||||
GPU_uniform(xyz_to_rgb.b));
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_wavelength(void)
|
||||
{
|
||||
|
@ -40,6 +67,7 @@ void register_node_type_sh_wavelength(void)
|
|||
node_type_socket_templates(&ntype, sh_node_wavelength_in, sh_node_wavelength_out);
|
||||
node_type_init(&ntype, NULL);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_wavelength);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue