mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -04:00
771 lines
28 KiB
C++
Executable File
771 lines
28 KiB
C++
Executable File
// Filename: shaderAttrib.cxx
|
|
// Created by: sshodhan (10Jul04)
|
|
// Updated by: fperazzi, PandaSE (06Apr10) (added more overloads
|
|
// for set_shader_input)
|
|
// Updated by: weifengh, PandaSE(15Apr10) (added overload for
|
|
// set_shader_auto)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pandabase.h"
|
|
#include "shaderAttrib.h"
|
|
#include "graphicsStateGuardianBase.h"
|
|
#include "bamReader.h"
|
|
#include "bamWriter.h"
|
|
#include "datagram.h"
|
|
#include "datagramIterator.h"
|
|
|
|
TypeHandle ShaderAttrib::_type_handle;
|
|
int ShaderAttrib::_attrib_slot;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::make_off
|
|
// Access: Published, Static
|
|
// Description: Constructs a new ShaderAttrib object that disables
|
|
// the use of shaders (it does not clear out all shader
|
|
// data, however.)
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
make_off() {
|
|
static CPT(RenderAttrib) _off_attrib;
|
|
if (_off_attrib == 0) {
|
|
ShaderAttrib *attrib = new ShaderAttrib;
|
|
attrib->_has_shader = true;
|
|
_off_attrib = return_new(attrib);
|
|
}
|
|
return _off_attrib;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::make
|
|
// Access: Published, Static
|
|
// Description: Constructs a new ShaderAttrib object with nothing
|
|
// set.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
make(const Shader *shader) {
|
|
static CPT(RenderAttrib) _null_attrib;
|
|
if (_null_attrib == 0) {
|
|
ShaderAttrib *attrib = new ShaderAttrib;
|
|
_null_attrib = return_new(attrib);
|
|
}
|
|
|
|
if (shader == NULL) {
|
|
return _null_attrib;
|
|
} else {
|
|
return DCAST(ShaderAttrib, _null_attrib)->set_shader(shader);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::make_default
|
|
// Access: Published, Static
|
|
// Description: Returns a RenderAttrib that corresponds to whatever
|
|
// the standard default properties for render attributes
|
|
// of this type ought to be.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
make_default() {
|
|
return return_new(new ShaderAttrib);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader(const Shader *s, int priority) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_shader = s;
|
|
result->_shader_priority = priority;
|
|
result->_auto_shader = false;
|
|
result->_has_shader = true;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_off
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_off(int priority) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_shader = NULL;
|
|
result->_shader_priority = priority;
|
|
result->_auto_shader = false;
|
|
result->_auto_normal_on = false;
|
|
result->_auto_glow_on = false;
|
|
result->_auto_gloss_on = false;
|
|
result->_auto_ramp_on = false;
|
|
result->_auto_shadow_on = false;
|
|
|
|
result->_has_shader = true;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_auto
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_auto(int priority) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_shader = NULL;
|
|
result->_shader_priority = priority;
|
|
result->_auto_shader = true;
|
|
result->_has_shader = true;
|
|
result->_auto_normal_on = true;
|
|
result->_auto_glow_on = true;
|
|
result->_auto_gloss_on = true;
|
|
result->_auto_ramp_on = true;
|
|
result->_auto_shadow_on = true;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_auto
|
|
// Access: Published
|
|
// Description: Set auto shader with bitmask to customize use,
|
|
// e.g., to keep normal, glow, etc., on or off
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_auto(BitMask32 shader_switch, int priority) const {
|
|
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_shader = NULL;
|
|
result->_shader_priority = priority;
|
|
result->_auto_shader = true;
|
|
result->_has_shader = true;
|
|
result->_auto_normal_on = shader_switch.get_bit(Shader::bit_AutoShaderNormal);
|
|
result->_auto_glow_on = shader_switch.get_bit(Shader::bit_AutoShaderGlow);
|
|
result->_auto_gloss_on = shader_switch.get_bit(Shader::bit_AutoShaderGloss);
|
|
result->_auto_ramp_on = shader_switch.get_bit(Shader::bit_AutoShaderRamp);
|
|
result->_auto_shadow_on = shader_switch.get_bit(Shader::bit_AutoShaderShadow);
|
|
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::clear_shader
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
clear_shader() const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_shader = NULL;
|
|
result->_shader_priority = 0;
|
|
result->_auto_shader = false;
|
|
result->_has_shader = false;
|
|
result->_auto_normal_on = false;
|
|
result->_auto_glow_on = false;
|
|
result->_auto_gloss_on = false;
|
|
result->_auto_ramp_on = false;
|
|
result->_auto_shadow_on = false;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_flag
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_flag(int flag, bool value) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
int bit = 1<<flag;
|
|
if (value) {
|
|
result->_flags |= bit;
|
|
} else {
|
|
result->_flags &= ~bit;
|
|
}
|
|
result->_has_flags |= bit;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::clear_flag
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
clear_flag(int flag) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
int bit = 1<<flag;
|
|
result->_flags &= ~bit;
|
|
result->_has_flags &= ~bit;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const ShaderInput *input) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
Inputs::iterator i = result->_inputs.find(input->get_name());
|
|
if (i == result->_inputs.end()) {
|
|
result->_inputs.insert(Inputs::value_type(input->get_name(),input));
|
|
} else {
|
|
i->second = input;
|
|
}
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_float &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_double &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_LVecBase4 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_LVecBase3 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_LVecBase2 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const LVecBase4 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const LVecBase3 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const LVecBase2 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_LMatrix4 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const PTA_LMatrix3 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const LMatrix4 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const LMatrix3 &v, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,v,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, Texture *tex, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,tex,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, const NodePath &np, int priority) const {
|
|
return set_shader_input(new ShaderInput(id,np,priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_shader_input(const InternalName *id, double n1, double n2, double n3, double n4, int priority) const {
|
|
return set_shader_input(new ShaderInput(id, LVecBase4(n1,n2,n3,n4), priority));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::set_instance_count
|
|
// Access: Published
|
|
// Description: Sets the geometry instance count. Do not confuse
|
|
// this with instanceTo, which is used for animation
|
|
// instancing, and has nothing to do with this.
|
|
// A value of 0 means not to use instancing at all.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
set_instance_count(int instance_count) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_instance_count = instance_count;
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::clear_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
clear_shader_input(const InternalName *id) const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_inputs.erase(id);
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::clear_shader_input
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
clear_shader_input(const string &id) const {
|
|
return clear_shader_input(InternalName::make(id));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::clear_all_shader_inputs
|
|
// Access: Published
|
|
// Description: Clears all the shader inputs on the attrib.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
clear_all_shader_inputs() const {
|
|
ShaderAttrib *result = new ShaderAttrib(*this);
|
|
result->_inputs.clear();
|
|
return return_new(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput of the given name. If
|
|
// no such name is found, this function does not return
|
|
// NULL --- it returns the "blank" ShaderInput.
|
|
////////////////////////////////////////////////////////////////////
|
|
const ShaderInput *ShaderAttrib::
|
|
get_shader_input(const InternalName *id) const {
|
|
Inputs::const_iterator i = _inputs.find(id);
|
|
if (i == _inputs.end()) {
|
|
return ShaderInput::get_blank();
|
|
} else {
|
|
return (*i).second;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput of the given name. If
|
|
// no such name is found, this function does not return
|
|
// NULL --- it returns the "blank" ShaderInput.
|
|
////////////////////////////////////////////////////////////////////
|
|
const ShaderInput *ShaderAttrib::
|
|
get_shader_input(const string &id) const {
|
|
return get_shader_input(InternalName::make(id));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input_nodepath
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput as a nodepath. Assertion
|
|
// fails if there is none, or if it is not a nodepath.
|
|
////////////////////////////////////////////////////////////////////
|
|
const NodePath &ShaderAttrib::
|
|
get_shader_input_nodepath(const InternalName *id) const {
|
|
static NodePath resfail;
|
|
Inputs::const_iterator i = _inputs.find(id);
|
|
if (i == _inputs.end()) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not present.\n";
|
|
nassert_raise(strm.str());
|
|
return resfail;
|
|
} else {
|
|
const ShaderInput *p = (*i).second;
|
|
if (p->get_value_type() != ShaderInput::M_nodepath) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not a nodepath.\n";
|
|
nassert_raise(strm.str());
|
|
return resfail;
|
|
}
|
|
return p->get_nodepath();
|
|
}
|
|
|
|
// Satisfy compiler.
|
|
return resfail;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input_vector
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput as a vector. Assertion
|
|
// fails if there is none, or if it is not a vector.
|
|
////////////////////////////////////////////////////////////////////
|
|
const LVecBase4 &ShaderAttrib::
|
|
get_shader_input_vector(InternalName *id) const {
|
|
static LVecBase4 resfail(0,0,0,0);
|
|
Inputs::const_iterator i = _inputs.find(id);
|
|
if (i == _inputs.end()) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not present.\n";
|
|
nassert_raise(strm.str());
|
|
return resfail;
|
|
} else {
|
|
const ShaderInput *p = (*i).second;
|
|
if (p->get_value_type() != ShaderInput::M_numeric) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not a vector.\n";
|
|
nassert_raise(strm.str());
|
|
return resfail;
|
|
}
|
|
return p->get_vector();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input_ptr
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput as a ShaderPtrData struct.
|
|
// Assertion fails if there is none. or if it is not
|
|
// a PTA(double/float)
|
|
////////////////////////////////////////////////////////////////////
|
|
const Shader::ShaderPtrData *ShaderAttrib::
|
|
get_shader_input_ptr(const InternalName *id) const {
|
|
Inputs::const_iterator i = _inputs.find(id);
|
|
if (i == _inputs.end()) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not present.\n";
|
|
nassert_raise(strm.str());
|
|
return NULL;
|
|
} else {
|
|
const ShaderInput *p = (*i).second;
|
|
if (p->get_value_type() != ShaderInput::M_numeric) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not a PTA(float/double) type.\n";
|
|
nassert_raise(strm.str());
|
|
return NULL;
|
|
}
|
|
return &(p->get_ptr());
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader_input_texture
|
|
// Access: Published
|
|
// Description: Returns the ShaderInput as a texture. Assertion
|
|
// fails if there is none, or if it is not a texture.
|
|
////////////////////////////////////////////////////////////////////
|
|
Texture *ShaderAttrib::
|
|
get_shader_input_texture(const InternalName *id) const {
|
|
Inputs::const_iterator i = _inputs.find(id);
|
|
if (i == _inputs.end()) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not present.\n";
|
|
nassert_raise(strm.str());
|
|
return NULL;
|
|
} else {
|
|
const ShaderInput *p = (*i).second;
|
|
if (p->get_value_type() != ShaderInput::M_texture) {
|
|
ostringstream strm;
|
|
strm << "Shader input " << id->get_name() << " is not a texture.\n";
|
|
nassert_raise(strm.str());
|
|
return NULL;
|
|
}
|
|
return p->get_texture();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_shader
|
|
// Access: Published
|
|
// Description: Returns the shader object associated with the node.
|
|
// If get_override returns true, but get_shader
|
|
// returns NULL, that means that this attribute should
|
|
// disable the shader.
|
|
////////////////////////////////////////////////////////////////////
|
|
const Shader *ShaderAttrib::
|
|
get_shader() const {
|
|
return _shader;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::compare_to_impl
|
|
// Access: Protected, Virtual
|
|
// Description: Intended to be overridden by derived ShaderAttrib
|
|
// types to return a unique number indicating whether
|
|
// this ShaderAttrib is equivalent to the other one.
|
|
//
|
|
// This should return 0 if the two ShaderAttrib 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 ShaderAttrib
|
|
// objects whose get_type() functions return the same.
|
|
////////////////////////////////////////////////////////////////////
|
|
int ShaderAttrib::
|
|
compare_to_impl(const RenderAttrib *other) const {
|
|
const ShaderAttrib *that;
|
|
DCAST_INTO_R(that, other, 0);
|
|
|
|
if (this->_shader != that->_shader) {
|
|
return (this->_shader < that->_shader) ? -1 : 1;
|
|
}
|
|
if (this->_shader_priority != that->_shader_priority) {
|
|
return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
|
|
}
|
|
if (this->_auto_shader != that->_auto_shader) {
|
|
return (this->_auto_shader < that->_auto_shader) ? -1 : 1;
|
|
}
|
|
if (this->_has_shader != that->_has_shader) {
|
|
return (this->_has_shader < that->_has_shader) ? -1 : 1;
|
|
}
|
|
if (this->_flags != that->_flags) {
|
|
return (this->_flags < that->_flags) ? -1 : 1;
|
|
}
|
|
if (this->_has_flags != that->_has_flags) {
|
|
return (this->_has_flags < that->_has_flags) ? -1 : 1;
|
|
}
|
|
if (this->_instance_count != that->_instance_count) {
|
|
return (this->_instance_count < that->_instance_count) ? -1 : 1;
|
|
}
|
|
if (this->_auto_normal_on != that->_auto_normal_on) {
|
|
return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1;
|
|
}
|
|
if (this->_auto_glow_on != that->_auto_glow_on) {
|
|
return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1;
|
|
}
|
|
if (this->_auto_gloss_on != that->_auto_gloss_on) {
|
|
return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1;
|
|
}
|
|
if (this->_auto_ramp_on != that->_auto_ramp_on) {
|
|
return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1;
|
|
}
|
|
if (this->_auto_shadow_on != that->_auto_shadow_on) {
|
|
return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1;
|
|
}
|
|
|
|
Inputs::const_iterator i1 = this->_inputs.begin();
|
|
Inputs::const_iterator i2 = that->_inputs.begin();
|
|
while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) {
|
|
if (i1->second != i2->second) {
|
|
return (i1->second < i2->second) ? -1 : 1;
|
|
}
|
|
++i1;
|
|
++i2;
|
|
}
|
|
if (i1 != this->_inputs.end()) {
|
|
return 1;
|
|
}
|
|
if (i2 != that->_inputs.end()) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_hash_impl
|
|
// Access: Protected, Virtual
|
|
// Description: Intended to be overridden by derived RenderAttrib
|
|
// types to return a unique hash for these particular
|
|
// properties. RenderAttribs that compare the same with
|
|
// compare_to_impl(), above, should return the same
|
|
// hash; RenderAttribs that compare differently should
|
|
// return a different hash.
|
|
////////////////////////////////////////////////////////////////////
|
|
size_t ShaderAttrib::
|
|
get_hash_impl() const {
|
|
size_t hash = 0;
|
|
hash = pointer_hash::add_hash(hash, _shader);
|
|
hash = int_hash::add_hash(hash, _shader_priority);
|
|
hash = int_hash::add_hash(hash, (int)_auto_shader);
|
|
hash = int_hash::add_hash(hash, (int)_has_shader);
|
|
hash = int_hash::add_hash(hash, _flags);
|
|
hash = int_hash::add_hash(hash, _has_flags);
|
|
hash = int_hash::add_hash(hash, _instance_count);
|
|
hash = int_hash::add_hash(hash, (int)_auto_normal_on);
|
|
hash = int_hash::add_hash(hash, (int)_auto_glow_on);
|
|
hash = int_hash::add_hash(hash, (int)_auto_gloss_on);
|
|
hash = int_hash::add_hash(hash, (int)_auto_shadow_on);
|
|
|
|
Inputs::const_iterator ii;
|
|
for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
|
|
hash = pointer_hash::add_hash(hash, (*ii).first);
|
|
hash = pointer_hash::add_hash(hash, (*ii).second);
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::compose_impl
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
compose_impl(const RenderAttrib *other) const {
|
|
ShaderAttrib *attr = new ShaderAttrib(*this);
|
|
const ShaderAttrib *over;
|
|
DCAST_INTO_R(over, other, 0);
|
|
// Update the shader portion.
|
|
if (over->_has_shader) {
|
|
if ((attr->_has_shader == false) ||
|
|
(over->_shader_priority >= attr->_shader_priority)) {
|
|
attr->_shader = over->_shader;
|
|
attr->_shader_priority = over->_shader_priority;
|
|
attr->_auto_shader = over->_auto_shader;
|
|
attr->_has_shader = over->_has_shader;
|
|
attr->_auto_normal_on = over->_auto_normal_on;
|
|
attr->_auto_glow_on = over->_auto_glow_on;
|
|
attr->_auto_gloss_on = over->_auto_gloss_on;
|
|
attr->_auto_ramp_on = over->_auto_ramp_on;
|
|
attr->_auto_shadow_on = over->_auto_shadow_on;
|
|
}
|
|
}
|
|
// Update the shader-data portion.
|
|
Inputs::const_iterator iover;
|
|
for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
|
|
const InternalName *id = (*iover).first;
|
|
const ShaderInput *dover = (*iover).second;
|
|
Inputs::iterator iattr = attr->_inputs.find(id);
|
|
if (iattr == attr->_inputs.end()) {
|
|
attr->_inputs.insert(Inputs::value_type(id,dover));
|
|
} else {
|
|
const ShaderInput *dattr = (*iattr).second;
|
|
if (dattr->get_priority() <= dover->get_priority()) {
|
|
iattr->second = iover->second;
|
|
}
|
|
}
|
|
}
|
|
// Just copy the instance count.
|
|
attr->_instance_count = over->_instance_count;
|
|
// Update the flags.
|
|
attr->_flags &= ~(over->_has_flags);
|
|
attr->_flags |= over->_flags;
|
|
attr->_has_flags |= (over->_has_flags);
|
|
return return_new(attr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::get_auto_shader_attrib_impl
|
|
// Access: Protected, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderAttrib) ShaderAttrib::
|
|
get_auto_shader_attrib_impl(const RenderState *state) const {
|
|
// For a ShaderAttrib, we only need to preserve the auto-shader
|
|
// flags. Custom shaders, and custom shader inputs, aren't relevant
|
|
// to the shader generator.
|
|
ShaderAttrib *attrib = new ShaderAttrib;
|
|
attrib->_auto_shader = _auto_shader;
|
|
attrib->_has_shader = _has_shader;
|
|
attrib->_auto_normal_on = _auto_normal_on;
|
|
attrib->_auto_glow_on = _auto_glow_on;
|
|
attrib->_auto_gloss_on = _auto_gloss_on;
|
|
attrib->_auto_ramp_on = _auto_ramp_on;
|
|
attrib->_auto_shadow_on = _auto_shadow_on;
|
|
return return_new(attrib);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ShaderAttrib::register_with_read_factory
|
|
// Access: Public, Static
|
|
// Description: Factory method to generate a Shader object
|
|
////////////////////////////////////////////////////////////////////
|
|
void ShaderAttrib::
|
|
register_with_read_factory() {
|
|
// IMPLEMENT ME
|
|
}
|
|
|