MDL SDK API nvidia_logo_transpbg.gif Up
Example for Execution of Compiled MDL Materials (CPU)
[Previous] [Up] [Next]

This example shows how a renderer can call the code generated by the "native" backend for compiled materials to evaluate sub-expressions of multiple materials on the CPU.

New Topics

  • MDL material state (CPU)
  • Execution of generated code (CPU)
  • Texture handling

Detailed Description

MDL material state (CPU)


The MDL material state structure mi::neuraylib::Shading_state_material is a representation of the renderer state as defined in section 19 "Renderer state" in the MDL specification. It is used to make the state of the renderer (like the position of an intersection point on the surface, the shading normal and the texture coordinates) available to the generated code.

Here's the material state structure just for reference:

tct_float3 normal; // state::normal() result
tct_float3 geom_normal; // state::geom_normal() result
tct_float3 position; // state::position() result
tct_float animation_time; // state::animation_time() result
const tct_float3 *text_coords; // state::texture_coordinate() table
const tct_float3 *tangent_u; // state::texture_tangent_u() table
const tct_float3 *tangent_v; // state::texture_tangent_v() table
tct_float4 *text_results; // texture results lookup table
const char *ro_data_segment; // read-only data segment
const tct_float4 *world_to_object; // world-to-object transform matrix
const tct_float4 *object_to_world; // object-to-world transform matrix
tct_int object_id; // state::object_id() result
};
mi::Float32_3_struct tct_float3
A float3.
Definition: target_code_types.h:77
struct Shading_state_material_impl<false> Shading_state_material
The MDL material state structure.
Definition: target_code_types.h:300
mi::Float32_4_struct tct_float4
A float4.
Definition: target_code_types.h:80
mi::Sint32 tct_int
An int.
Definition: target_code_types.h:83
float tct_float
A float.
Definition: target_code_types.h:71

Please refer to the structure documentation for more information.

In this example, we fill the material state structure with some example values and only use one texture space. For the world-to-object and object-to-world transformation matrices we use identity matrices. We will iterate the position and text_coords fields over a 2x2 quad around the center of the world with position x and y coordinates ranging from -1 to 1 and the texture uv-coordinates ranging from 0 to 1, respectively.

Execution of generated code (CPU)


For the native (CPU) backend, filling this structure is actually already enough to prepare the execution of the generated code. Calling mi::neuraylib::ITarget_code::execute() with the material state and a sufficiently large result buffer will fill the buffer with the requested result. In this example, we will provide a NULL pointer as a target argument block. For instance compilation, the target argument block parameter is not used, and for class compilation, providing a NULL pointer will result in the default target argument block for the used material instance. See Instance-compilation and class-compilation for more details about compilation modes.

In this example, we bake a sub-expression of a material into a texture by executing the generated code for every texel updating the material state accordingly. At the end, we write the texture to disk.

Texture handling


Per default, the MDL SDK provides a built-in runtime which handles texture access functions (texture lookups etc.). In some situations, you may however want to provide your own implementation. This requires you to disable the built-in texture handler by setting the mi::neuraylib::IMdl_backend option use_builtin_resource_handler to "off" (via mi::neuraylib::IMdl_backend::set_option()). It also requires you to implement the following functions:

  • tex_lookup_float4_2d
  • tex_lookup_float3_2d
  • tex_texel_float4_2d
  • tex_lookup_float4_3d
  • tex_lookup_float3_3d
  • tex_texel_float4_3d
  • tex_lookup_float4_cube
  • tex_lookup_float3_cube
  • tex_resolution_2d

Except for the last one, these functions correspond directly to the functions described in section 20.3 "Standard library functions - Texture" in the MDL specification.

You pass your functions to the MDL SDK via an instance of the struct mi::neuraylib::Texture_handler_base when calling any of the mi::neuraylib::ITarget_code::execute*() functions. The mi::neuraylib::Texture_handler_base has a vtable parameter which contains function pointers matching the signature of the required functions. These function pointers need to point to your functions.

An example implementation (limited to 2D texture lookups for now) can be found in texture_support.h. To switch example_execution_native to the custom texturing code, please disable the define USE_BUILTIN_TEXTURE_RUNTIME on top of example_execution_native.cpp.

Example Source

Source Code Location: examples/mdl_sdk/execution_native/example_execution_native.cpp

/******************************************************************************
* Copyright 2024 NVIDIA Corporation. All rights reserved.
*****************************************************************************/
// examples/mdl_sdk/execution_native/example_execution_native.cpp
//
// Introduces the execution of generated code for compiled materials for
// the native (CPU) backend and shows how to manually bake a material
// sub-expression to a texture.
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "example_shared.h"
#include "texture_support_native.h"
// Command line options structure.
struct Options {
// An result output file name.
std::string outputfile;
// The resolution of the display / image.
unsigned res_x, res_y;
// Whether class compilation should be used for the materials.
bool use_class_compilation;
// Whether the custom texture runtime should be used.
bool use_custom_tex_runtime;
// Whether derivative support should be enabled.
// This example does not support derivatives in combination with the custom texture runtime.
bool enable_derivatives;
// Material to use.
std::string material_name;
Options()
: outputfile("example_native.png")
, res_x(700)
, res_y(520)
, use_class_compilation(false)
, use_custom_tex_runtime(false)
, enable_derivatives(false)
{}
};
// The last row is always implied to be (0, 0, 0, 1).
const mi::Float32_3_4 identity(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f
);
// Creates an instance of the given material.
void create_material_instance(
const char* material_name,
const char* instance_name)
{
// split module and material name
std::string module_name, material_simple_name;
if (!mi::examples::mdl::parse_cmd_argument_material_name(
material_name, module_name, material_simple_name, true))
exit_failure();
// Load the module.
mdl_impexp_api->load_module(transaction, module_name.c_str(), context);
if (!print_messages(context))
exit_failure("Loading module '%s' failed.", module_name.c_str());
// Get the database name for the module we loaded
mdl_factory->get_db_module_name(module_name.c_str()));
transaction->access<mi::neuraylib::IModule>(module_db_name->get_c_str()));
if (!module)
exit_failure("Failed to access the loaded module.");
// Attach the material name
std::string material_db_name
= std::string(module_db_name->get_c_str()) + "::" + material_simple_name;
material_db_name = mi::examples::mdl::add_missing_material_signature(
module.get(), material_db_name);
if (material_db_name.empty())
exit_failure("Failed to find the material %s in the module %s.",
material_simple_name.c_str(), module_name.c_str());
// Get the material definition from the database
transaction->access<mi::neuraylib::IFunction_definition>(material_db_name.c_str()));
if (!material_definition)
exit_failure("Accessing definition '%s' failed.", material_db_name.c_str());
// Create a material instance from the material definition with the default arguments.
mi::Sint32 result;
material_definition->create_function_call(0, &result));
if (result != 0)
exit_failure("Instantiating '%s' failed.", material_db_name.c_str());
transaction->store(material_instance.get(), instance_name);
}
// Compiles the given material instance in the given compilation modes and stores it in the DB.
void compile_material_instance(
const char* instance_name,
const char* compiled_material_name,
bool class_compilation)
{
transaction->access<mi::neuraylib::IMaterial_instance>(instance_name));
mi::Uint32 flags = class_compilation
// convert to target type SID_MATERIAL
mdl_factory->create_type_factory(transaction));
tf->get_predefined_struct(mi::neuraylib::IType_struct::SID_MATERIAL));
context->set_option("target_type", standard_material_type.get());
material_instance->create_compiled_material(flags, context));
check_success(print_messages(context));
transaction->store(compiled_material.get(), compiled_material_name);
}
// Generate and execute native CPU code for a subexpression of a given compiled material.
mi::neuraylib::ITarget_code const *generate_native(
const char* compiled_material_name,
const char* path,
const char* fname,
bool use_custom_tex_runtime,
bool enable_derivatives)
{
transaction->access<mi::neuraylib::ICompiled_material>(compiled_material_name));
check_success(be_native->set_option("num_texture_spaces", "1") == 0);
if (use_custom_tex_runtime)
check_success(be_native->set_option("use_builtin_resource_handler", "off") == 0);
if (enable_derivatives)
check_success(be_native->set_option("texture_runtime_with_derivs", "on") == 0);
// Generate the native code
be_native->translate_material_expression(
transaction, compiled_material.get(), path, fname, context));
check_success(print_messages(context));
check_success(code_native);
code_native->retain();
return code_native.get();
}
// Bake the material expression created with the native backend into a canvas with the given
// resolution.
mi::neuraylib::ICanvas *bake_expression_native(
mi::neuraylib::ITarget_code const *code_native,
mi::Uint32 width,
mi::Uint32 height)
{
// Create a canvas (with only one tile)
image_api->create_canvas("Rgb_fp", width, height));
// Setup MDL material state (with only one texture space)
mi::Float32_3_struct texture_coords[1] = { { 0.0f, 0.0f, 0.0f } };
mi::Float32_3_struct texture_tangent_u[1] = { { 1.0f, 0.0f, 0.0f } };
mi::Float32_3_struct texture_tangent_v[1] = { { 0.0f, 1.0f, 0.0f } };
/*normal=*/ { 0.0f, 0.0f, 1.0f },
/*geom_normal=*/ { 0.0f, 0.0f, 1.0f },
/*position=*/ { 0.0f, 0.0f, 0.0f },
/*animation_time=*/ 0.0f,
/*texture_coords=*/ texture_coords,
/*tangent_u=*/ texture_tangent_u,
/*tangent_v=*/ texture_tangent_v,
/*text_results=*/ nullptr,
/*ro_data_segment=*/ nullptr,
/*world_to_object=*/ &identity[0],
/*object_to_world=*/ &identity[0],
/*object_id=*/ 0,
/*meters_per_scene_unit=*/ 1.0f
};
// Provide a large enough buffer for any result type.
// In this case, we know, we will get a color which is a float3, so this is overkill.
union
{
int int_val;
float float_val;
double double_val;
mi::Float32_4_4_struct float4x4_val;
mi::Float64_3_struct double3_val;
mi::Float64_4_struct double4_val;
mi::Float64_4_4_struct double4x4_val;
} execute_result = { 0 };
// Calculate all expression values for a 2x2 quad around the center of the world
// and write them to the canvas.
mi::base::Handle<mi::neuraylib::ITile> tile(canvas->get_tile());
mi::Float32_3_struct *data = static_cast<mi::Float32_3_struct *>(tile->get_data());
for (mi::Uint32 y = 0; y < height; ++y) {
for (mi::Uint32 x = 0; x < width; ++x) {
// Update state for the current pixel
float rel_x = float(x) / float(width);
float rel_y = float(y) / float(height);
mdl_state.position.x = 2.0f * rel_x - 1; // [-1, 1)
mdl_state.position.y = 2.0f * rel_y - 1; // [-1, 1)
texture_coords[0].x = rel_x; // [0, 1)
texture_coords[0].y = rel_y; // [0, 1)
// Evaluate sub-expression
check_success(
code_native->execute(0, mdl_state, tex_handler, nullptr, &execute_result) == 0);
// Apply gamma correction
execute_result.float3_val.x = powf(execute_result.float3_val.x, 1.f / 2.2f);
execute_result.float3_val.y = powf(execute_result.float3_val.y, 1.f / 2.2f);
execute_result.float3_val.z = powf(execute_result.float3_val.z, 1.f / 2.2f);
// Store result in texture
data[y * width + x] = execute_result.float3_val;
}
}
canvas->retain();
return canvas.get();
}
// Bake the material expression created with the native backend into a canvas with the given
// resolution with derivative support.
mi::neuraylib::ICanvas *bake_expression_native_with_derivs(
mi::neuraylib::ITarget_code const *code_native,
mi::Uint32 width,
mi::Uint32 height)
{
// Create a canvas
image_api->create_canvas("Rgb_fp", width, height));
// Setup MDL material state (with only one texture space)
float step_x = 1.f / width;
float step_y = 1.f / height;
mi::neuraylib::tct_deriv_float3 texture_coords[1] = {
{
{ 0.0f, 0.0f, 0.0f }, // value component
{ step_x, 0.0f, 0.0f }, // dx component
{ 0.0f, step_y, 0.0f } // dy component
} };
mi::neuraylib::tct_float3 texture_tangent_u[1] = { { 1.0f, 0.0f, 0.0f } };
mi::neuraylib::tct_float3 texture_tangent_v[1] = { { 0.0f, 1.0f, 0.0f } };
/*normal=*/ { 0.0f, 0.0f, 1.0f },
/*geom_normal=*/ { 0.0f, 0.0f, 1.0f },
/*position=*/
{
{ 0.0f, 0.0f, 0.0f }, // value component
{ 2 * step_x, 0.0f, 0.0f }, // dx component
{ 0.0f, 2 * step_y, 0.0f } // dy component
},
/*animation_time=*/ 0.0f,
/*texture_coords=*/ texture_coords,
/*tangent_u=*/ texture_tangent_u,
/*tangent_v=*/ texture_tangent_v,
/*text_results=*/ nullptr,
/*ro_data_segment=*/ nullptr,
/*world_to_object=*/ &identity[0],
/*object_to_world=*/ &identity[0],
/*object_id=*/ 0,
/*meters_per_scene_unit=*/ 1.0f
};
// Provide a large enough buffer for any result type.
// In this case, we know, we will get a color which is a float3, so this is overkill.
union
{
int int_val;
float float_val;
double double_val;
mi::Float32_4_4_struct float4x4_val;
mi::Float64_3_struct double3_val;
mi::Float64_4_struct double4_val;
mi::Float64_4_4_struct double4x4_val;
} execute_result = { 0 };
// Calculate all expression values for a 2x2 quad around the center of the world
// and write them to the canvas.
mi::base::Handle<mi::neuraylib::ITile> tile(canvas->get_tile());
mi::Float32_3_struct *data = static_cast<mi::Float32_3_struct *>(tile->get_data());
for (mi::Uint32 y = 0; y < height; ++y) {
for (mi::Uint32 x = 0; x < width; ++x) {
// Update state for the current pixel
float rel_x = x * step_x;
float rel_y = y * step_y;
mdl_state.position.val.x = 2.0f * rel_x - 1; // [-1, 1)
mdl_state.position.val.y = 2.0f * rel_y - 1; // [-1, 1)
texture_coords[0].val.x = rel_x; // [0, 1)
texture_coords[0].val.y = rel_y; // [0, 1)
// Evaluate sub-expression
check_success(code_native->execute(
0,
reinterpret_cast<mi::neuraylib::Shading_state_material &>(mdl_state),
reinterpret_cast<mi::neuraylib::Texture_handler_base *>(tex_handler),
nullptr,
&execute_result) == 0);
// Apply gamma correction
execute_result.float3_val.x = powf(execute_result.float3_val.x, 1.f / 2.2f);
execute_result.float3_val.y = powf(execute_result.float3_val.y, 1.f / 2.2f);
execute_result.float3_val.z = powf(execute_result.float3_val.z, 1.f / 2.2f);
// Store result in texture
data[y * width + x] = execute_result.float3_val;
}
}
canvas->retain();
return canvas.get();
}
// Prepare the textures for our own texture runtime.
bool prepare_textures(
std::vector<Texture>& textures,
const mi::neuraylib::ITarget_code* target_code)
{
for (mi::Size i = 1 /*skip invalid texture*/; i < target_code->get_texture_count(); ++i)
{
transaction->access<const mi::neuraylib::ITexture>(
target_code->get_texture(i)));
transaction->access<mi::neuraylib::IImage>(texture->get_image()));
mi::base::Handle<const mi::neuraylib::ICanvas> canvas(image->get_canvas(0, 0, 0));
char const *image_type = image->get_type(0, 0);
if (image->is_uvtile() || image->is_animated()) {
std::cerr << "The example does not support uvtile and/or animated textures!" << std::endl;
return false;
}
// For simplicity, the texture access functions are only implemented for float4 and gamma
// is pre-applied here (all images are converted to linear space).
// Convert to linear color space if necessary
if (texture->get_effective_gamma(0, 0) != 1.0f) {
// Copy/convert to float4 canvas and adjust gamma from "effective gamma" to 1.
image_api->convert(canvas.get(), "Color"));
gamma_canvas->set_gamma(texture->get_effective_gamma(0, 0));
image_api->adjust_gamma(gamma_canvas.get(), 1.0f);
canvas = gamma_canvas;
}
else if (strcmp(image_type, "Color") != 0 && strcmp(image_type, "Float32<4>") != 0) {
// Convert to expected format
canvas = image_api->convert(canvas.get(), "Color");
}
textures.push_back(Texture(canvas));
}
return true;
}
// Print command line usage to console and terminate the application.
void usage(char const *prog_name)
{
std::cout
<< "Usage: " << prog_name << " [options] [<material_name>]\n"
<< "Options:\n"
<< " --res <x> <y> resolution (default: 700x520)\n"
<< " --cc use class compilation\n"
<< " --cr use custom texture runtime\n"
<< " -d enable use of derivatives\n"
<< " (not supported in combination with --cr by this example)\n"
<< " -o <outputfile> image file to write result to\n"
<< " (default: example_native.png)\n"
<< " -p|--mdl_path <path> mdl search path, can occur multiple times\n"
<< std::endl;
exit_failure();
}
//------------------------------------------------------------------------------
//
// Main function
//
//------------------------------------------------------------------------------
int MAIN_UTF8(int argc, char *argv[])
{
// Parse command line options
Options options;
mi::examples::mdl::Configure_options configure_options;
configure_options.add_example_search_path = false;
for (int i = 1; i < argc; ++i) {
char const *opt = argv[i];
if (opt[0] == '-') {
if (strcmp(opt, "-o") == 0 && i < argc - 1) {
options.outputfile = argv[++i];
} else if (strcmp(opt, "--res") == 0 && i < argc - 2) {
options.res_x = std::max(atoi(argv[++i]), 1);
options.res_y = std::max(atoi(argv[++i]), 1);
} else if (strcmp(opt, "--cc") == 0) {
options.use_class_compilation = true;
} else if (strcmp(opt, "--cr") == 0) {
options.use_custom_tex_runtime = true;
} else if (strcmp(opt, "-d") == 0) {
options.enable_derivatives = true;
} else if ((strcmp(opt, "--mdl_path") == 0 || strcmp(opt, "-p") == 0)
&& i < argc - 1) {
configure_options.additional_mdl_paths.push_back(argv[++i]);
} else {
std::cout << "Unknown option: \"" << opt << "\"" << std::endl;
usage(argv[0]);
}
} else
options.material_name = opt;
}
// Use default material, if none was provided via command line
if (options.material_name.empty()) {
configure_options.add_example_search_path = true;
options.material_name = "::nvidia::sdk_examples::tutorials::example_execution1";
}
// Access the MDL SDK
mi::base::Handle<mi::neuraylib::INeuray> neuray(mi::examples::mdl::load_and_get_ineuray());
if (!neuray.is_valid_interface())
exit_failure("Failed to load the SDK.");
// Configure the MDL SDK
if (!mi::examples::mdl::configure(neuray.get(), configure_options))
exit_failure("Failed to initialize the SDK.");
// Start the MDL SDK
mi::Sint32 ret = neuray->start();
if (ret != 0)
exit_failure("Failed to initialize the SDK. Result code: %d", ret);
{
// Create a transaction
neuray->get_api_component<mi::neuraylib::IDatabase>());
mi::base::Handle<mi::neuraylib::IScope> scope(database->get_global_scope());
mi::base::Handle<mi::neuraylib::ITransaction> transaction(scope->create_transaction());
{
neuray->get_api_component<mi::neuraylib::IMdl_factory>());
neuray->get_api_component<mi::neuraylib::IMdl_impexp_api>());
neuray->get_api_component<mi::neuraylib::IMdl_backend_api>());
mdl_factory->create_execution_context());
// Load the MDL module and create a material instance
std::string instance_name = "material instance";
create_material_instance(
mdl_factory.get(),
transaction.get(),
mdl_impexp_api.get(),
context.get(),
options.material_name.c_str(),
instance_name.c_str());
// Compile the material instance in instance compilation mode
std::string instance_compilation_name
= std::string("instance compilation of ") + instance_name;
// Compile the material instance
std::string compilation_name
= std::string("compilation of ") + instance_name;
compile_material_instance(
mdl_factory.get(),
transaction.get(),
context.get(),
instance_name.c_str(),
compilation_name.c_str(),
options.use_class_compilation);
// Generate target code for some material expression
generate_native(
transaction.get(),
mdl_backend_api.get(),
context.get(),
compilation_name.c_str(),
"surface.scattering.tint", // MDL expression path
"tint", // name of generated function
options.use_custom_tex_runtime,
options.enable_derivatives));
// Acquire image API needed to create a canvas for baking
neuray->get_api_component<mi::neuraylib::IImage_api>());
std::vector<Texture> textures;
if (options.use_custom_tex_runtime) {
// Setup custom texture handler
check_success(prepare_textures(
textures, transaction.get(), image_api.get(), target_code.get()));
}
// Bake the expression into a canvas
if (options.enable_derivatives) {
Texture_handler_deriv tex_handler;
Texture_handler_deriv *tex_handler_ptr = nullptr;
if (options.use_custom_tex_runtime) {
tex_handler.vtable = &tex_deriv_vtable;
tex_handler.num_textures = target_code->get_texture_count() - 1;
tex_handler.textures = textures.data();
tex_handler_ptr = &tex_handler;
}
canvas = bake_expression_native_with_derivs(
image_api.get(), target_code.get(), tex_handler_ptr,
options.res_x, options.res_y);
} else {
Texture_handler tex_handler;
Texture_handler *tex_handler_ptr = nullptr;
if (options.use_custom_tex_runtime) {
tex_handler.vtable = &tex_vtable;
tex_handler.num_textures = target_code->get_texture_count() - 1;
tex_handler.textures = textures.data();
tex_handler_ptr = &tex_handler;
}
canvas = bake_expression_native(
image_api.get(), target_code.get(), tex_handler_ptr,
options.res_x, options.res_y);
}
// Export the canvas to an image on disk
mdl_impexp_api->export_canvas(options.outputfile.c_str(), canvas.get());
}
transaction->commit();
}
// Shut down the MDL SDK
if (neuray->shutdown() != 0)
exit_failure("Failed to shutdown the SDK.");
// Unload the MDL SDK
neuray = nullptr;
if (!mi::examples::mdl::unload())
exit_failure("Failed to unload the SDK.");
exit_success();
}
// Convert command line arguments to UTF8 on Windows
COMMANDLINE_TO_UTF8
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113
NxM-dimensional matrix class template of fixed dimensions.
Definition: matrix.h:367
Abstract interface for a canvas represented by a rectangular array of tiles.
Definition: icanvas.h:89
This interface represents a compiled material.
Definition: icompiled_material.h:97
This interface is used to interact with the distributed database.
Definition: idatabase.h:289
This interface represents a function definition.
Definition: ifunction_definition.h:44
This interface provides various utilities related to canvases and buffers.
Definition: iimage_api.h:72
virtual ICanvas * create_canvas(const char *pixel_type, Uint32 width, Uint32 height, Uint32 layers=1, bool is_cubemap=false, Float32 gamma=0.0f) const =0
Creates a canvas with given pixel type, resolution, and layers.
virtual ITile * convert(const ITile *tile, const char *pixel_type) const =0
Converts a tile to a different pixel type.
virtual void adjust_gamma(ITile *tile, Float32 old_gamma, Float32 new_gamma) const =0
Sets the gamma value of a tile and adjusts the pixel data accordingly.
This interface represents a pixel image file.
Definition: iimage.h:66
This interface represents a material instance.
Definition: imaterial_instance.h:34
@ CLASS_COMPILATION
Selects class compilation instead of instance compilation.
Definition: imaterial_instance.h:41
@ DEFAULT_OPTIONS
Default compilation options (e.g., instance compilation).
Definition: imaterial_instance.h:40
This interface can be used to obtain the MDL backends.
Definition: imdl_backend_api.h:56
@ MB_NATIVE
Generate native code.
Definition: imdl_backend_api.h:64
virtual IMdl_backend * get_backend(Mdl_backend_kind kind)=0
Returns an MDL backend generator.
The execution context can be used to query status information like error and warning messages concern...
Definition: imdl_execution_context.h:131
virtual Sint32 set_option(const char *name, const char *value)=0
Sets a string option.
Factory for various MDL interfaces and functions.
Definition: imdl_factory.h:53
virtual IMdl_execution_context * create_execution_context()=0
Creates an execution context.
virtual IType_factory * create_type_factory(ITransaction *transaction)=0
Returns an MDL type factory for the given transaction.
virtual const IString * get_db_module_name(const char *mdl_name)=0
Returns the DB name for the MDL name of a module (or file path for MDLE modules).
API component for MDL related import and export operations.
Definition: imdl_impexp_api.h:43
virtual Sint32 export_canvas(const char *filename, const ICanvas *canvas, const IMap *export_options=0) const =0
Exports a canvas to a file on disk.
virtual Sint32 load_module(ITransaction *transaction, const char *argument, IMdl_execution_context *context=0)=0
Loads an MDL module from disk (or a builtin module) into the database.
This interface represents an MDL module.
Definition: imodule.h:634
Represents target code of an MDL backend.
Definition: imdl_backend.h:783
Textures add image processing options to images.
Definition: itexture.h:68
A transaction provides a consistent view on the database.
Definition: itransaction.h:82
virtual const base::IInterface * access(const char *name)=0
Retrieves an element from the database.
virtual Sint32 commit()=0
Commits the transaction.
virtual Sint32 store(base::IInterface *db_element, const char *name, Uint8 privacy=LOCAL_SCOPE)=0
Stores the element db_element in the database under the name name and with the privacy level privacy.
@ SID_MATERIAL
The "::material" struct type.
Definition: itype.h:484
Interface * get() const
Access to the interface. Returns 0 for an invalid interface.
Definition: handle.h:294
unsigned int Uint32
32-bit unsigned integer.
Definition: types.h:49
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
signed int Sint32
32-bit signed integer.
Definition: types.h:46
virtual Sint32 execute(Size index, const Shading_state_material &state, Texture_handler_base *tex_handler, const ITarget_argument_block *cap_args, void *result) const =0
Run this code on the native CPU with the given captured arguments block.
virtual const char * get_texture(Size index) const =0
Returns the name of a texture resource used by the target code.
tct_traits<true>::tct_derivable_float3 tct_deriv_float3
A float3 with derivatives.
Definition: target_code_types.h:132
virtual Size get_texture_count() const =0
Returns the number of texture resources used by the target code.
Storage class for a NxM-dimensional matrix class template of fixed dimensions.
Definition: matrix.h:90
Generic storage class template for math vector representations storing DIM elements of type T.
Definition: vector.h:135
The MDL material state structure inside the MDL SDK is a representation of the renderer state as defi...
Definition: target_code_types.h:210
traits::tct_derivable_float3 position
The result of state::position().
Definition: target_code_types.h:225
The texture handler structure that is passed to the texturing functions.
Definition: target_code_types.h:712
The texture handler structure that is passed to the texturing functions with derivative support.
Definition: target_code_types.h:721
Texture_handler_deriv_vtable const * vtable
In vtable-mode, the vtable field is used to call the texturing functions.
Definition: target_code_types.h:724

Source Code Location: examples/mdl_sdk/shared/texture_support_native.h

/******************************************************************************
* Copyright 2024 NVIDIA Corporation. All rights reserved.
*****************************************************************************/
// This file contains the implementations and the vtable of the texture access functions.
#ifndef TEXTURE_SUPPORT_H
#define TEXTURE_SUPPORT_H
#include "example_shared.h"
#define USE_SMOOTHERSTEP_FILTER
typedef mi::neuraylib::Texture_handler_base Texture_handler_base;
typedef mi::neuraylib::Texture_handler_deriv_base Texture_handler_deriv_base;
// Custom structure representing an MDL texture
struct Texture
{
: canvas(c)
, ncomp(4)
{
// for now, we only support floating point rgba
check_success(strcmp(canvas->get_type(), "Color") == 0);
size.x = canvas->get_resolution_x();
size.y = canvas->get_resolution_y();
size.z = canvas->get_layers_size();
data = static_cast<const mi::Float32*> (tile->get_data());
}
mi::Float32 const *data; // texture data for fast access
mi::Uint32_3_struct size; // size of the texture
mi::Uint32 ncomp; // components per pixel
};
// The texture handler structure required by the MDL SDK with custom additional fields.
struct Texture_handler : Texture_handler_base {
// additional data for the texture access functions can be provided here
size_t num_textures; // the number of textures used by the material
// (without the invalid texture)
Texture const *textures; // the textures used by the material
// (without the invalid texture)
};
// The texture handler structure required by the MDL SDK with custom additional fields.
struct Texture_handler_deriv : Texture_handler_deriv_base {
// additional data for the texture access functions can be provided here
size_t num_textures; // the number of textures used by the material
// (without the invalid texture)
Texture const *textures; // the textures used by the material
// (without the invalid texture)
};
// Stores a float4 in a float[4] array.
inline static void store_result4(float res[4], const mi::Float32_4_struct &v)
{
res[0] = v.x;
res[1] = v.y;
res[2] = v.z;
res[3] = v.w;
}
// Stores a float in all elements of a float[4] array.
static inline void store_result4(float res[4], const float v)
{
res[0] = res[1] = res[2] = res[3] = v;
}
// Stores the given float values in a float[4] array.
static inline void store_result4(
float res[4], const float v0, const float v1, const float v2, const float v3)
{
res[0] = v0;
res[1] = v1;
res[2] = v2;
res[3] = v3;
}
// Stores a float4 in a float[3] array, ignoring v.w.
static inline void store_result3(float res[3], const mi::Float32_4_struct &v)
{
res[0] = v.x;
res[1] = v.y;
res[2] = v.z;
}
// Stores a float in all elements of a float[3] array.
static inline void store_result3(float res[3], const float v)
{
res[0] = res[1] = res[2] = v;
}
// Stores the given float values in a float[3] array.
static inline void store_result3(float res[3], const float v0, const float v1, const float v2)
{
res[0] = v0;
res[1] = v1;
res[2] = v2;
}
// ------------------------------------------------------------------------------------------------
// Textures
// ------------------------------------------------------------------------------------------------
static inline mi::Float32 u2f_rn(const mi::Uint32 u) {
return (mi::Float32) u;
}
static inline mi::Uint32 f2u_rz(const mi::Float32 f) {
return (mi::Uint32) f;
}
static inline mi::Sint64 f2ll_rz(const mi::Float32 f) {
return (mi::Sint64) f;
}
static inline mi::Sint64 f2ll_rd(const mi::Float32 f) {
}
mi::Uint32 texremap(
mi::Uint32 tex_size, Tex_wrap_mode wrap_mode, const mi::Sint32 crop_offset, float texf)
{
mi::Sint32 texi = 0;
const mi::Sint64 texil = f2ll_rz(texf);
const mi::Sint64 texsizel = mi::Sint64(tex_size);
if (mi::Uint64(f2ll_rd(texf)) >= mi::Uint64(tex_size)) {
// Wrap or clamp
texi = (int) std::min(std::max(texil, 0ll), (texsizel - 1ll));
// Repeat
else {
texi = mi::Sint32(texil % texsizel);
const mi::Sint32 s = mi::math::sign_bit(texf);
const mi::Sint64 d = texil / (mi::Sint64) tex_size;
const mi::Sint32 a =
((mi::Sint32) d^s) & 1;
const bool alternate = (a != 0);
if (alternate) // Flip negative tex
texi = -texi;
if (s != a) // "Otherwise" pad negative tex back to positive
texi += (mi::Sint32) tex_size - 1;
}
}
else texi = (int) texil;
// Crop
texi += crop_offset;
return mi::Uint32(texi);
}
void tex_lookup2D(
mi::Float32 res[4],
Texture const &tex,
const mi::Float32 uv[2],
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
mi::Float32 frame)
{
const mi::Float32 crop_w = crop_u[1] - crop_u[0];
const mi::Float32 crop_h = crop_v[1] - crop_v[0];
const mi::Sint32_2 crop_offset(
f2u_rz(u2f_rn(tex.size.x-1) * crop_u[0]),
f2u_rz(u2f_rn(tex.size.y-1) * crop_v[0]));
const mi::Uint32_2 crop_texres(
std::max(f2u_rz(u2f_rn(tex.size.x) * crop_w), 1u),
std::max(f2u_rz(u2f_rn(tex.size.y) * crop_h), 1u));
const float U = uv[0] * crop_texres.x - 0.5f;
const float V = uv[1] * crop_texres.y - 0.5f;
const mi::Uint32 U0 = texremap(crop_texres.x, wrap_u, crop_offset[0], U);
const mi::Uint32 U1 = texremap(crop_texres.x, wrap_u, crop_offset[0], U+1.0f);
const mi::Uint32 V0 = texremap(crop_texres.y, wrap_v, crop_offset[1], V);
const mi::Uint32 V1 = texremap(crop_texres.y, wrap_v, crop_offset[1], V+1.0f);
const mi::Uint32 i00 = (tex.size.x * V0 + U0) * tex.ncomp;
const mi::Uint32 i01 = (tex.size.x * V0 + U1) * tex.ncomp;
const mi::Uint32 i10 = (tex.size.x * V1 + U0) * tex.ncomp;
const mi::Uint32 i11 = (tex.size.x * V1 + U1) * tex.ncomp;
mi::Float32 ufrac = U - mi::math::floor(U);
mi::Float32 vfrac = V - mi::math::floor(V);
#ifdef USE_SMOOTHERSTEP_FILTER
ufrac *= ufrac*ufrac*(ufrac*(ufrac*6.0f - 15.0f) + 10.0f); // smoother step
vfrac *= vfrac*vfrac*(vfrac*(vfrac*6.0f - 15.0f) + 10.0f);
#endif
mi::Float32_4(tex.data[i00 + 0], tex.data[i00 + 1], tex.data[i00 + 2], tex.data[i00 + 3]),
mi::Float32_4(tex.data[i01 + 0], tex.data[i01 + 1], tex.data[i01 + 2], tex.data[i01 + 3]),
ufrac);
mi::Float32_4(tex.data[i10 + 0], tex.data[i10 + 1], tex.data[i10 + 2], tex.data[i10 + 3]),
mi::Float32_4(tex.data[i11 + 0], tex.data[i11 + 1], tex.data[i11 + 2], tex.data[i11 + 3]),
ufrac);
store_result4(res, mi::math::lerp(c1, c2, vfrac));
}
void tex_lookup_float4_2d(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const mi::Float32 coord[2],
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
mi::Float32 frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
store_result4(result, 0.0f);
return;
}
Texture const &tex = self->textures[texture_idx - 1];
tex_lookup2D(result, tex, coord, wrap_u, wrap_v, crop_u, crop_v, frame);
}
void tex_lookup_deriv_float4_2d(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const tct_deriv_float2 *coord,
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
mi::Float32 frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
store_result4(result, 0.0f);
return;
}
mi::Float32 uv[2] = { coord->val.x, coord->val.y };
Texture const &tex = self->textures[texture_idx - 1];
tex_lookup2D(result, tex, uv, wrap_u, wrap_v, crop_u, crop_v, frame);
}
void tex_lookup_float3_2d(
mi::Float32 result[3],
mi::Uint32 texture_idx,
const mi::Float32 coord[2],
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
mi::Float32 frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
store_result3(result, 0.0f);
return;
}
tex_lookup_float4_2d(c, self, texture_idx, coord, wrap_u, wrap_v, crop_u, crop_v, frame);
result[0] = c[0];
result[1] = c[1];
result[2] = c[2];
}
void tex_lookup_deriv_float3_2d(
mi::Float32 result[3],
mi::Uint32 texture_idx,
const tct_deriv_float2 *coord,
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
mi::Float32 frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
store_result3(result, 0.0f);
return;
}
mi::Float32 uv[2] = { coord->val.x, coord->val.y };
tex_lookup_float4_2d(c, self, texture_idx, uv, wrap_u, wrap_v, crop_u, crop_v, frame);
result[0] = c[0];
result[1] = c[1];
result[2] = c[2];
}
void tex_texel_float4_2d(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const mi::Sint32 coord[2],
const mi::Sint32 uv_tile[2],
float frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
store_result3(result, 0.0f);
return;
}
Texture const &tex = self->textures[texture_idx - 1];
const mi::Uint32 idx = (tex.size.x * coord[1] + coord[0]) * tex.ncomp;
store_result4(result,
mi::Float32_4(tex.data[idx + 0], tex.data[idx + 1], tex.data[idx + 2], tex.data[idx + 3]));
}
void tex_lookup_float4_3d(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const mi::Float32 coord[3],
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
const mi::Float32 crop_w[2],
mi::Float32 frame)
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
result[3] = 1.0f;
}
void tex_lookup_float3_3d(
mi::Float32 result[3],
mi::Uint32 texture_idx,
const mi::Float32 coord[3],
const mi::Float32 crop_u[2],
const mi::Float32 crop_v[2],
const mi::Float32 crop_w[2],
mi::Float32 frame)
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
}
void tex_texel_float4_3d(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const mi::Sint32 coord[3],
float frame)
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
result[3] = 1.0f;
}
void tex_lookup_float4_cube(
mi::Float32 result[4],
mi::Uint32 texture_idx,
const mi::Float32 coord[3])
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
result[3] = 1.0f;
}
void tex_lookup_float3_cube(
mi::Float32 result[3],
mi::Uint32 texture_idx,
const mi::Float32 coord[3])
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
}
void tex_resolution_2d(
mi::Sint32 result[2],
mi::Uint32 texture_idx,
const mi::Sint32 uv_tile[2],
float frame)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
if (texture_idx == 0 || texture_idx - 1 >= self->num_textures) {
// invalid texture returns zero
result[0] = 0;
result[1] = 0;
return;
}
Texture const &tex = self->textures[texture_idx - 1];
result[0] = tex.size.x;
result[1] = tex.size.y;
}
void tex_resolution_3d(
mi::Sint32 result[3],
mi::Uint32 texture_idx,
float frame)
{
result[0] = 0;
result[1] = 0;
result[2] = 0;
}
bool tex_texture_isvalid(
mi::Uint32 texture_idx)
{
Texture_handler const *self = static_cast<Texture_handler const *>(self_base);
return texture_idx != 0 && texture_idx - 1 < self->num_textures;
}
void tex_frame(
mi::Sint32 result[2],
mi::Uint32 texture_idx)
{
result[0] = 0;
result[1] = 0;
}
// ------------------------------------------------------------------------------------------------
// Light Profiles (dummy functions)
// ------------------------------------------------------------------------------------------------
mi::Float32 df_light_profile_power(
const Texture_handler_base *self,
mi::Uint32 light_profile_idx)
{
return 0.0f;
}
mi::Float32 df_light_profile_maximum(
const Texture_handler_base *self,
mi::Uint32 light_profile_idx)
{
return 0.0f;
}
bool df_light_profile_isvalid(
const Texture_handler_base *self,
mi::Uint32 light_profile_idx)
{
return false;
}
mi::Float32 df_light_profile_evaluate(
const Texture_handler_base *self,
mi::Uint32 light_profile_idx,
const float theta_phi[2])
{
return 0.0f;
}
void df_light_profile_sample(
mi::Float32 result[3], // theta, phi, pdf
const Texture_handler_base *self,
mi::Uint32 light_profile_idx,
const float xi[3])
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
}
mi::Float32 df_light_profile_pdf(
const Texture_handler_base *self,
mi::Uint32 light_profile_idx,
const float theta_phi[2])
{
return 0.0f;
}
// ------------------------------------------------------------------------------------------------
// BSDF measurements (dummy functions)
// ------------------------------------------------------------------------------------------------
bool df_bsdf_measurement_isvalid(
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index)
{
return false;
}
void df_bsdf_measurement_resolution(
mi::Uint32 result[3],
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index,
{
result[0] = 0;
result[1] = 0;
result[2] = 0;
}
void df_bsdf_measurement_evaluate(
mi::Float32 result[3],
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index,
const mi::Float32 theta_phi_in[2],
const mi::Float32 theta_phi_out[2],
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
}
void df_bsdf_measurement_sample(
mi::Float32 result[3],
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index,
const mi::Float32 theta_phi_out[2],
const mi::Float32 xi[3],
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
}
mi::Float32 df_bsdf_measurement_pdf(
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index,
const mi::Float32 theta_phi_in[2],
const mi::Float32 theta_phi_out[2],
{
return 0.0f;
}
void df_bsdf_measurement_albedos(
mi::Float32 result[4],
const Texture_handler_base *self,
mi::Uint32 bsdf_measurement_index,
const mi::Float32 theta_phi[2])
{
result[0] = 0.0f;
result[1] = 0.0f;
result[2] = 0.0f;
result[3] = 0.0f;
}
// ------------------------------------------------------------------------------------------------
// Normal adaption (dummy functions)
//
// Can be enabled via backend option "use_renderer_adapt_normal".
// ------------------------------------------------------------------------------------------------
#ifndef TEX_SUPPORT_NO_DUMMY_ADAPTNORMAL
// Implementation of adapt_normal().
void adapt_normal(
float result[3],
Texture_handler_base const *self_base,
float const normal[3])
{
// just return original normal
result[0] = normal[0];
result[1] = normal[1];
result[2] = normal[2];
}
#endif // TEX_SUPPORT_NO_DUMMY_ADAPTNORMAL
// ------------------------------------------------------------------------------------------------
// Scene data (dummy functions)
// ------------------------------------------------------------------------------------------------
#ifndef TEX_SUPPORT_NO_DUMMY_SCENEDATA
bool scene_data_isvalid(
Texture_handler_base const *self_base,
unsigned scene_data_id)
{
return false;
}
void scene_data_lookup_float4(
float result[4],
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value[4],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
result[2] = default_value[2];
result[3] = default_value[3];
}
void scene_data_lookup_float3(
float result[3],
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value[3],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
result[2] = default_value[2];
}
void scene_data_lookup_color(
float result[3],
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value[3],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
result[2] = default_value[2];
}
void scene_data_lookup_float2(
float result[2],
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value[2],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
}
float scene_data_lookup_float(
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value,
bool uniform_lookup)
{
// just return default value
return default_value;
}
void scene_data_lookup_int4(
int result[4],
Texture_handler_base const *self_base,
unsigned scene_data_id,
int const default_value[4],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
result[2] = default_value[2];
result[3] = default_value[3];
}
void scene_data_lookup_int3(
int result[3],
Texture_handler_base const *self_base,
unsigned scene_data_id,
int const default_value[3],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
result[2] = default_value[2];
}
void scene_data_lookup_int2(
int result[2],
Texture_handler_base const *self_base,
unsigned scene_data_id,
int const default_value[2],
bool uniform_lookup)
{
// just return default value
result[0] = default_value[0];
result[1] = default_value[1];
}
int scene_data_lookup_int(
Texture_handler_base const *self_base,
unsigned scene_data_id,
int default_value,
bool uniform_lookup)
{
// just return default value
return default_value;
}
void scene_data_lookup_float4x4(
float result[16],
Texture_handler_base const *self_base,
unsigned scene_data_id,
float const default_value[16],
bool uniform_lookup)
{
// just return default value
for (int i = 0; i < 16; ++i)
result[i] = default_value[i];
}
void scene_data_lookup_deriv_float4(
Texture_handler_base const *self_base,
unsigned scene_data_id,
tct_deriv_arr_float_4 const *default_value,
bool uniform_lookup)
{
// just return default value
*result = *default_value;
}
void scene_data_lookup_deriv_float3(
Texture_handler_base const *self_base,
unsigned scene_data_id,
tct_deriv_arr_float_3 const *default_value,
bool uniform_lookup)
{
// just return default value
*result = *default_value;
}
void scene_data_lookup_deriv_color(
Texture_handler_base const *self_base,
unsigned scene_data_id,
tct_deriv_arr_float_3 const *default_value,
bool uniform_lookup)
{
// just return default value
*result = *default_value;
}
void scene_data_lookup_deriv_float2(
Texture_handler_base const *self_base,
unsigned scene_data_id,
tct_deriv_arr_float_2 const *default_value,
bool uniform_lookup)
{
// just return default value
*result = *default_value;
}
void scene_data_lookup_deriv_float(
tct_deriv_float *result,
Texture_handler_base const *self_base,
unsigned scene_data_id,
tct_deriv_float const *default_value,
bool uniform_lookup)
{
// just return default value
*result = *default_value;
}
#endif // TEX_SUPPORT_NO_DUMMY_SCENEDATA
// ------------------------------------------------------------------------------------------------
// Vtables
// ------------------------------------------------------------------------------------------------
// The vtable containing all texture access handlers required by the generated code
// in "vtable" mode.
tex_lookup_float4_2d,
tex_lookup_float3_2d,
tex_texel_float4_2d,
tex_lookup_float4_3d,
tex_lookup_float3_3d,
tex_texel_float4_3d,
tex_lookup_float4_cube,
tex_lookup_float3_cube,
tex_resolution_2d,
tex_resolution_3d,
tex_texture_isvalid,
tex_frame,
df_light_profile_power,
df_light_profile_maximum,
df_light_profile_isvalid,
df_light_profile_evaluate,
df_light_profile_sample,
df_light_profile_pdf,
df_bsdf_measurement_isvalid,
df_bsdf_measurement_resolution,
df_bsdf_measurement_evaluate,
df_bsdf_measurement_sample,
df_bsdf_measurement_pdf,
df_bsdf_measurement_albedos,
adapt_normal,
scene_data_isvalid,
scene_data_lookup_float,
scene_data_lookup_float2,
scene_data_lookup_float3,
scene_data_lookup_float4,
scene_data_lookup_int,
scene_data_lookup_int2,
scene_data_lookup_int3,
scene_data_lookup_int4,
scene_data_lookup_color,
scene_data_lookup_float4x4,
/*m_scene_data_lookup_deriv_float*/ nullptr,
/*m_scene_data_lookup_deriv_float2*/ nullptr,
/*m_scene_data_lookup_deriv_float3*/ nullptr,
/*m_scene_data_lookup_deriv_float4*/ nullptr,
/*m_scene_data_lookup_deriv_color*/ nullptr
};
// The vtable containing all texture access handlers required by the generated code
// in "vtable" mode with derivatives.
tex_lookup_deriv_float4_2d,
tex_lookup_deriv_float3_2d,
tex_texel_float4_2d,
tex_lookup_float4_3d,
tex_lookup_float3_3d,
tex_texel_float4_3d,
tex_lookup_float4_cube,
tex_lookup_float3_cube,
tex_resolution_2d,
tex_resolution_3d,
tex_texture_isvalid,
tex_frame,
df_light_profile_power,
df_light_profile_maximum,
df_light_profile_isvalid,
df_light_profile_evaluate,
df_light_profile_sample,
df_light_profile_pdf,
df_bsdf_measurement_isvalid,
df_bsdf_measurement_resolution,
df_bsdf_measurement_evaluate,
df_bsdf_measurement_sample,
df_bsdf_measurement_pdf,
df_bsdf_measurement_albedos,
adapt_normal,
scene_data_isvalid,
scene_data_lookup_float,
scene_data_lookup_float2,
scene_data_lookup_float3,
scene_data_lookup_float4,
scene_data_lookup_int,
scene_data_lookup_int2,
scene_data_lookup_int3,
scene_data_lookup_int4,
scene_data_lookup_color,
scene_data_lookup_float4x4,
scene_data_lookup_deriv_float,
scene_data_lookup_deriv_float2,
scene_data_lookup_deriv_float3,
scene_data_lookup_deriv_float4,
scene_data_lookup_deriv_color,
};
#endif
Fixed-size math vector class template with generic operations.
Definition: vector.h:286
long long Sint64
64-bit signed integer.
Definition: types.h:61
unsigned long long Uint64
64-bit unsigned integer.
Definition: types.h:62
float Float32
32-bit float.
Definition: types.h:51
bool sign_bit(Sint8 s)
Returns true if s<0 and false if s>= 0.
Definition: function.h:790
Bbox<T, DIM> lerp(const Bbox<T, DIM> &bbox1, const Bbox<T, DIM> &bbox2, T t)
Returns the linear interpolation between bbox1 and bbox2, i.e., it returns (1-t) * bbox1 + t * bbox2.
Definition: bbox.h:672
Color floor(const Color &c)
Returns a color with the elementwise largest integral value that is not greater than the element in c...
Definition: color.h:603
tct_traits<true>::tct_derivable_float2 tct_deriv_float2
A float2 with derivatives.
Definition: target_code_types.h:129
Mbsdf_part
MBSDFs can consist of two parts, which can be selected using this enumeration.
Definition: target_code_types.h:328
tct_deriv< float[4]> tct_deriv_arr_float_4
A float[4] with derivatives (needed to avoid problems with wrong alignment).
Definition: target_code_types.h:144
tct_traits<true>::tct_derivable_float tct_deriv_float
A float with derivatives.
Definition: target_code_types.h:126
Tex_wrap_mode
The texture wrap modes as defined by tex::wrap_mode in the MDL specification.
Definition: target_code_types.h:309
struct Shading_state_material_impl<true> Shading_state_material_with_derivs
The MDL material state structure with derivatives for the texture coordinates.
Definition: target_code_types.h:303
tct_deriv< float[2]> tct_deriv_arr_float_2
A float[2] with derivatives (needed to avoid problems with wrong alignment).
Definition: target_code_types.h:138
tct_deriv< float[3]> tct_deriv_arr_float_3
A float[3] with derivatives (needed to avoid problems with wrong alignment).
Definition: target_code_types.h:141
@ TEX_WRAP_CLIP
tex::wrap_clip: makes the texture lookup return zero for texture coordinates outside of the range
Definition: target_code_types.h:323
@ TEX_WRAP_MIRRORED_REPEAT
tex::wrap_mirrored_repeat: like wrap_repeat but takes one minus the fractional part every other inter...
Definition: target_code_types.h:319
@ TEX_WRAP_CLAMP
tex::wrap_clamp: clamps the lookup coordinate to the range
Definition: target_code_types.h:311
The runtime for bitmap texture access for the generated target code can optionally be implemented in ...
Definition: target_code_types.h:344
A template struct with derivatives.
Definition: target_code_types.h:97
[Previous] [Up] [Next]