Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/shader/spheretexHighlighter.cxx

Go to the documentation of this file.
00001 // Filename: spheretexHighlighter.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 #include "spheretexHighlighter.h"
00019 #include "config_shader.h"
00020 
00021 #include <light.h>
00022 #include <spotlight.h>
00023 #include <renderBuffer.h>
00024 #include <get_rel_pos.h>
00025 #include <dftraverser.h>
00026 #include <displayRegion.h>
00027 #include <graphicsWindow.h>
00028 #include <materialTransition.h>
00029 #include <materialAttribute.h>
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 // Static variables
00033 ////////////////////////////////////////////////////////////////////
00034 TypeHandle SpheretexHighlighter::_type_handle;
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: SpheretexHighlighter::Constructor
00038 //       Access:
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 SpheretexHighlighter::SpheretexHighlighter(int size) : FrustumShader()
00042 {
00043   set_size(size);
00044 
00045   Texture* texture = new Texture;
00046   texture->set_minfilter(Texture::FT_linear);
00047   texture->set_magfilter(Texture::FT_linear);
00048   texture->set_wrapu(Texture::WM_clamp);
00049   texture->set_wrapv(Texture::WM_clamp);
00050   texture->_pbuffer = new PixelBuffer(PixelBuffer::rgb_buffer(_size, _size));
00051   _spheretex_shader.set_texture(texture);
00052   _spheretex_shader.set_blend_mode(ColorBlendProperty::M_add);
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: SpheretexHighlighter::set_multipass
00057 //       Access: Public
00058 //  Description:
00059 ////////////////////////////////////////////////////////////////////
00060 void SpheretexHighlighter::
00061 set_multipass(bool)
00062 {
00063   //A highlight shader always needs to blend
00064   _multipass_on = true;
00065  _spheretex_shader.set_multipass(true);
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: SpheretexHighlighter::set_priority
00070 //       Access: Public
00071 //  Description:
00072 ////////////////////////////////////////////////////////////////////
00073 void SpheretexHighlighter::
00074 set_priority(int priority)
00075 {
00076   Shader::set_priority(priority);
00077   _spheretex_shader.set_priority(priority);
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: SpheretexHighlighter::pre_apply
00082 //       Access:
00083 //  Description:
00084 ///////////////////////////////////////////////////////////////////
00085 void SpheretexHighlighter::
00086 pre_apply(Node *node, const AllAttributesWrapper &init_state,
00087           const AllTransitionsWrapper &, GraphicsStateGuardian *gsg)
00088 {
00089   if (get_num_frusta() == 0) {
00090     shader_cat.error()
00091       << "SpheretexHighlighter::config() - no lights in frusta list"
00092       << endl;
00093     return;
00094   } else if (get_num_frusta() > 1) {
00095     shader_cat.warning()
00096       << "SpheretexHighlighter::config() - frusta list has more than one "
00097       << "frustum - ignore all but the first one for now..." << endl;
00098   }
00099   if (_frusta[0]->get_type() != Spotlight::get_class_type()) {
00100     shader_cat.error()
00101       << "SpheretexHighlighter::config() - only works for Spotlights"
00102       << " so far - we'll add point lights later" << endl;
00103     return;
00104   }
00105   // MPG - we could make this work for point lights as well
00106   Spotlight* light = (Spotlight *)_frusta[0];
00107 
00108   // Figure out how shiny the highlighted object is
00109   float shininess = 0.0;
00110 
00111   const NodeAttribute *mat_attrib =
00112     init_state.get_attribute(MaterialTransition::get_class_type());
00113   if (mat_attrib != (NodeAttribute *)NULL) {
00114     const Material *material =
00115       DCAST(MaterialAttribute, mat_attrib)->get_material();
00116     shininess = material->get_shininess();
00117   }
00118 
00119   if (shininess == 0.0) {
00120     shininess = 100.0;
00121   }
00122 
00123   // Figure out where the highlight is relative to the object's center and
00124   // the light
00125   const LensNode* projnode = gsg->get_current_camera();
00126   LVector3f model_pos = get_rel_pos(node, projnode);
00127   LVector3f norm_model_pos = normalize(model_pos);
00128   LPoint3f light_pos = get_rel_pos(light, projnode);
00129   LVector3f light_vec = light_pos - model_pos;
00130   light_vec = normalize(light_vec);
00131 
00132   // Compute highlight for all pixels on the image that are on the sphere
00133   LVector3f view_vec(0, -1, 0); // Looking down +y axis
00134   LVector3f norm, S;
00135   float ZZ, XX_ZZ, intensity, grazing;
00136   uchar color[3];
00137   float scale = 1.0 / ((float)(_size - 1));
00138 
00139   Texture* texture = _spheretex_shader.get_texture();
00140 
00141   for (int y = 0; y < _size; ++y) {
00142     norm[2] = 2. * ((float)y * scale) - 1.; // 0.._size-1 -> -1..1
00143     ZZ = norm[2] * norm[2]; // z^2
00144 
00145     for (int x = 0; x < _size; ++x) {
00146       norm[0] = 2. * ((float)x * scale) -1.; // 0.._size-1 -> -1..1
00147       XX_ZZ = (norm[0] * norm[0]) + ZZ; // x^2 + z^2
00148 
00149       color[0] = color[1] = color[2] = 0;
00150 
00151       if (XX_ZZ <= 1.) { // Are we on the unit sphere?
00152         norm[1] = -(float)sqrt(1. - XX_ZZ); // This yields a unit vector
00153         grazing = dot(norm, light_vec);
00154         if (grazing > 0.) { // Does any light actually reflect off this point?
00155           S = norm;
00156           S *= 2. * grazing;
00157           S = S - light_vec; // the reflection vector
00158           intensity = -dot(S, norm_model_pos); // approximate R . V
00159           // If, relative to the viewer, the normal doesn't point towards the
00160           // light (even slightly), no reflection will be seen
00161           if (intensity > 0.) {
00162             intensity = pow(intensity, shininess);
00163             color[0] = color[1] = color[2] = (uchar)(intensity * 255.);
00164           }
00165         }
00166       }
00167       texture->_pbuffer->set_uchar_rgb_texel(color, x, y, _size);
00168       texture->unprepare();
00169     }
00170   }
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: SpheretexHighlighter::apply
00175 //       Access:
00176 //  Description:
00177 ////////////////////////////////////////////////////////////////////
00178 void SpheretexHighlighter::
00179 apply(Node *node, const AllAttributesWrapper &init_state,
00180       const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg) {
00181 
00182   Shader::apply(node, init_state, net_trans, gsg);
00183 
00184   _spheretex_shader.apply(node, init_state, net_trans, gsg);
00185 }

Generated on Fri May 2 00:44:03 2003 for Panda by doxygen1.3