diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 81f1498acc..7c6a33708f 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -894,12 +894,25 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f 0.0); return &t; } - case Shader::SMO_card_center: { - int px = _current_display_region->get_pixel_width(); - int py = _current_display_region->get_pixel_height(); - t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px), - (py*0.5) / Texture::up_to_power_2(py), - 0.0); + case Shader::SMO_texpad_x: { + Texture *tex = _target._shader->get_shader_input_texture(name); + nassertr(tex != 0, &LMatrix4f::zeros_mat()); + int sx = tex->get_x_size() - tex->get_pad_x_size(); + int sy = tex->get_y_size() - tex->get_pad_y_size(); + int sz = tex->get_z_size() - tex->get_pad_z_size(); + double cx = (sx * 0.5) / tex->get_x_size(); + double cy = (sy * 0.5) / tex->get_y_size(); + double cz = (sz * 0.5) / tex->get_z_size(); + t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0); + return &t; + } + case Shader::SMO_texpix_x: { + Texture *tex = _target._shader->get_shader_input_texture(name); + nassertr(tex != 0, &LMatrix4f::zeros_mat()); + double px = 1.0 / tex->get_x_size(); + double py = 1.0 / tex->get_y_size(); + double pz = 1.0 / tex->get_z_size(); + t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0); return &t; } case Shader::SMO_attr_material: { diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index ca2d2f9546..46a0a476e9 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -348,7 +348,9 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_view_to_model)) { dep |= SSD_transform; } - if ((inp == SMO_alight_x)|| + if ((inp == SMO_texpad_x)|| + (inp == SMO_texpix_x)|| + (inp == SMO_alight_x)|| (inp == SMO_dlight_x)|| (inp == SMO_plight_x)|| (inp == SMO_slight_x)|| @@ -789,12 +791,6 @@ compile_parameter(const ShaderArgId &arg_id, } bind._part[0] = SMO_window_size; bind._arg[0] = NULL; - } else if (pieces[1] == "cardcenter") { - if (!cp_errchk_parameter_float(p, 2, 2)) { - return false; - } - bind._part[0] = SMO_card_center; - bind._arg[0] = NULL; } else { cp_report_error(p,"unknown system parameter"); return false; @@ -909,6 +905,48 @@ compile_parameter(const ShaderArgId &arg_id, return true; } + // Keywords to fetch texture parameter data. + + if (pieces[0] == "texpad") { + if ((!cp_errchk_parameter_words(p,2)) || + (!cp_errchk_parameter_in(p)) || + (!cp_errchk_parameter_uniform(p))|| + (!cp_errchk_parameter_float(p,3,4))) { + return false; + } + ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = SMP_row3; + bind._func = SMF_first; + bind._part[0] = SMO_texpad_x; + bind._arg[0] = InternalName::make(pieces[1]); + bind._part[1] = SMO_identity; + bind._arg[1] = NULL; + cp_optimize_mat_spec(bind); + _mat_spec.push_back(bind); + return true; + } + + if (pieces[0] == "texpix") { + if ((!cp_errchk_parameter_words(p,2)) || + (!cp_errchk_parameter_in(p)) || + (!cp_errchk_parameter_uniform(p))|| + (!cp_errchk_parameter_float(p,2,4))) { + return false; + } + ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = SMP_row3; + bind._func = SMF_first; + bind._part[0] = SMO_texpix_x; + bind._arg[0] = InternalName::make(pieces[1]); + bind._part[1] = SMO_identity; + bind._arg[1] = NULL; + cp_optimize_mat_spec(bind); + _mat_spec.push_back(bind); + return true; + } + if (pieces[0] == "l") { // IMPLEMENT THE ERROR CHECKING return true; // Cg handles this automatically. diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 5a62c6bb09..7cc1f5b521 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -70,7 +70,8 @@ public: SMO_window_size, SMO_pixel_size, - SMO_card_center, + SMO_texpad_x, + SMO_texpix_x, SMO_attr_material, SMO_attr_color, diff --git a/panda/src/pgraph/attribSlots.I b/panda/src/pgraph/attribSlots.I index cb2b18a886..9a70f5ec11 100644 --- a/panda/src/pgraph/attribSlots.I +++ b/panda/src/pgraph/attribSlots.I @@ -27,6 +27,7 @@ clear_to_zero() { _alpha_test = NULL; _antialias = NULL; _audio_volume = NULL; + _aux_bitplane = NULL; _clip_plane = NULL; _color = NULL; _color_blend = NULL; diff --git a/panda/src/pgraph/attribSlots.cxx b/panda/src/pgraph/attribSlots.cxx index 549c0f75f8..06808eb04d 100644 --- a/panda/src/pgraph/attribSlots.cxx +++ b/panda/src/pgraph/attribSlots.cxx @@ -35,6 +35,7 @@ initialize_defvals() { _defvals._alpha_test = DCAST(AlphaTestAttrib,AlphaTestAttrib::make(AlphaTestAttrib::M_none, 0.0)); _defvals._antialias = DCAST(AntialiasAttrib,AntialiasAttrib::make(AntialiasAttrib::M_none)); _defvals._audio_volume = DCAST(AudioVolumeAttrib,AudioVolumeAttrib::make_identity()); + _defvals._aux_bitplane = DCAST(AuxBitplaneAttrib,AuxBitplaneAttrib::make()); _defvals._clip_plane = DCAST(ClipPlaneAttrib,ClipPlaneAttrib::make_all_off()); _defvals._color = DCAST(ColorAttrib,ColorAttrib::make_off()); _defvals._color_blend = DCAST(ColorBlendAttrib,ColorBlendAttrib::make_off()); @@ -64,6 +65,7 @@ initialize_defvals() { _defvals._alpha_test = DCAST(AlphaTestAttrib,_defvals._alpha_test->make_default()); _defvals._antialias = DCAST(AntialiasAttrib,_defvals._antialias->make_default()); _defvals._audio_volume = DCAST(AudioVolumeAttrib,_defvals._audio_volume->make_default()); + _defvals._aux_bitplane = DCAST(AuxBitplaneAttrib,_defvals._aux_bitplane->make_default()); _defvals._clip_plane = DCAST(ClipPlaneAttrib,_defvals._clip_plane->make_default()); _defvals._color = DCAST(ColorAttrib,_defvals._color->make_default()); _defvals._color_blend = DCAST(ColorBlendAttrib,_defvals._color_blend->make_default()); @@ -108,6 +110,7 @@ AttribSlots(const AttribSlots ©) : _alpha_test(copy._alpha_test), _antialias(copy._antialias), _audio_volume(copy._audio_volume), + _aux_bitplane(copy._aux_bitplane), _clip_plane(copy._clip_plane), _color(copy._color), _color_blend(copy._color_blend), @@ -144,6 +147,7 @@ operator =(const AttribSlots &src) { _alpha_test = src._alpha_test; _antialias = src._antialias; _audio_volume = src._audio_volume; + _aux_bitplane = src._aux_bitplane; _clip_plane = src._clip_plane; _color = src._color; _color_blend = src._color_blend; @@ -180,29 +184,30 @@ get_slot(int n) const { case 0: return DCAST(RenderAttrib, _alpha_test); case 1: return DCAST(RenderAttrib, _antialias); case 2: return DCAST(RenderAttrib, _audio_volume); - case 3: return DCAST(RenderAttrib, _clip_plane); - case 4: return DCAST(RenderAttrib, _color); - case 5: return DCAST(RenderAttrib, _color_blend); - case 6: return DCAST(RenderAttrib, _color_scale); - case 7: return DCAST(RenderAttrib, _color_write); - case 8: return DCAST(RenderAttrib, _cull_bin); - case 9: return DCAST(RenderAttrib, _cull_face); - case 10: return DCAST(RenderAttrib, _depth_offset); - case 11: return DCAST(RenderAttrib, _depth_test); - case 12: return DCAST(RenderAttrib, _depth_write); - case 13: return DCAST(RenderAttrib, _fog); - case 14: return DCAST(RenderAttrib, _light); - case 15: return DCAST(RenderAttrib, _light_ramp); - case 16: return DCAST(RenderAttrib, _material); - case 17: return DCAST(RenderAttrib, _render_mode); - case 18: return DCAST(RenderAttrib, _rescale_normal); - case 19: return DCAST(RenderAttrib, _shade_model); - case 20: return DCAST(RenderAttrib, _shader); - case 21: return DCAST(RenderAttrib, _stencil); - case 22: return DCAST(RenderAttrib, _tex_gen); - case 23: return DCAST(RenderAttrib, _tex_matrix); - case 24: return DCAST(RenderAttrib, _texture); - case 25: return DCAST(RenderAttrib, _transparency); + case 3: return DCAST(RenderAttrib, _aux_bitplane); + case 4: return DCAST(RenderAttrib, _clip_plane); + case 5: return DCAST(RenderAttrib, _color); + case 6: return DCAST(RenderAttrib, _color_blend); + case 7: return DCAST(RenderAttrib, _color_scale); + case 8: return DCAST(RenderAttrib, _color_write); + case 9: return DCAST(RenderAttrib, _cull_bin); + case 10: return DCAST(RenderAttrib, _cull_face); + case 11: return DCAST(RenderAttrib, _depth_offset); + case 12: return DCAST(RenderAttrib, _depth_test); + case 13: return DCAST(RenderAttrib, _depth_write); + case 14: return DCAST(RenderAttrib, _fog); + case 15: return DCAST(RenderAttrib, _light); + case 16: return DCAST(RenderAttrib, _light_ramp); + case 17: return DCAST(RenderAttrib, _material); + case 18: return DCAST(RenderAttrib, _render_mode); + case 19: return DCAST(RenderAttrib, _rescale_normal); + case 20: return DCAST(RenderAttrib, _shade_model); + case 21: return DCAST(RenderAttrib, _shader); + case 22: return DCAST(RenderAttrib, _stencil); + case 23: return DCAST(RenderAttrib, _tex_gen); + case 24: return DCAST(RenderAttrib, _tex_matrix); + case 25: return DCAST(RenderAttrib, _texture); + case 26: return DCAST(RenderAttrib, _transparency); default: nassertr(false, NULL); return NULL; diff --git a/panda/src/pgraph/attribSlots.h b/panda/src/pgraph/attribSlots.h index 64248105ac..d8b7b5c555 100644 --- a/panda/src/pgraph/attribSlots.h +++ b/panda/src/pgraph/attribSlots.h @@ -27,6 +27,7 @@ #include "alphaTestAttrib.h" #include "antialiasAttrib.h" #include "audioVolumeAttrib.h" +#include "auxBitplaneAttrib.h" #include "clipPlaneAttrib.h" #include "colorAttrib.h" #include "colorBlendAttrib.h" @@ -63,6 +64,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots CPT(AlphaTestAttrib) _alpha_test; CPT(AntialiasAttrib) _antialias; CPT(AudioVolumeAttrib) _audio_volume; + CPT(AuxBitplaneAttrib) _aux_bitplane; CPT(ClipPlaneAttrib) _clip_plane; CPT(ColorAttrib) _color; CPT(ColorBlendAttrib) _color_blend; @@ -97,7 +99,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots public: // Each "array" reference requires a switch and a DCAST, so it's not overly fast. - enum { slot_count=26 }; + enum { slot_count=27 }; const RenderAttrib *get_slot(int n) const; private: diff --git a/panda/src/pgraph/auxBitplaneAttrib.I b/panda/src/pgraph/auxBitplaneAttrib.I new file mode 100644 index 0000000000..0623f07ea0 --- /dev/null +++ b/panda/src/pgraph/auxBitplaneAttrib.I @@ -0,0 +1,41 @@ +// Filename: auxBitplaneAttrib.I +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::Constructor +// Access: Private +// Description: Use AuxBitplaneAttrib::make() to construct a new +// AuxBitplaneAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE AuxBitplaneAttrib:: +AuxBitplaneAttrib(int outputs) : + _outputs(outputs) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::get_outputs +// Access: Published +// Description: Returns the AuxBitplaneAttrib output bits. +//////////////////////////////////////////////////////////////////// +INLINE int AuxBitplaneAttrib:: +get_outputs() const { + return _outputs; +} + diff --git a/panda/src/pgraph/auxBitplaneAttrib.cxx b/panda/src/pgraph/auxBitplaneAttrib.cxx new file mode 100644 index 0000000000..15b04b5eb9 --- /dev/null +++ b/panda/src/pgraph/auxBitplaneAttrib.cxx @@ -0,0 +1,175 @@ +// Filename: auxBitplaneAttrib.cxx +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "auxBitplaneAttrib.h" +#include "attribSlots.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle AuxBitplaneAttrib::_type_handle; +CPT(RenderAttrib) AuxBitplaneAttrib::_default; + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::make +// Access: Published, Static +// Description: Constructs a default AuxBitplaneAttrib object. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) AuxBitplaneAttrib:: +make() { + if (_default == 0) { + AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(ABO_color); + _default = return_new(attrib); + } + return _default; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::make +// Access: Published, Static +// Description: Constructs a specified AuxBitplaneAttrib object. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) AuxBitplaneAttrib:: +make(int outputs) { + AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(outputs); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void AuxBitplaneAttrib:: +output(ostream &out) const { + out << get_type() << "(" << _outputs << ")"; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived AuxBitplaneAttrib +// types to return a unique number indicating whether +// this AuxBitplaneAttrib is equivalent to the other one. +// +// This should return 0 if the two AuxBitplaneAttrib objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two AuxBitplaneAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int AuxBitplaneAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const AuxBitplaneAttrib *ta; + DCAST_INTO_R(ta, other, 0); + int compare_result = _outputs - ta->_outputs; + if (compare_result!=0) { + return compare_result; + } + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived AuxBitplaneAttrib +// types to specify what the default property for a +// AuxBitplaneAttrib of this type should be. +// +// This should return a newly-allocated AuxBitplaneAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of AuxBitplaneAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *AuxBitplaneAttrib:: +make_default_impl() const { + return new AuxBitplaneAttrib(ABO_color); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::store_into_slot +// Access: Public, Virtual +// Description: Stores this attrib into the appropriate slot of +// an object of class AttribSlots. +//////////////////////////////////////////////////////////////////// +void AuxBitplaneAttrib:: +store_into_slot(AttribSlots *slots) const { + slots->_aux_bitplane = this; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// AuxBitplaneAttrib. +//////////////////////////////////////////////////////////////////// +void AuxBitplaneAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void AuxBitplaneAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int32(_outputs); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type AuxBitplaneAttrib is encountered +// in the Bam file. It should create the AuxBitplaneAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *AuxBitplaneAttrib:: +make_from_bam(const FactoryParams ¶ms) { + AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(0); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuxBitplaneAttrib::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new AuxBitplaneAttrib. +//////////////////////////////////////////////////////////////////// +void AuxBitplaneAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _outputs = scan.get_int32(); +} diff --git a/panda/src/pgraph/auxBitplaneAttrib.h b/panda/src/pgraph/auxBitplaneAttrib.h new file mode 100644 index 0000000000..1ff3199893 --- /dev/null +++ b/panda/src/pgraph/auxBitplaneAttrib.h @@ -0,0 +1,95 @@ +// Filename: auxBitplaneAttrib.h +// Created by: drose (04Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef AUXBITPLANEATTRIB_H +#define AUXBITPLANEATTRIB_H + +#include "pandabase.h" +#include "renderAttrib.h" + +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : AuxBitplaneAttrib +// Description : Modern frame buffers can have 'aux' bitplanes, which +// are additional bitplanes above and beyond the +// standard depth and color. This attrib controls what +// gets rendered into those additional bitplanes when +// using the standard shader generator. +// +// AuxBitplaneAttrib is relevant only when shader +// generation is enabled. Otherwise, it has no effect. +// +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_PGRAPH AuxBitplaneAttrib : public RenderAttrib { +private: + INLINE AuxBitplaneAttrib(int outputs); + +PUBLISHED: + enum AuxBitplaneOutput { + ABO_color = 1, // The usual. + ABO_csnormal = 2, // Camera space normal. + }; + static CPT(RenderAttrib) make(); + static CPT(RenderAttrib) make(int outputs); + + INLINE int get_outputs() const; + +public: + virtual void output(ostream &out) const; + virtual void store_into_slot(AttribSlots *slots) const; + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +private: + int _outputs; + + static CPT(RenderAttrib) AuxBitplaneAttrib::_default; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderAttrib::init_type(); + register_type(_type_handle, "AuxBitplaneAttrib", + RenderAttrib::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "auxBitplaneAttrib.I" + +#endif + diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index bb74872e9e..52d6a32d4f 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -20,6 +20,7 @@ #include "alphaTestAttrib.h" #include "audioVolumeAttrib.h" +#include "auxBitplaneAttrib.h" #include "ambientLight.h" #include "antialiasAttrib.h" #include "auxSceneData.h" @@ -373,6 +374,7 @@ init_libpgraph() { AmbientLight::init_type(); AntialiasAttrib::init_type(); AudioVolumeAttrib::init_type(); + AuxBitplaneAttrib::init_type(); AuxSceneData::init_type(); BillboardEffect::init_type(); Camera::init_type(); @@ -462,6 +464,7 @@ init_libpgraph() { AmbientLight::register_with_read_factory(); AntialiasAttrib::register_with_read_factory(); AudioVolumeAttrib::register_with_read_factory(); + AuxBitplaneAttrib::register_with_read_factory(); BillboardEffect::register_with_read_factory(); Camera::register_with_read_factory(); ClipPlaneAttrib::register_with_read_factory(); diff --git a/panda/src/pgraph/lightRampAttrib.I b/panda/src/pgraph/lightRampAttrib.I index 2591c86576..d8a0e4b5e3 100644 --- a/panda/src/pgraph/lightRampAttrib.I +++ b/panda/src/pgraph/lightRampAttrib.I @@ -28,7 +28,6 @@ LightRampAttrib() { _mode = LRT_identity; _level[0] = 0.0; _level[1] = 0.0; - _level[2] = 0.0; _threshold[0] = 0.0; _threshold[1] = 0.0; } @@ -50,7 +49,7 @@ get_mode() const { //////////////////////////////////////////////////////////////////// INLINE float LightRampAttrib:: get_level(int n) const { - if ((n<0)||(n>2)) return 0.0; + if ((n<0)||(n>1)) return 0.0; return _level[n]; } diff --git a/panda/src/pgraph/lightRampAttrib.cxx b/panda/src/pgraph/lightRampAttrib.cxx index dc58bc4b91..dd8c50c077 100644 --- a/panda/src/pgraph/lightRampAttrib.cxx +++ b/panda/src/pgraph/lightRampAttrib.cxx @@ -48,12 +48,11 @@ make_identity() { // Description: Constructs a new LightRampAttrib object. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) LightRampAttrib:: -make_single_threshold(float val0, float val1, float thresh0) { +make_single_threshold(float thresh0, float val0) { LightRampAttrib *attrib = new LightRampAttrib(); attrib->_mode = LRT_single_threshold; - attrib->_level[0] = val0; - attrib->_level[1] = val1; attrib->_threshold[0] = thresh0; + attrib->_level[0] = val0; return return_new(attrib); } @@ -63,14 +62,13 @@ make_single_threshold(float val0, float val1, float thresh0) { // Description: Constructs a new LightRampAttrib object. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) LightRampAttrib:: -make_double_threshold(float val0, float val1, float val2, float thresh0, float thresh1) { +make_double_threshold(float thresh0, float val0, float thresh1, float val1) { LightRampAttrib *attrib = new LightRampAttrib(); attrib->_mode = LRT_single_threshold; - attrib->_level[0] = val0; - attrib->_level[1] = val1; - attrib->_level[2] = val2; attrib->_threshold[0] = thresh0; + attrib->_level[0] = val0; attrib->_threshold[1] = thresh1; + attrib->_level[1] = val1; return return_new(attrib); } @@ -118,7 +116,7 @@ compare_to_impl(const RenderAttrib *other) const { if (compare_result!=0) { return compare_result; } - for (int i=0; i<3; i++) { + for (int i=0; i<2; i++) { compare_result = _level[i] - ta->_level[i]; if (compare_result!=0) { return compare_result; @@ -182,7 +180,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); dg.add_int8(_mode); - for (int i=0; i<3; i++) { + for (int i=0; i<2; i++) { dg.add_float32(_level[i]); } for (int i=0; i<2; i++) { @@ -222,7 +220,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { RenderAttrib::fillin(scan, manager); _mode = (LightRampMode)scan.get_int8(); - for (int i=0; i<3; i++) { + for (int i=0; i<2; i++) { _level[i] = scan.get_float32(); } for (int i=0; i<2; i++) { diff --git a/panda/src/pgraph/lightRampAttrib.h b/panda/src/pgraph/lightRampAttrib.h index 8eae520dea..4732570c77 100644 --- a/panda/src/pgraph/lightRampAttrib.h +++ b/panda/src/pgraph/lightRampAttrib.h @@ -33,7 +33,9 @@ class FactoryParams; // // LightRampAttrib is relevant only when lighting and // shader generation are both enabled. Otherwise, it has -// no effect. +// no effect. The light ramp only affects the diffuse +// contribution. Ambient light is not ramped. +// //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH LightRampAttrib : public RenderAttrib { private: @@ -46,8 +48,8 @@ PUBLISHED: LRT_double_threshold, }; static CPT(RenderAttrib) make_identity(); - static CPT(RenderAttrib) make_single_threshold(float lev0, float lev1, float thresh0); - static CPT(RenderAttrib) make_double_threshold(float lev0, float lev1, float lev2, float thresh0, float thresh1); + static CPT(RenderAttrib) make_single_threshold(float thresh0, float lev0); + static CPT(RenderAttrib) make_double_threshold(float thresh0, float lev0, float thresh1, float lev1); INLINE LightRampMode get_mode() const; INLINE float get_level(int n) const; @@ -63,7 +65,7 @@ protected: private: LightRampMode _mode; - float _level[3]; + float _level[2]; float _threshold[2]; static CPT(RenderAttrib) LightRampAttrib::_identity; diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index e292a74ed8..9b9f67fe0c 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -3,6 +3,7 @@ #include "antialiasAttrib.cxx" #include "attribNodeRegistry.cxx" #include "audioVolumeAttrib.cxx" +#include "auxBitplaneAttrib.cxx" #include "auxSceneData.cxx" #include "attribSlots.cxx" #include "bamFile.cxx" diff --git a/panda/src/pgraph/shaderGenerator.cxx b/panda/src/pgraph/shaderGenerator.cxx index 53c115a44b..759d9dd40f 100644 --- a/panda/src/pgraph/shaderGenerator.cxx +++ b/panda/src/pgraph/shaderGenerator.cxx @@ -146,6 +146,16 @@ analyze_renderstate(const RenderState *rs) { rs->store_into_slots(&_attribs); + // Figure out which bitplane should hold which output. + + int next = 0; + if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_color) { + _bitplane_color = next++; + } + if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_csnormal) { + _bitplane_normal = next++; + } + // Count number of textures. _num_textures = 0; @@ -155,7 +165,7 @@ analyze_renderstate(const RenderState *rs) { // Determine whether or not vertex colors or flat colors are present. - if (_attribs._color != 0) { + if ((_bitplane_color >= 0)&&(_attribs._color != 0)) { if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) { _vertex_colors = true; } else if (_attribs._color->get_color_type() == ColorAttrib::T_flat) { @@ -211,10 +221,11 @@ analyze_renderstate(const RenderState *rs) { // Determine whether lighting is needed. - if (_attribs._light->get_num_on_lights() > 0) { + if ((_bitplane_color >= 0) && + (_attribs._light->get_num_on_lights() > 0)) { _lighting = true; } - + // Find the material. if (!_attribs._material->is_off()) { @@ -225,7 +236,7 @@ analyze_renderstate(const RenderState *rs) { // Decide which material modes need to be calculated. - if (_alights.size() > 0) { + if (_lighting && (_alights.size() > 0)) { if (_material->has_ambient()) { Colorf a = _material->get_ambient(); if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) { @@ -236,7 +247,7 @@ analyze_renderstate(const RenderState *rs) { } } - if (_dlights.size() + _plights.size() + _slights.size()) { + if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) { if (_material->has_diffuse()) { Colorf d = _material->get_diffuse(); if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) { @@ -247,14 +258,14 @@ analyze_renderstate(const RenderState *rs) { } } - if (_material->has_emission()) { + if (_lighting && (_material->has_emission())) { Colorf e = _material->get_emission(); if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) { _have_emission = true; } } - if (_dlights.size() + _plights.size() + _slights.size()) { + if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) { if (_material->has_specular()) { Colorf s = _material->get_specular(); if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) { @@ -283,13 +294,11 @@ analyze_renderstate(const RenderState *rs) { } } - if (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity) { - if (_separate_ambient_diffuse) { - pgraph_cat.error() << "Light Ramp incompatible with separate ambient/diffuse\n"; - _separate_ambient_diffuse = false; - } + if (_lighting && + (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity)) { + _separate_ambient_diffuse = true; } - + // Does the shader need material properties as input? _need_material_props = @@ -322,8 +331,11 @@ clear_analysis() { _map_index_height = -1; _map_index_glow = -1; _map_index_gloss = -1; + _bitplane_color = -1; + _bitplane_normal = -1; _attribs.clear_to_defaults(); _material = (Material*)NULL; + _need_material_props = false; _alights.clear(); _dlights.clear(); _plights.clear(); @@ -391,6 +403,9 @@ create_shader_attrib(const string &txt) { // - other TextureStage::Modes // - cartoon thresholding and other special effects // +// Potential optimizations +// - omit attenuation calculations if attenuation off +// //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ShaderGenerator:: synthesize_shader(const RenderState *rs) { @@ -406,15 +421,16 @@ synthesize_shader(const RenderState *rs) { char *tangent_freg = 0; char *binormal_vreg = 0; char *binormal_freg = 0; + char *csnormal_freg = 0; pvector texcoord_vreg; pvector texcoord_freg; pvector tslightvec_freg; - + if (_vertex_colors) { _vcregs_used = 1; _fcregs_used = 1; } - + // Generate the shader's text. ostringstream text; @@ -450,6 +466,15 @@ synthesize_shader(const RenderState *rs) { text << "\t out float4 l_binormal : " << binormal_freg << ",\n"; } } + if (_bitplane_normal >= 0) { + if (normal_vreg == 0) { + normal_vreg = alloc_vreg(); + text << "\t in float4 vtx_normal : " << normal_vreg << ",\n"; + } + csnormal_freg = alloc_freg(); + text << "\t uniform float4x4 itp_modelview,\n"; + text << "\t out float4 l_csnormal : " << csnormal_freg << ",\n"; + } text << "\t float4 vtx_position : POSITION,\n"; text << "\t out float4 l_position : POSITION,\n"; @@ -467,11 +492,15 @@ synthesize_shader(const RenderState *rs) { if (_lighting) { text << "\t l_pos = vtx_position;\n"; text << "\t l_normal = vtx_normal;\n"; - if (_map_index_normal) { + if (_map_index_normal >= 0) { text << "\t l_tangent = vtx_tangent" << _map_index_normal << ";\n"; text << "\t l_binormal = -vtx_binormal" << _map_index_normal << ";\n"; } } + if (_bitplane_normal >= 0) { + text << "\t l_csnormal.xyz = mul(itp_modelview, vtx_normal);\n"; + text << "\t l_csnormal.w = 0;\n"; + } text << "}\n\n"; text << "void fshader(\n"; @@ -480,17 +509,14 @@ synthesize_shader(const RenderState *rs) { text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n"; text << "\t uniform sampler2D tex_" << i << ",\n"; } - if (_vertex_colors) { - text << "\t in float4 l_color : COLOR,\n"; - } else { - text << "\t uniform float4 attr_color,\n"; - } if (_lighting) { text << "\t in float3 l_normal : " << normal_freg << ",\n"; - if (_map_index_normal) { + if (_map_index_normal >= 0) { text << "\t in float3 l_tangent : " << tangent_freg << ",\n"; text << "\t in float3 l_binormal : " << binormal_freg << ",\n"; } + } + if (_lighting) { text << "\t in float4 l_pos : " << pos_freg << ",\n"; for (int i=0; i<(int)_alights.size(); i++) { text << "\t uniform float4 alight_alight" << i << ",\n"; @@ -516,15 +542,28 @@ synthesize_shader(const RenderState *rs) { } } } - text << "\t out float4 o_color : COLOR\n"; + if (_bitplane_normal >= 0) { + text << "\t in float4 l_csnormal : " << csnormal_freg << ",\n"; + text << "\t out float4 o_csnormal : COLOR" << _bitplane_normal << ",\n"; + } + if (_bitplane_color >= 0) { + text << "\t out float4 o_color : COLOR" << _bitplane_color << ",\n"; + } + if (_vertex_colors) { + text << "\t in float4 l_color : COLOR\n"; + } else { + text << "\t uniform float4 attr_color\n"; + } text << ") {\n"; + if (_bitplane_color < 0) { + text << "float4 \t o_color;\n"; + } text << "\t // Fetch all textures.\n"; for (int i=0; i<_num_textures; i++) { text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n"; } - if (_lighting) { - if (_map_index_normal) { + if (_map_index_normal >= 0) { text << "\t // Translate tangent-space normal in map to model-space.\n"; text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n"; text << "\t l_normal = l_normal * tsnormal.z;\n"; @@ -535,6 +574,12 @@ synthesize_shader(const RenderState *rs) { text << "\t // Correct the surface normal for interpolation effects\n"; text << "\t l_normal = normalize(l_normal);\n"; } + } + if (_bitplane_normal >= 0) { + text << "\t // Output the camera-space surface normal\n"; + text << "\t o_csnormal = (normalize(l_csnormal)*0.5) + float4(0.5,0.5,0.5,0);\n"; + } + if (_lighting) { text << "\t // Begin model-space light calculations\n"; text << "\t float ldist,lattenv,langle;\n"; text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n"; @@ -641,11 +686,10 @@ synthesize_shader(const RenderState *rs) { { float t = _attribs._light_ramp->get_threshold(0); float l0 = _attribs._light_ramp->get_level(0); - float l1 = _attribs._light_ramp->get_level(1); text << "\t // Single-threshold light ramp\n"; text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n"; - text << "\t float lr_out = (lr_in < " << t << ") ? " << l0 << ":" << l1 << ";\n"; - text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n"; + text << "\t float lr_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n"; + text << "\t tot_diffuse = tot_diffuse * lr_scale;\n"; break; } case LightRampAttrib::LRT_double_threshold: @@ -692,12 +736,13 @@ synthesize_shader(const RenderState *rs) { text << "\t o_color += tot_diffuse;\n"; } } + // Use of lerp here is a workaround for a radeon driver bug. if (_vertex_colors) { - text << "\t o_color.a = l_color.a;\n"; + text << "\t o_color = lerp(o_color, l_color, float4(0,0,0,1));\n"; } else if (_flat_colors) { - text << "\t o_color.a = attr_color.a;\n"; + text << "\t o_color = lerp(o_color, attr_color, float4(0,0,0,1));\n"; } else { - text << "\t o_color.a = 1;\n"; + text << "\t o_color.a = lerp(o_color, float4(1,1,1,1), float4(0,0,0,1));\n"; } text << "\t // End model-space light calculations\n"; } else { diff --git a/panda/src/pgraph/shaderGenerator.h b/panda/src/pgraph/shaderGenerator.h index fc175575c2..4987623c5c 100644 --- a/panda/src/pgraph/shaderGenerator.h +++ b/panda/src/pgraph/shaderGenerator.h @@ -118,6 +118,9 @@ protected: int _map_index_glow; int _map_index_gloss; + int _bitplane_color; + int _bitplane_normal; + bool _need_material_props; void analyze_renderstate(const RenderState *rs);