shader_lightlist.h
Go to the documentation of this file.
00001 
00002 // Copyright 1986, 2015 NVIDIA ARC GmbH. All rights reserved.
00004 // Created:     27.02.08
00005 // Module:      api
00006 // Purpose:     mental ray C++ shader interface extensions
00008 
00017 
00018 
00019 #ifndef SHADER_LIGHTLIST_H
00020 #define SHADER_LIGHTLIST_H
00021 
00022 #include "mi_shader_if.h"
00023 
00024 namespace mi {
00025 namespace shader_v3 {
00026 
00027 
00054 class LightIterator {
00055 public:
00079     LightIterator(
00080         miState*        state,
00081         miTag*          shader_light_list = 0,
00082         int             n_shader_lights = 0,
00083         int             version = mi_ray_interface_version);
00084 
00105     LightIterator(
00106         miState*        state,
00107         const miVector  &axis,
00108         miScalar        spread_cos,
00109         miTag*          shader_light_list = 0,
00110         int             n_shader_lights = 0,
00111         int             version = mi_ray_interface_version);
00112 
00113 
00120     LightIterator(const LightIterator &iter);
00121 
00126     ~LightIterator();
00127 
00135     miTag operator*() const;
00136 
00150     LightList* operator->() const;
00151 
00159     const LightIterator& operator++();
00160 
00170     LightIterator operator++(int);
00171 
00176     bool at_end() const;
00177 
00187     const LightIterator &operator=(const LightIterator &iter);
00188 
00195     bool operator==(const LightIterator &iter) const;
00196 
00203     bool operator!=(const LightIterator &iter) const;
00204 
00205 private:
00209     LightList* m_list;
00210 
00214     size_t m_current;
00215 };
00216 
00217 
00227 class LightList {
00228 public:
00229 
00239     virtual size_t set_current(size_t current)          = 0;
00240 
00246     virtual size_t get_current() const                  = 0;
00247 
00254     virtual bool sample()                               = 0;
00255 
00260     virtual miScalar get_dot_nl() const                 = 0;
00261 
00266     virtual const miVector& get_direction() const       = 0;
00267 
00276     virtual void get_contribution(miColor *c) const     = 0;
00277 
00286     virtual void get_contribution(miSpectrum *s) const  = 0;
00287 
00295     virtual int get_number_of_samples() const           = 0;
00296 
00305     virtual miTag get_light_tag(size_t current) const   = 0;
00306 
00310     virtual size_t get_number_of_lights() const         = 0;
00311 
00317     virtual void connect()                              = 0;
00318 
00324     virtual void release()                              = 0;
00325 }; 
00326 
00327 
00328 class Access_bsdf;
00329 
00334 class MISLightIterator {
00335 public:
00336 
00364     static void get_direct_lighting(
00365         miColor*        result,
00366         miState*        state,
00367         miColor&        diffuse_color,
00368         miTag*          shader_light_list = 0,
00369         int             n_shader_lights = 0,
00370         int             version = mi_ray_interface_version);
00371 
00395     MISLightIterator(
00396         miState*        state,
00397         miTag*          shader_light_list = 0,
00398         int             n_shader_lights = 0,
00399         int             version = mi_ray_interface_version);
00400 
00427     MISLightIterator(
00428         miState*        state,
00429         Access_bsdf&    bsdf,
00430         miTag*          shader_light_list = 0,
00431         int             n_shader_lights = 0,
00432         int             version = mi_ray_interface_version);
00433 
00440     MISLightIterator(const MISLightIterator &iter);
00441 
00446     ~MISLightIterator();
00447 
00455     miTag operator*() const;
00456 
00470     MISLightList* operator->() const;
00471 
00479     const MISLightIterator& operator++();
00480 
00490     MISLightIterator operator++(int);
00491 
00496     bool at_end() const;
00497 
00507     const MISLightIterator &operator=(const MISLightIterator &iter);
00508 
00515     bool operator==(const MISLightIterator &iter) const;
00516 
00523     bool operator!=(const MISLightIterator &iter) const;
00524 
00525 private:
00529     MISLightList* m_list;
00530 
00534     size_t m_current;
00535 };
00536 
00537 
00578 class MISLightList {
00579 public:
00580 
00590     virtual size_t set_current(size_t current)          = 0;
00591 
00597     virtual size_t get_current() const                  = 0;
00598 
00606     virtual bool has_bsdf() const                       = 0;
00607 
00614     virtual bool sample()                               = 0;
00615 
00620     virtual miScalar get_dot_nl() const                 = 0;
00621 
00626     virtual const miVector& get_direction() const       = 0;
00627 
00641     virtual void get_contribution(miColor *c) const     = 0;
00642 
00652     virtual void get_bsdf_contribution(miColor *c) const = 0;
00653 
00658     virtual miScalar get_pdf() const                    = 0;
00659 
00664     virtual miScalar get_weight() const                 = 0;
00665 
00670     virtual miScalar get_norm_factor() const            = 0;
00671 
00686     virtual void get_sampled_contribution(miColor *c) const     = 0;
00687 
00695     virtual int get_number_of_samples() const           = 0;
00696 
00705     virtual miTag get_light_tag(size_t current) const   = 0;
00706 
00710     virtual size_t get_number_of_lights() const         = 0;
00711 
00717     virtual void connect()                              = 0;
00718 
00724     virtual void release()                              = 0;
00725 };
00726 
00727 
00728 //-----------------------------------------------------------------------------
00729 // inline implementation for LightIterator methods
00730 //-----------------------------------------------------------------------------
00731 
00732 inline LightIterator::LightIterator(
00733     miState             *state,
00734     const miVector      &axis,
00735     miScalar            spread_cos,
00736     miTag               *shader_light_list, 
00737     int                 n_shader_lights,
00738     int                 version)
00739 : m_list(Access_interface(version)->createLightList(
00740         state, axis, spread_cos, shader_light_list, n_shader_lights))
00741 , m_current(0)
00742 {
00743 }
00744 
00745 inline LightIterator::LightIterator(
00746     miState             *state,
00747     miTag               *shader_light_list, 
00748     int                 n_shader_lights,
00749     int                 version)
00750 : m_list(Access_interface(version)->createLightList(
00751         state, state->normal, 0, shader_light_list, n_shader_lights))
00752 , m_current(0)
00753 {
00754 }
00755 
00756 inline LightIterator::LightIterator(const LightIterator &iter) 
00757 : m_list(iter.m_list)
00758 , m_current(iter.m_current)
00759 { 
00760     if(m_list) m_list->connect();  // maintain reference count 
00761 }
00762 
00763 inline LightIterator::~LightIterator() 
00764 {
00765     if(m_list) m_list->release();  // maintain reference count
00766 }
00767 
00768 inline const LightIterator& LightIterator::operator=(const LightIterator &iter)
00769 {
00770     if(m_list != iter.m_list) {
00771         // need the compare above, otherwise the release might delete the list
00772         // and the connect below would be invalid.
00773         if (m_list) m_list->release();
00774         m_list = iter.m_list;
00775         m_list->connect();
00776     }
00777     m_current = iter.m_current;
00778     return *this;
00779 }
00780 
00781 inline miTag LightIterator::operator*() const 
00782 {
00783     return m_list->get_light_tag(m_current);
00784 }
00785 
00786 inline LightList* LightIterator::operator->() const
00787 {
00788     m_list->set_current(m_current);
00789     return m_list;
00790 }
00791 
00792 inline const LightIterator& LightIterator::operator++() 
00793 {
00794     ++m_current;
00795     return *this;
00796 }
00797 
00798 inline LightIterator LightIterator::operator++(int)
00799 {
00800     LightIterator res(*this);
00801     ++m_current;
00802     return res;
00803 }
00804 
00805 inline bool LightIterator::at_end() const
00806 {
00807     return m_current == m_list->get_number_of_lights();
00808 }
00809 
00810 inline bool LightIterator::operator==(const LightIterator &iter) const 
00811 {
00812     return m_list == iter.m_list && m_current == iter.m_current;
00813 }
00814 
00815 inline bool LightIterator::operator!=(const LightIterator &iter) const 
00816 {
00817     return !this->operator==(iter);
00818 }
00819 
00820 
00821 //-----------------------------------------------------------------------------
00822 // inline implementation for MISLightIterator methods
00823 //-----------------------------------------------------------------------------
00824 
00825 // static convenience method to compute the total direct lighting contribution.
00826 // The diffuse color is needed in case there is no BSDF attached, since in this
00827 // case the core has no way to retrieve it (when a BSDF is there, its contribution
00828 // accounts for the diffuse color and other components)
00829 inline void MISLightIterator::get_direct_lighting(
00830     miColor*            result,
00831     miState*            state,
00832     miColor&            diffuse_color,
00833     miTag*              shader_light_list,
00834     int                 n_shader_lights,
00835     int                 version)
00836 {
00837     result->r = result->g = result->b = 0.0;
00838     result->a = 1.0;
00839 
00840     MISLightIterator it(state, shader_light_list, n_shader_lights, version);
00841 
00842     for ( ; !it.at_end () ; ++it) {
00843         miColor this_light_tot = {0.0, 0.0, 0.0, 1.0};
00844         
00845         while (it->sample ()) {
00846             miColor this_color;
00847             it->get_sampled_contribution(&this_color);
00848         
00849             // the color returned by 'get_sampled_contribution' is already
00850             // multiplied by the MIS weight, the dot_nl factor, the norm.
00851             // factor and the inverse of the probability
00852             this_light_tot.r += this_color.r;
00853             this_light_tot.g += this_color.g;
00854             this_light_tot.b += this_color.b;
00855         }
00856         
00857         // normalizes the total contribution of the light by dividing
00858         // by the number of samples
00859         int n = it->get_number_of_samples();
00860         
00861         if (n>1) {
00862             float n_inv = 1.0f/(float) n;
00863             
00864             this_light_tot.r *= n_inv;
00865             this_light_tot.g *= n_inv;
00866             this_light_tot.b *= n_inv;
00867         }
00868         
00869         result->r += this_light_tot.r;
00870         result->g += this_light_tot.g;
00871         result->b += this_light_tot.b;
00872     }
00873 
00874     if (!it->has_bsdf()) {
00875         // there is no BSDF attached to the current material, the total
00876         // light contribution must be multiplied by the diffuse color
00877 
00878         result->r *= diffuse_color.r;
00879         result->g *= diffuse_color.g;
00880         result->b *= diffuse_color.b;
00881     }
00882 }
00883 
00884 inline MISLightIterator::MISLightIterator(
00885     miState             *state,
00886     miTag               *shader_light_list, 
00887     int                 n_shader_lights,
00888     int                 version)
00889 : m_list(Access_interface(version)->createMISLightList(
00890         state, shader_light_list, n_shader_lights))
00891 , m_current(0)
00892 {
00893 }
00894 
00895 inline MISLightIterator::MISLightIterator(
00896     miState             *state,
00897     Access_bsdf         &bsdf,
00898     miTag               *shader_light_list, 
00899     int                 n_shader_lights,
00900     int                 version)
00901 : m_list(Access_interface(version)->createMISLightList(
00902         state, bsdf, shader_light_list, n_shader_lights))
00903 , m_current(0)
00904 {
00905 }
00906 
00907 inline MISLightIterator::MISLightIterator(const MISLightIterator &iter) 
00908 : m_list(iter.m_list)
00909 , m_current(iter.m_current)
00910 { 
00911     if(m_list) m_list->connect();  // maintain reference count 
00912 }
00913 
00914 inline MISLightIterator::~MISLightIterator() 
00915 {
00916     if(m_list) m_list->release();  // maintain reference count
00917 }
00918 
00919 inline const MISLightIterator& MISLightIterator::operator=(const MISLightIterator &iter)
00920 {
00921     if(m_list != iter.m_list) {
00922         // need the compare above, otherwise the release might delete the list
00923         // and the connect below would be invalid.
00924         if (m_list) m_list->release();
00925         m_list = iter.m_list;
00926         m_list->connect();
00927     }
00928     m_current = iter.m_current;
00929     return *this;
00930 }
00931 
00932 inline miTag MISLightIterator::operator*() const 
00933 {
00934     return m_list->get_light_tag(m_current);
00935 }
00936 
00937 inline MISLightList* MISLightIterator::operator->() const
00938 {
00939     m_list->set_current(m_current);
00940     return m_list;
00941 }
00942 
00943 inline const MISLightIterator& MISLightIterator::operator++() 
00944 {
00945     ++m_current;
00946     return *this;
00947 }
00948 
00949 inline MISLightIterator MISLightIterator::operator++(int)
00950 {
00951     MISLightIterator res(*this);
00952     ++m_current;
00953     return res;
00954 }
00955 
00956 inline bool MISLightIterator::at_end() const
00957 {
00958     return m_current == m_list->get_number_of_lights();
00959 }
00960 
00961 inline bool MISLightIterator::operator==(const MISLightIterator &iter) const 
00962 {
00963     return m_list == iter.m_list && m_current == iter.m_current;
00964 }
00965 
00966 inline bool MISLightIterator::operator!=(const MISLightIterator &iter) const 
00967 {
00968     return !this->operator==(iter);
00969 }
00970 
00971 
00972 }}
00973 
00974 #endif //SHADER_LIGHTLIST_H

Copyright © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.