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.