{ "cells": [ { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "# Deep dive into a BSDF" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview\n", "\n", "As you have probably already discovered, Mitsuba 3 can do much more than rendering. In this tutorial we will show how to instantiate a BSDF plugin using Python dictionaries and plot its distribution function using `matplotlib`.\n", "\n", "
\n", "\n", "🚀 **You will learn how to:**\n", "\n", "\n", " \n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup\n", "\n", "Of course, let's start with the usual Python imports! As emphasized in previous tutorials, Mitsuba requires a specific variant to be set before performing any other imports or computations. For this tutorial, we are going to use one of the JIT vectorized variant of the system. This will allow us to write code as if it was operating on normal scalar values, and have it run on arbitrary-sized arrays of values on the CPU or GPU." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import drjit as dr\n", "import mitsuba as mi\n", "\n", "mi.set_variant('llvm_ad_rgb')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Instantiating a BSDF\n", "\n", "One easy way to instanciate Mitsuba objects (e.g., [Shape][1], [BSDF][2], ...) is using the [load_dict][3] function. This function takes as input a Python `dict` following a similar structure to the XML scene description and instantiates the corresponding plugin. You can learn more about the specific format of this `dict` by reading the dedicated section in the [documentation][4].\n", "\n", "In this scenario, we want to construct a [roughconductor BSDF][5] with a high roughness value and a GGX microfacet distribution.\n", "\n", "[1]: https://mitsuba.readthedocs.io/en/latest/src/generated/plugins_shapes.html\n", "[2]: https://mitsuba.readthedocs.io/en/latest/src/generated/plugins_bsdfs.html\n", "[3]: https://mitsuba.readthedocs.io/en/latest/src/api_reference.html#mitsuba.load_dict\n", "[4]: https://mitsuba.readthedocs.io/en/latest/src/key_topics/scene_format.html#scene-python-dict-format\n", "[5]: https://mitsuba.readthedocs.io/en/latest/src/generated/plugins_bsdfs.html#rough-conductor-material-roughconductor" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "bsdf = mi.load_dict({\n", " 'type': 'roughconductor',\n", " 'alpha': 0.2,\n", " 'distribution': 'ggx'\n", "})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vectorized evaluation of the BSDF\n", "\n", "We will now evaluate this BSDF for a whole array of directions at once, leveraging the enabled vectorize backend. Similarly to working on `numpy` arrays, we use DrJit routines to perform array-based arithmetics.\n", "\n", "For instance, here we start by defining a function to map from spherical and Euclidean coordinates." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def sph_to_dir(theta, phi):\n", " \"\"\"Map spherical to Euclidean coordinates\"\"\"\n", " st, ct = dr.sincos(theta)\n", " sp, cp = dr.sincos(phi)\n", " return mi.Vector3f(cp * st, sp * st, ct)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then use this function to generate a set of directions to evaluate the BSDF with." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Create a (dummy) surface interaction to use for the evaluation of the BSDF\n", "si = dr.zeros(mi.SurfaceInteraction3f)\n", "\n", "# Specify an incident direction with 45 degrees elevation\n", "si.wi = sph_to_dir(dr.deg2rad(45.0), 0.0)\n", "\n", "# Create grid in spherical coordinates and map it onto the sphere\n", "res = 300\n", "theta_o, phi_o = dr.meshgrid(\n", " dr.linspace(mi.Float, 0, dr.pi, res),\n", " dr.linspace(mi.Float, 0, 2 * dr.pi, 2 * res)\n", ")\n", "wo = sph_to_dir(theta_o, phi_o)\n", "\n", "# Evaluate the whole array (18000 directions) at once\n", "values = bsdf.eval(mi.BSDFContext(), si, wo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting the results\n", "\n", "Dr.Jit arrays of any flavour can easily be converted to an array type of other mainstream libraries, such as `numpy`, `PyTorch`, `JAX` and `TensorFlow`. For more detailed information on this, take a look at the extensive [drjit documentation][1].\n", "In our case we are going to convert our drjit array to a numpy array.\n", "\n", "[1]: https://drjit.readthedocs.io/en/master/" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "values_np = np.array(values)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now use our favourite plotting library to visualize the BSDF distribution (here we use `matplotlib`)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "nbsphinx-thumbnail": {}, "tags": [] }, "outputs": [ { "data": { "image/png": "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7jyeEwDIRyYT3rvvvltvfOMb9drXvlbXX3+9HnvsMV199dWxt3Pdddfp8ccfd173oQ99SCdPntRXvvIVLS8v65ZbbtEXv/jFqdt84hOf0NGjR/XQQw/ppS99qXM73W5X3W53fP7SpUux9xMAoiPwAKBomUx4b7zxRj388MN6wQteoO9973v6mZ/5Gf393/997O14yyJOnz6tH/3oR/rud7+rAwcO6LOf/axuv/12SdLnP/95vf71r9fS0tLM/S9evChJuuyyy3wf46677tKRI0fGH1deeWXs/QQAAEB1LO3v7+9HueH6+rr+6I/+SF/4whf01FNP6ciRI7r22mt14sQJ/eqv/mom62b/9V//Va961au0sbGhdruthx56SC94wQt0/vx5HTt2TJJ07bXX6i/+4i/0ute9buq+e3t7esMb3qALFy7ogQce8H0M14R3GL3vkdRO/TUAAAAgra6k/08XL17U4cOHU28t8pKGt771rXrooYd0++2369ixY9re3ta73/1ufec739H73/9+ve51r9NHPvIRPfOZz0y8M4888oiuvfZatdvD8Dxz5oyOHj06jt3HHntMP/zhD/WLv/iLM/e944479M1vfjMwdiWp3W6Ptw8AAID6ixy8//Iv/6IHHnhAP//zPz++7H3ve5++8IUvqNFo6E/+5E90yy236IEHHtCzn/3sRDtz9uxZ3XDDDePzZ86cmTr/+c9/Xq985SvV6XSm7nfy5Ende++9uv/++/WsZz0r0WMDAACgniKv4T127Ji2trac11199dX667/+a73jHe/Q7/3e7yXembNnz+rGG28cnz9z5szU+X/6p3/SG9/4xvH5/f19nTx5Up/73Od03333JQ5tAAAA1Ffk4D158qR+93d/V2fOnPG9zW/+5m/qvvvuS7Qje3t7evTRR6cC99y5c7rmmmskST/+8Y/19a9/Xb/0S780vv6OO+7QJz/5SX3605/WoUOHdP78eZ0/f17b29uJ9gEAAAD1E3lJw6lTp/TDH/5Qz3/+8/XKV75Sb3rTm7S3tzd1tIS/+7u/0xVXXJFoR86dO6etra2p4L3hhht055136uabb9bjjz+uF77whVPb/6u/+itJ0ste9rKpbX384x/X7/zO7yTaDwAAANRL5KM0eP7jP/5Df/7nf64vfOEL2t7e1sGDB3XFFVfo4sWL2tnZ0Sc+8Qm9+c1vznxH3/CGN+glL3mJ3vWud2W63UuXLunIkSPiKA0AAABlUdBRGjy33nqrPvvZz6rX6+nhhx/Wf/3Xf+nSpUu64oor9PKXv1xHjx5NvVMuL3nJS/Qbv/EbuWwbAAAA9RV7wls3THgBAADKJtsJbybvtAYAAACUFcELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANQawQsAAIBaI3gBAABQawQvAAAAao3gBQAAQK0RvAAAAKg1ghcAAAC1RvACAACg1gheAAAA1BrBCwAAgFojeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqLXKBu91112npaUl58fdd99d9O4BAACgJJpF70BS99xzj37u535Op0+f1vXXX69ut6vnPOc5+sxnPqPXv/71vvfrdrvqdrvj8xcvXvSuyXmPAQAAEM2wy/b39zPZWmWD94knnlCz2dSJEyfUbrf10EMPaW9vT7fddpva7bbv/e666y594AMfcFzzF/ntLAAAAGL73//9Xx05ciT1diobvI888oiuvfbacdyeOXNGR48e1bFjxwLv9973vlenTp0an79w4YKuvvpqff/738/kCQWAoly6dElXXnmlfvCDH+jw4cNF7w4AJHbx4kVdddVVuuyyyzLZXmWD9+zZs7rhhhvG58+cOTN13k+73XZOgI8cOcIfCAC1cPjwYX6fAaiFAweyeblZZV+0dvbsWd14443j82fOnJk6DwAAAEgVDd69vT09+uijU4F77tw5XXPNNcXtFAAAAEqpksF77tw5bW1tTQXvDTfcoDvvvFP//u//Hmtb7XZbd955Z+AL3QCgCvh9BqAusv59trSf1fEeAAAAgBKq5IQXAAAAiIrgBQAAQK0RvAAAAKg1ghcAAAC1ttDB++EPf1jXXHONOp2Obr31Vn3ta18repcAAAAWwl133aVbbrlFhw4d0tGjR/WmN71J3/rWt3J5rIUN3s985jM6deqU7rzzTj388MO66aab9OpXv1o//vGPi941AACA2vvyl7+sO+64Qw8++KC+9KUvaXd3V6961au0ubmZ+WMt7GHJbr31Vt1yyy26++67JQ3fzOLKK6/UO9/5Tr3nPe8peO8AIJrrrrtOjz/+uPO6D33oQzp58uSc9wgAknnyySd19OhRffnLX9ZLX/rSTH+/LeSEt9fr6aGHHtIrXvGK8WUHDhzQK17xCn31q18tcM8AIJ577rlHknT69Gn96Ec/0ne/+10dOHBAn/3sZ3X77bcXvHcAEN3FixclSZdddpmkbH+/LWTwPvXUUxoMBjp27NjU5ceOHdP58+cL2isAiO+JJ55Qs9nUiRMn9IxnPENPPfWU9vb2dNttt/GOawAqY29vT7//+7+vEydO6HnPe56kbH+/NfPYaQDAfDzyyCO69tprx7/8z5w5o6NHj878Bz0AlNkdd9yhb37zm3rggQfGl2X5+20hg/eKK65Qo9HQE088MXX5E088oWc84xkF7RUAxHf27FndcMMN4/NnzpyZOg8AZXfy5Ende++9uv/++/WsZz1rfHmWv98WcklDq9XSzTffrNOnT48v29vb0+nTp/WiF72owD0DgHjOnj2rG2+8cXz+zJkzU+cBoKz29/d18uRJfe5zn9N9992nZz/72VPXZ/n7bSGDV5JOnTqlj370o/rbv/1bPfbYY3rHO96hzc1Nve1tbyt61wAgkr29PT366KNTfwDOnTuna665pridAoCI7rjjDn3yk5/Upz/9aR06dEjnz5/X+fPntb29nfnvt4U9LJkk3X333fqzP/sznT9/XsePH9df/uVf6tZbby16twAgkm9/+9u69tpr9b3vfU9XXXWVJOm1r32tvvrVr+ree+/ViRMnCt5DAPC3tLTkvPzjH/+4Tpw4kenvt4UOXgAAANTfwi5pAAAAwGIgeAEAAFBrBC8AAABqjeAFAABArRG8AAAAqDWCFwAAALVG8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwBU3HXXXaePfexjRe8GAJQWwQsAFba9va1vf/vbuummm4reFQAoLYIXACrsm9/8pvb39/W85z2v6F0BgNIieAGggr7xjW/o5S9/uV7ykpdob29PV111lT74wQ8WvVsAUErNoncAABDPuXPn9Au/8Av6wz/8Q11++eXa29vTLbfcoj/4gz/Qy172Mh0/frzoXQSAUmHCCwAV8/a3v12/8iu/ove97336/ve/rxMnTuhd73qXDh8+rH/7t38revcAoHQIXgCokPPnz+u+++7T29/+dg0GAz3yyCM6fvy4Dhw4oEajoVarVfQuAkDpELwAUCEPPvig9vb2dPz4cX3rW9/S9va2jh8/ru9+97v6yU9+ohe/+MWSpLNnz+q2227TTTfdpF/+5V9Wt9steM8BoDgELwBUSK/XkyTt7OzoP//zP3X11Vfrsssu00c+8hE973nP0w033KCdnR295S1v0cc+9jGdOXNGz3zmM/WpT32q4D0HgOLwojUAqJAXvehFajab+uM//mNtbGzoOc95ju6++2596EMf0v333y9J+sd//Ee95jWv0XOf+1xJ0s/+7M/qySefLHK3AaBQBC8AVMiVV16pv/mbv9G73/1u/ehHP1Kz2dTW1pa++MUv6uabb5YkPfbYY7r++uvH93n00Uf1ute9rqhdBoDCsaQBACrmt37rt/TDH/5QT3/603XPPffowQcf1G233Ta+/qd+6qf0+OOPSxoer/crX/mKXvOa1xS1uwBQuKX9/f39oncCABDP//zP/+jKK6/UuXPn9JznPGfqus3NTf3ar/2avve97+lpT3uaPvrRj+q6664raE8BoHgELwBU0D//8z/rzW9+s9bX17W0tFT07gBAqRG8AAAAqDXW8AIAAKDWCF4AAADUGsELAACAWiN4AQAAUGsELwAAAGqN4AUAAECtEbwAAACoNYIXAAAAtUbwAgAAoNYIXgAAANTa/w/wpBBIt3C74gAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "# Extract red channel of BRDF values and reshape into 2D grid\n", "values_r = values_np[0, :]\n", "values_r = values_r.reshape(2 * res, res).T\n", "\n", "# Plot values for spherical coordinates\n", "fig, ax = plt.subplots(figsize=(8, 4))\n", "\n", "im = ax.imshow(values_r, extent=[0, 2 * np.pi, np.pi, 0], cmap='jet')\n", "\n", "ax.set_xlabel(r'$\\phi_o$', size=10)\n", "ax.set_xticks([0, dr.pi, dr.two_pi])\n", "ax.set_xticklabels(['0', '$\\\\pi$', '$2\\\\pi$'])\n", "ax.set_ylabel(r'$\\theta_o$', size=10)\n", "ax.set_yticks([0, dr.pi / 2, dr.pi])\n", "ax.set_yticklabels(['0', '$\\\\pi/2$', '$\\\\pi$']);" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## See also\n", "\n", "- [mitsuba.load_dict()][1]\n", "- [mitsuba.BSDF.eval()][2]\n", "\n", "[1]: https://mitsuba.readthedocs.io/en/latest/src/api_reference.html#mitsuba.load_dict\n", "[2]: https://mitsuba.readthedocs.io/en/latest/src/api_reference.html#mitsuba.BSDF.eval" ] } ], "metadata": { "file_extension": ".py", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" }, "metadata": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" } }, "mimetype": "text/x-python", "name": "python", "npconvert_exporter": "python", "pygments_lexer": "ipython3", "version": 3 }, "nbformat": 4, "nbformat_minor": 4 }