Merge branch 'master' into deploy-ng

This commit is contained in:
Mitchell Stokes 2017-06-30 21:38:34 -07:00
commit e13ad8e146
33 changed files with 555 additions and 162 deletions

View File

@ -50,6 +50,10 @@ class Actor(DirectObject, NodePath):
def __repr__(self):
return 'Actor.PartDef(%s, %s)' % (repr(self.partBundleNP), repr(self.partModel))
#snake_case alias:
get_bundle = getBundle
class AnimDef:
"""Instances of this class are stored within the
@ -72,6 +76,10 @@ class Actor(DirectObject, NodePath):
def __repr__(self):
return 'Actor.AnimDef(%s)' % (repr(self.filename))
#snake_case alias:
make_copy = makeCopy
class SubpartDef:
"""Instances of this class are stored within the SubpartDict
@ -2549,3 +2557,89 @@ class Actor(DirectObject, NodePath):
for partBundleDict in self.__partBundleDict.values():
partDef = partBundleDict.get(subpartDef.truePartName)
partDef.getBundle().setName(newBundleName)
#snake_case alias:
control_joint = controlJoint
set_lod_animation = setLODAnimation
get_anim_control_dict = getAnimControlDict
get_actor_info = getActorInfo
clear_lod_animation = clearLODAnimation
reset_lod = resetLOD
fix_bounds = fixBounds
get_anim_filename = getAnimFilename
get_subparts_complete = getSubpartsComplete
verify_subparts_complete = verifySubpartsComplete
get_play_rate = getPlayRate
clear_python_data = clearPythonData
load_anims = loadAnims
set_subparts_complete = setSubpartsComplete
draw_in_front = drawInFront
get_lod_node = getLODNode
hide_part = hidePart
get_joint_transform_state = getJointTransformState
set_control_effect = setControlEffect
get_anim_controls = getAnimControls
release_joint = releaseJoint
print_anim_blends = printAnimBlends
get_lod = getLOD
disable_blend = disableBlend
show_part = showPart
get_joint_transform = getJointTransform
face_away_from_viewer = faceAwayFromViewer
set_lod = setLOD
osd_anim_blends = osdAnimBlends
get_current_frame = getCurrentFrame
set_play_rate = setPlayRate
bind_all_anims = bindAllAnims
unload_anims = unloadAnims
remove_part = removePart
use_lod = useLOD
get_anim_blends = getAnimBlends
get_lod_index = getLODIndex
get_num_frames = getNumFrames
post_flatten = postFlatten
get_lod_names = getLODNames
list_joints = listJoints
make_subpart = makeSubpart
get_anim_control = getAnimControl
get_part_bundle = getPartBundle
get_part_bundle_dict = getPartBundleDict
get_duration = getDuration
has_lod = hasLOD
print_lod = printLOD
fix_bounds_old = fixBounds_old
get_anim_names = getAnimNames
get_part_bundles = getPartBundles
anim_panel = animPanel
stop_joint = stopJoint
actor_interval = actorInterval
hide_all_bounds = hideAllBounds
show_all_bounds = showAllBounds
init_anims_on_all_lods = initAnimsOnAllLODs
get_part = getPart
add_lod = addLOD
show_all_parts = showAllParts
get_joints = getJoints
get_overlapping_joints = getOverlappingJoints
enable_blend = enableBlend
face_towards_viewer = faceTowardsViewer
bind_anim = bindAnim
set_blend = setBlend
get_frame_time = getFrameTime
remove_node = removeNode
wait_pending = waitPending
expose_joint = exposeJoint
set_lod_node = setLODNode
get_frame_rate = getFrameRate
get_current_anim = getCurrentAnim
get_part_names = getPartNames
freeze_joint = freezeJoint
set_center = setCenter
rename_part_bundles = renamePartBundles
get_geom_node = getGeomNode
set_geom_node = setGeomNode
load_model = loadModel
copy_actor = copyActor
get_base_frame_rate = getBaseFrameRate
remove_anim_control_dict = removeAnimControlDict
load_anims_on_all_lods = loadAnimsOnAllLODs

View File

@ -21,6 +21,9 @@ class InputStateToken:
def __hash__(self):
return self._hash
#snake_case alias:
is_valid = isValid
class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
def release(self):
self._inputState._ignore(self)
@ -39,6 +42,9 @@ class InputStateTokenGroup:
token.release()
self._tokens = []
#snake_case alias:
add_token = addToken
class InputState(DirectObject.DirectObject):
"""
InputState is for tracking the on/off state of some events.
@ -235,3 +241,10 @@ class InputState(DirectObject.DirectObject):
"""for debugging"""
return self.notify.debug(
"%s (%s) %s"%(id(self), len(self._state), message))
#snake_case alias:
watch_with_modifiers = watchWithModifiers
is_set = isSet
get_event_name = getEventName
debug_print = debugPrint
release_inputs = releaseInputs

View File

@ -537,3 +537,24 @@ class CommonFilters:
del self.configuration["GammaAdjust"]
return self.reconfigure((old_gamma != 1.0), "GammaAdjust")
return True
#snake_case alias:
del_cartoon_ink = delCartoonInk
set_half_pixel_shift = setHalfPixelShift
del_half_pixel_shift = delHalfPixelShift
set_inverted = setInverted
del_inverted = delInverted
del_view_glow = delViewGlow
set_volumetric_lighting = setVolumetricLighting
del_gamma_adjust = delGammaAdjust
set_bloom = setBloom
set_view_glow = setViewGlow
set_ambient_occlusion = setAmbientOcclusion
set_cartoon_ink = setCartoonInk
del_bloom = delBloom
del_ambient_occlusion = delAmbientOcclusion
load_shader = loadShader
set_blur_sharpen = setBlurSharpen
del_blur_sharpen = delBlurSharpen
del_volumetric_lighting = delVolumetricLighting
set_gamma_adjust = setGammaAdjust

View File

@ -349,3 +349,15 @@ class FilterManager(DirectObject):
self.nextsort = self.win.getSort() - 1000
self.basex = 0
self.basey = 0
#snake_case alias:
is_fullscreen = isFullscreen
resize_buffers = resizeBuffers
set_stacked_clears = setStackedClears
render_scene_into = renderSceneInto
get_scaled_size = getScaledSize
render_quad_into = renderQuadInto
get_clears = getClears
set_clears = setClears
create_buffer = createBuffer
window_event = windowEvent

View File

@ -13,8 +13,9 @@ void vshader(float4 vtx_position : POSITION,
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
float offset = texpix_src.x;
l_texcoord0 = float4(c.x-offset* -4, c.x-offset* -3, c.x-offset* -2, c.y);
l_texcoord1 = float4(c.x-offset* -1, c.x-offset* 0, c.x-offset* 1, c.y);
float pad = texpad_src.x * 2;
l_texcoord0 = float4(min(c.x-offset* -4, pad), min(c.x-offset* -3, pad), min(c.x-offset* -2, pad), c.y);
l_texcoord1 = float4(min(c.x-offset* -1, pad), c.x-offset* 0, c.x-offset* 1, c.y);
l_texcoord2 = float4(c.x-offset* 2, c.x-offset* 3, c.x-offset* 4, c.y);
}

View File

@ -13,8 +13,9 @@ void vshader(float4 vtx_position : POSITION,
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
float offset = texpix_src.y;
l_texcoord0 = float4(c.y-offset* -4, c.y-offset* -3, c.y-offset* -2, c.x);
l_texcoord1 = float4(c.y-offset* -1, c.y-offset* 0, c.y-offset* 1, c.x);
float pad = texpad_src.y * 2;
l_texcoord0 = float4(min(c.y-offset* -4, pad), min(c.y-offset* -3, pad), min(c.y-offset* -2, pad), c.x);
l_texcoord1 = float4(min(c.y-offset* -1, pad), c.y-offset* 0, c.y-offset* 1, c.x);
l_texcoord2 = float4(c.y-offset* 2, c.y-offset* 3, c.y-offset* 4, c.x);
}

View File

@ -18,16 +18,18 @@ void vshader(float4 vtx_position : POSITION,
void fshader(float2 l_texcoord0 : TEXCOORD0,
out float4 o_color : COLOR,
uniform float2 texpix_src,
uniform float4 texpad_src,
uniform sampler2D k_src : TEXUNIT0)
{
float pad = texpad_src.x * 2;
float3 offset = float3(1.0*texpix_src.x, 2.0*texpix_src.x, 3.0*texpix_src.x);
o_color = tex2D(k_src, l_texcoord0);
o_color += tex2D(k_src, float2(l_texcoord0.x - offset.z, l_texcoord0.y));
o_color += tex2D(k_src, float2(l_texcoord0.x - offset.y, l_texcoord0.y));
o_color += tex2D(k_src, float2(l_texcoord0.x - offset.x, l_texcoord0.y));
o_color += tex2D(k_src, float2(l_texcoord0.x + offset.x, l_texcoord0.y));
o_color += tex2D(k_src, float2(l_texcoord0.x + offset.y, l_texcoord0.y));
o_color += tex2D(k_src, float2(l_texcoord0.x + offset.z, l_texcoord0.y));
o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.x, pad), l_texcoord0.y));
o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.y, pad), l_texcoord0.y));
o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.z, pad), l_texcoord0.y));
o_color /= 7;
o_color.w = 1;
}

View File

@ -18,16 +18,18 @@ void vshader(float4 vtx_position : POSITION,
void fshader(float2 l_texcoord0 : TEXCOORD0,
out float4 o_color : COLOR,
uniform float2 texpix_src,
uniform float4 texpad_src,
uniform sampler2D k_src : TEXUNIT0)
{
float pad = texpad_src.y * 2;
float3 offset = float3(1.0*texpix_src.y, 2.0*texpix_src.y, 3.0*texpix_src.y);
o_color = tex2D(k_src, l_texcoord0);
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.z));
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.y));
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.x));
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.x));
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.y));
o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.z));
o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.x, pad)));
o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.y, pad)));
o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.z, pad)));
o_color /= 7;
o_color.w = 1;
}

View File

@ -289,3 +289,27 @@ class Audio3DManager:
for sound in self.sound_dict[object]:
self.detachSound(sound)
#snake_case alias:
get_doppler_factor = getDopplerFactor
set_listener_velocity_auto = setListenerVelocityAuto
attach_listener = attachListener
set_distance_factor = setDistanceFactor
attach_sound_to_object = attachSoundToObject
get_drop_off_factor = getDropOffFactor
set_doppler_factor = setDopplerFactor
get_sounds_on_object = getSoundsOnObject
set_sound_velocity_auto = setSoundVelocityAuto
get_sound_max_distance = getSoundMaxDistance
load_sfx = loadSfx
get_distance_factor = getDistanceFactor
set_listener_velocity = setListenerVelocity
set_sound_max_distance = setSoundMaxDistance
get_sound_velocity = getSoundVelocity
get_listener_velocity = getListenerVelocity
set_sound_velocity = setSoundVelocity
set_sound_min_distance = setSoundMinDistance
get_sound_min_distance = getSoundMinDistance
detach_listener = detachListener
set_drop_off_factor = setDropOffFactor
detach_sound = detachSound

View File

@ -101,3 +101,15 @@ class DirectObject:
func = choice(getRepository()._crashOnProactiveLeakDetect,
self.notify.error, self.notify.warning)
func('destroyed %s instance is still %s%s' % (self.__class__.__name__, estr, tstr))
#snake_case alias:
add_task = addTask
do_method_later = doMethodLater
detect_leaks = detectLeaks
accept_once = acceptOnce
ignore_all = ignoreAll
get_all_accepting = getAllAccepting
is_ignoring = isIgnoring
remove_all_tasks = removeAllTasks
remove_task = removeTask
is_accepting = isAccepting

View File

@ -635,3 +635,16 @@ class Messenger:
str = str + '='*50 + '\n'
return str
#snake_case alias:
get_events = getEvents
is_ignoring = isIgnoring
who_accepts = whoAccepts
find_all = findAll
replace_method = replaceMethod
ignore_all = ignoreAll
is_accepting = isAccepting
is_empty = isEmpty
detailed_repr = detailedRepr
get_all_accepting = getAllAccepting
toggle_verbose = toggleVerbose

View File

@ -835,13 +835,16 @@ if (COMPILER=="GCC"):
# Needed when linking ffmpeg statically on Linux.
LibName("FFMPEG", "-Wl,-Bsymbolic")
cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
if cv_lib == "opencv_core":
OPENCV_VER_23 = True
SmartPkgEnable("OPENCV", "opencv", ("opencv_core", "opencv_highgui"), ("opencv2/core/core.hpp"))
if PkgSkip("FFMPEG") or GetTarget() == "darwin":
cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
if cv_lib == "opencv_core":
OPENCV_VER_23 = True
SmartPkgEnable("OPENCV", "opencv", ("opencv_core", "opencv_highgui"), ("opencv2/core/core.hpp"))
else:
SmartPkgEnable("OPENCV", "opencv", ("cv", "highgui", "cvaux", "ml", "cxcore"),
("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h"))
else:
SmartPkgEnable("OPENCV", "opencv", ("cv", "highgui", "cvaux", "ml", "cxcore"),
("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h"))
PkgDisable("OPENCV")
rocket_libs = ("RocketCore", "RocketControls")
if (GetOptimize() <= 3):

View File

@ -1849,16 +1849,6 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
scene_setup->set_cs_world_transform(cs_world_transform);
// Make sure that the GSG has a ShaderGenerator for the munger to use. We
// have to do this here because the ShaderGenerator needs a host window
// pointer. Hopefully we'll be able to eliminate that requirement in the
// future.
#ifdef HAVE_CG
if (gsg->get_shader_generator() == NULL) {
gsg->set_shader_generator(new ShaderGenerator(gsg, window));
}
#endif
return scene_setup;
}

View File

@ -344,11 +344,11 @@ munge_state_impl(const RenderState *state) {
#ifdef HAVE_CG
if (_auto_shader) {
CPT(RenderState) shader_state = munged_state->get_auto_shader_state();
ShaderGenerator *shader_generator = get_gsg()->get_shader_generator();
if (shader_generator == NULL) {
pgraph_cat.error()
<< "auto_shader enabled, but GSG has no shader generator assigned!\n";
return munged_state;
GraphicsStateGuardian *gsg = get_gsg();
ShaderGenerator *shader_generator = gsg->get_shader_generator();
if (shader_generator == nullptr) {
shader_generator = new ShaderGenerator(gsg);
gsg->set_shader_generator(shader_generator);
}
if (shader_state->_generated_shader == NULL) {
// Cache the generated ShaderAttrib on the shader state.

View File

@ -56,12 +56,12 @@ PUBLISHED:
BLOCKING void ls(ostream &out = cout) const;
BLOCKING void ls_all(ostream &out = cout) const;
EXTENSION(BLOCKING PyObject *read_file(bool auto_unwrap) const);
EXTENSION(PyObject *read_file(bool auto_unwrap) const);
BLOCKING virtual istream *open_read_file(bool auto_unwrap) const;
BLOCKING virtual void close_read_file(istream *stream) const;
virtual bool was_read_successful() const;
EXTENSION(BLOCKING PyObject *write_file(PyObject *data, bool auto_wrap));
EXTENSION(PyObject *write_file(PyObject *data, bool auto_wrap));
BLOCKING virtual ostream *open_write_file(bool auto_wrap, bool truncate);
BLOCKING virtual ostream *open_append_file();
BLOCKING virtual void close_write_file(ostream *stream);

View File

@ -95,11 +95,11 @@ PUBLISHED:
static VirtualFileSystem *get_global_ptr();
EXTENSION(BLOCKING PyObject *read_file(const Filename &filename, bool auto_unwrap) const);
EXTENSION(PyObject *read_file(const Filename &filename, bool auto_unwrap) const);
BLOCKING istream *open_read_file(const Filename &filename, bool auto_unwrap) const;
BLOCKING static void close_read_file(istream *stream);
EXTENSION(BLOCKING PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap));
EXTENSION(PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap));
BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate);
BLOCKING ostream *open_append_file(const Filename &filename);
BLOCKING static void close_write_file(ostream *stream);

View File

@ -26,9 +26,22 @@
*/
PyObject *Extension<VirtualFileSystem>::
read_file(const Filename &filename, bool auto_unwrap) const {
// Release the GIL while we do this potentially slow operation.
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyThreadState *_save;
Py_UNBLOCK_THREADS
#endif
vector_uchar pv;
bool okflag = _this->read_file(filename, pv, auto_unwrap);
nassertr(okflag, NULL);
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
Py_BLOCK_THREADS
#endif
if (!okflag) {
return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", filename.c_str());
}
#if PY_MAJOR_VERSION >= 3
if (pv.empty()) {

View File

@ -26,9 +26,23 @@
*/
PyObject *Extension<VirtualFile>::
read_file(bool auto_unwrap) const {
// Release the GIL while we do this potentially slow operation.
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyThreadState *_save;
Py_UNBLOCK_THREADS
#endif
vector_uchar pv;
bool okflag = _this->read_file(pv, auto_unwrap);
nassertr(okflag, NULL);
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
Py_BLOCK_THREADS
#endif
if (!okflag) {
Filename fn = _this->get_filename();
return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", fn.c_str());
}
#if PY_MAJOR_VERSION >= 3
if (pv.empty()) {
@ -68,7 +82,18 @@ write_file(PyObject *data, bool auto_wrap) {
}
#endif
// Release the GIL while we do this potentially slow operation.
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyThreadState *_save;
Py_UNBLOCK_THREADS
#endif
bool result = _this->write_file((const unsigned char *)buffer, length, auto_wrap);
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
Py_BLOCK_THREADS
#endif
return PyBool_FromLong(result);
}

View File

@ -127,19 +127,7 @@ PUBLISHED:
MAKE_PROPERTY(local, get_local, set_local);
MAKE_PROPERTY(twoside, get_twoside, set_twoside);
private:
LColor _base_color;
LColor _ambient;
LColor _diffuse;
LColor _specular;
LColor _emission;
PN_stdfloat _shininess;
PN_stdfloat _roughness;
PN_stdfloat _metallic;
PN_stdfloat _refractive_index;
static PT(Material) _default;
public:
enum Flags {
F_ambient = 0x001,
F_diffuse = 0x002,
@ -153,8 +141,24 @@ private:
F_base_color = 0x200,
F_refractive_index = 0x400,
};
private:
LColor _base_color;
LColor _ambient;
LColor _diffuse;
LColor _specular;
LColor _emission;
PN_stdfloat _shininess;
PN_stdfloat _roughness;
PN_stdfloat _metallic;
PN_stdfloat _refractive_index;
static PT(Material) _default;
int _flags;
friend class MaterialAttrib;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);

View File

@ -428,7 +428,9 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_view_to_apiclip_x)) {
dep |= SSD_shaderinputs;
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) ||

View File

@ -18,6 +18,7 @@
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "auxBitplaneAttrib.h"
TypeHandle AlphaTestAttrib::_type_handle;
int AlphaTestAttrib::_attrib_slot;
@ -98,7 +99,15 @@ get_hash_impl() const {
*/
CPT(RenderAttrib) AlphaTestAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
return this;
// This is only important if the shader subsumes the alpha test, which only
// happens if there is an AuxBitplaneAttrib with ABO_glow.
const AuxBitplaneAttrib *aux;
if (!state->get_attrib(aux) ||
(aux->get_outputs() & AuxBitplaneAttrib::ABO_glow) == 0) {
return nullptr;
} else {
return this;
}
}
/**

View File

@ -15,6 +15,7 @@
#include "geom.h"
#include "geomTransformer.h"
#include "sceneGraphReducer.h"
#include "stateMunger.h"
#include "accumulatedAttribs.h"
#include "colorAttrib.h"
#include "colorScaleAttrib.h"
@ -391,33 +392,32 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
((GeomPrimitive *)prim.p())->prepare(prepared_objects);
}
if (munger->is_of_type(StateMunger::get_class_type())) {
StateMunger *state_munger = (StateMunger *)munger.p();
geom_state = state_munger->munge_state(geom_state);
}
// And now prepare each of the textures.
const RenderAttrib *attrib =
geom_state->get_attrib(TextureAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) {
const TextureAttrib *ta;
DCAST_INTO_V(ta, attrib);
const TextureAttrib *ta;
if (geom_state->get_attrib(ta)) {
int num_stages = ta->get_num_on_stages();
for (int i = 0; i < num_stages; ++i) {
Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
// TODO: prepare the sampler states, if specified.
if (texture != (Texture *)NULL) {
if (texture != nullptr) {
texture->prepare(prepared_objects);
}
}
}
// As well as the shaders.
attrib = geom_state->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) {
const ShaderAttrib *sa;
DCAST_INTO_V(sa, attrib);
const ShaderAttrib *sa;
if (geom_state->get_attrib(sa)) {
Shader *shader = (Shader *)sa->get_shader();
if (shader != (Shader *)NULL) {
if (shader != nullptr) {
shader->prepare(prepared_objects);
}
// TODO: prepare the shader inputs. TODO: Invoke the shader generator
// if enabled.
// TODO: prepare the shader inputs.
}
}

View File

@ -15,7 +15,7 @@
* Use MaterialAttrib::make() to construct a new MaterialAttrib object.
*/
INLINE MaterialAttrib::
MaterialAttrib() {
MaterialAttrib() : _flags(0) {
}
/**
@ -24,7 +24,7 @@ MaterialAttrib() {
*/
INLINE bool MaterialAttrib::
is_off() const {
return _material == (const Material *)NULL;
return _flags == 0;
}
/**
@ -35,3 +35,11 @@ INLINE Material *MaterialAttrib::
get_material() const {
return _material;
}
/**
* Equivalent to get_material()->get_flags().
*/
INLINE int MaterialAttrib::
get_material_flags() const {
return _flags;
}

View File

@ -30,6 +30,8 @@ make(Material *material) {
MaterialAttrib *attrib = new MaterialAttrib;
attrib->_material = material;
material->set_attrib_lock();
attrib->_flags = material->_flags;
nassertr(attrib->_flags & Material::F_attrib_lock, nullptr);
return return_new(attrib);
}
@ -58,10 +60,34 @@ make_default() {
void MaterialAttrib::
output(ostream &out) const {
out << get_type() << ":";
if (is_off()) {
if (_material != nullptr) {
out << *_material;
} else if (is_off()) {
out << "(off)";
} else {
out << *_material;
// This is a state returned from get_auto_shader_attrib().
out << "(on";
#ifndef NDEBUG
if (_flags & Material::F_ambient) {
out << " amb";
}
if (_flags & Material::F_diffuse) {
out << " diff";
}
if (_flags & Material::F_specular) {
out << " spec";
}
if (_flags & Material::F_emission) {
out << " emit";
}
if (_flags & Material::F_local) {
out << " local";
}
if (_flags & Material::F_twoside) {
out << " twoside";
}
#endif
out << ")";
}
}
@ -87,7 +113,7 @@ compare_to_impl(const RenderAttrib *other) const {
if (_material != ta->_material) {
return _material < ta->_material ? -1 : 1;
}
return 0;
return _flags < ta->_flags;
}
/**
@ -100,6 +126,7 @@ size_t MaterialAttrib::
get_hash_impl() const {
size_t hash = 0;
hash = pointer_hash::add_hash(hash, _material);
hash = int_hash::add_hash(hash, _flags);
return hash;
}
@ -108,7 +135,15 @@ get_hash_impl() const {
*/
CPT(RenderAttrib) MaterialAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
return this;
if (_material == nullptr) {
return this;
} else {
// Make a copy, but only with the flags, not with the material itself.
MaterialAttrib *attrib = new MaterialAttrib();
attrib->_material = nullptr;
attrib->_flags = _flags;
return return_new(attrib);
}
}
/**
@ -139,8 +174,12 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = RenderAttrib::complete_pointers(p_list, manager);
TypedWritable *material = p_list[pi++];
if (material != (TypedWritable *)NULL) {
if (material != nullptr) {
_material = DCAST(Material, material);
_flags = _material->_flags | Material::F_attrib_lock;
} else {
_material = nullptr;
_flags = 0;
}
return pi;

View File

@ -36,6 +36,9 @@ PUBLISHED:
INLINE bool is_off() const;
INLINE Material *get_material() const;
public:
INLINE int get_material_flags() const;
PUBLISHED:
MAKE_PROPERTY(material, get_material);
@ -49,6 +52,7 @@ protected:
private:
PT(Material) _material;
int _flags;
PUBLISHED:
static int get_class_slot() {

View File

@ -86,11 +86,14 @@ get_hash_impl() const {
CPT(RenderAttrib) RescaleNormalAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
// We currently only support M_normalize in the ShaderGenerator.
if (_mode == M_none || _mode == M_normalize) {
/*if (_mode == M_none || _mode == M_normalize) {
return this;
} else {
return RescaleNormalAttrib::make(M_normalize);
}
}*/
// Actually, we currently ignore this attribute in the shader generator,
// and always normalize the normals. It's too much of a bother.
return nullptr;
}
/**

View File

@ -523,14 +523,15 @@ void ShaderAttrib::
output(ostream &out) const {
out << "ShaderAttrib:";
if (_has_shader) {
if (_shader == NULL) {
if (_auto_shader) {
out << "auto";
return;
} else if (_has_shader) {
if (_shader == nullptr) {
out << "off";
} else {
out << _shader->get_filename().get_basename();
}
} else if (_auto_shader) {
out << "auto";
}
out << "," << _inputs.size() << " inputs";

View File

@ -140,6 +140,26 @@ get_on_texture(TextureStage *stage) const {
return NULL;
}
/**
* Returns the type of the texture associated with the indicated stage. It is
* an error to call this if has_on_stage(stage) returns false.
*
* This method is no different than get_on_texture(stage)->get_texture_type();
* it merely exists to address a corner case for the shader generator.
*/
INLINE Texture::TextureType TextureAttrib::
get_on_texture_type(TextureStage *stage) const {
Stages::const_iterator si;
si = _on_stages.find(StageNode(stage));
nassertr(si != _on_stages.end(), Texture::TT_2d_texture);
if ((*si)._texture == nullptr) {
return (*si)._texture_type;
} else {
return (*si)._texture->get_texture_type();
}
}
/**
* Returns the sampler associated with the indicated stage, or the one
* associated with its texture if no custom stage has been specified. It is
@ -215,6 +235,26 @@ is_identity() const {
return _on_stages.empty() && _off_stages.empty() && !_off_all_stages;
}
/**
* Call only on a state returned by get_auto_shader_attrib.
*/
bool TextureAttrib::
on_stage_affects_rgb(size_t n) const {
nassertr(n < _render_stages.size(), false);
StageNode *stage = _render_stages[n];
return stage->_texture_affects_rgb;
}
/**
* Call only on a state returned by get_auto_shader_attrib.
*/
bool TextureAttrib::
on_stage_affects_alpha(size_t n) const {
nassertr(n < _render_stages.size(), false);
StageNode *stage = _render_stages[n];
return stage->_texture_affects_alpha;
}
/**
* Confirms whether the _on_stages list is still sorted. It will become
* unsorted if someone calls TextureStage::set_sort().
@ -223,7 +263,7 @@ is_identity() const {
*/
INLINE void TextureAttrib::
check_sorted() const {
if (_sort_seq != TextureStage::get_sort_seq()) {
if (_sort_seq != TextureStage::get_sort_seq() && !_sort_seq.is_fresh()) {
((TextureAttrib *)this)->sort_on_stages();
}
}

View File

@ -106,6 +106,8 @@ find_on_stage(const TextureStage *stage) const {
*/
CPT(RenderAttrib) TextureAttrib::
add_on_stage(TextureStage *stage, Texture *tex, int override) const {
nassertr(tex != nullptr, this);
TextureAttrib *attrib = new TextureAttrib(*this);
Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first;
(*si)._override = override;
@ -127,6 +129,8 @@ add_on_stage(TextureStage *stage, Texture *tex, int override) const {
*/
CPT(RenderAttrib) TextureAttrib::
add_on_stage(TextureStage *stage, Texture *tex, const SamplerState &sampler, int override) const {
nassertr(tex != nullptr, this);
TextureAttrib *attrib = new TextureAttrib(*this);
Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first;
(*si)._override = override;
@ -381,10 +385,19 @@ output(ostream &out) const {
const StageNode &sn = *(*ri);
TextureStage *stage = sn._stage;
Texture *tex = sn._texture;
if (tex != NULL) {
if (tex != nullptr) {
out << " " << stage->get_name() << ":" << tex->get_name();
} else {
out << " " << stage->get_name();
out << " " << stage->get_name() << ":(" << sn._texture_type;
if (sn._texture_affects_rgb) {
out << " rgb";
if (sn._texture_affects_alpha) {
out << "a";
}
} else if (sn._texture_affects_alpha) {
out << " alpha";
}
out << ")";
}
if (sn._override != 0) {
out << "^" << sn._override;
@ -500,6 +513,19 @@ compare_to_impl(const RenderAttrib *other) const {
}
}
if (texture == nullptr) {
// This is an attribute returned by get_auto_shader_attrib_impl.
if ((*si)._texture_type != (*osi)._texture_type) {
return (*si)._texture_type < (*osi)._texture_type ? -1 : 1;
}
if ((*si)._texture_affects_rgb != (*osi)._texture_affects_rgb) {
return (*si)._texture_affects_rgb < (*osi)._texture_affects_rgb ? -1 : 1;
}
if ((*si)._texture_affects_alpha != (*osi)._texture_affects_alpha) {
return (*si)._texture_affects_alpha < (*osi)._texture_affects_alpha ? -1 : 1;
}
}
++si;
++osi;
}
@ -563,6 +589,13 @@ get_hash_impl() const {
hash = pointer_hash::add_hash(hash, sn._texture);
hash = int_hash::add_hash(hash, (int)sn._implicit_sort);
hash = int_hash::add_hash(hash, sn._override);
if (sn._texture == nullptr) {
// This is an attribute returned by get_auto_shader_attrib_impl.
hash = int_hash::add_hash(hash, (int)sn._texture_type);
hash = int_hash::add_hash(hash, (int)sn._texture_affects_rgb);
hash = int_hash::add_hash(hash, (int)sn._texture_affects_alpha);
}
}
// This bool value goes here, between the two lists, to differentiate
@ -739,7 +772,45 @@ invert_compose_impl(const RenderAttrib *other) const {
*/
CPT(RenderAttrib) TextureAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
return this;
if (_on_stages.empty()) {
// Having no stages is the same as not applying a texture attribute.
return nullptr;
}
// We make a texture attribute that does not store the texture and sampler,
// so that we don't have to generate a shader for every possible texture.
// We do have to store the few texture properties that do affect the
// generated shader.
PT(TextureAttrib) attrib = new TextureAttrib;
attrib->_on_stages = _on_stages;
attrib->sort_on_stages();
Stages::iterator si;
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
Texture::Format format = (*si)._texture->get_format();
(*si)._texture_type = (*si)._texture->get_texture_type();
(*si)._texture_affects_rgb = (format != Texture::F_alpha);
(*si)._texture_affects_alpha = Texture::has_alpha(format);
(*si)._texture = nullptr;
(*si)._has_sampler = false;
// We will no longer be composing or sorting this state so we can get rid
// of these values.
(*si)._override = 0;
(*si)._implicit_sort = 0;
// Exception to optimize a common case: if the first texture is an RGB
// texture, we don't care about whether it affects the alpha channel.
if (attrib->_render_stages[0] == &(*si) &&
(*si)._texture_affects_rgb && !(*si)._texture_affects_alpha) {
(*si)._texture_affects_alpha = true;
}
}
// Prevent check_sorted() from being called on this state.
attrib->_sort_seq = UpdateSeq::fresh();
return return_new(attrib);
}
/**

View File

@ -59,6 +59,7 @@ PUBLISHED:
INLINE int get_ff_tc_index(int n) const;
INLINE bool has_on_stage(TextureStage *stage) const;
INLINE Texture *get_on_texture(TextureStage *stage) const;
INLINE Texture::TextureType get_on_texture_type(TextureStage *stage) const;
INLINE const SamplerState &get_on_sampler(TextureStage *stage) const;
INLINE int get_on_stage_override(TextureStage *stage) const;
@ -81,6 +82,8 @@ PUBLISHED:
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
public:
INLINE bool on_stage_affects_rgb(size_t n) const;
INLINE bool on_stage_affects_alpha(size_t n) const;
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
virtual bool lower_attrib_can_override() const;
@ -114,6 +117,11 @@ private:
int _ff_tc_index;
unsigned int _implicit_sort;
int _override;
// These fields are used by the shader generator.
Texture::TextureType _texture_type : 16;
bool _texture_affects_rgb : 8;
bool _texture_affects_alpha : 8;
};
class CompareTextureStagePriorities {

View File

@ -114,7 +114,14 @@ get_hash_impl() const {
*/
CPT(RenderAttrib) TransparencyAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
return this;
if (_mode == TransparencyAttrib::M_alpha) {
return this;
} else if (_mode == TransparencyAttrib::M_premultiplied_alpha ||
_mode == TransparencyAttrib::M_dual) {
return return_new(new TransparencyAttrib(M_alpha));
} else {
return nullptr;
}
}
/**

View File

@ -55,8 +55,8 @@ TypeHandle ShaderGenerator::_type_handle;
* shader generator belongs.
*/
ShaderGenerator::
ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host) :
_gsg(gsg), _host(host) {
ShaderGenerator(GraphicsStateGuardianBase *gsg) :
_gsg(gsg) {
// The ATTR# input semantics seem to map to generic vertex attributes in
// both arbvp1 and glslv, which behave more consistently. However, they
@ -265,12 +265,7 @@ analyze_renderstate(const RenderState *rs) {
const MaterialAttrib *material;
rs->get_attrib_def(material);
if (!material->is_off()) {
_material = material->get_material();
} else {
_material = Material::get_default();
}
_material_flags = material->get_material_flags();
// Break out the lights by type.
@ -285,14 +280,7 @@ analyze_renderstate(const RenderState *rs) {
nassertv(light_obj != (PandaNode *)NULL);
if (light_obj->is_ambient_light()) {
if (_material->has_ambient()) {
LColor a = _material->get_ambient();
if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
_have_ambient = true;
}
} else {
_have_ambient = true;
}
_have_ambient = true;
_lighting = true;
} else if (light_obj->is_of_type(LightLensNode::get_class_type())) {
@ -357,37 +345,28 @@ analyze_renderstate(const RenderState *rs) {
}
// Determine whether we should normalize the normals.
const RescaleNormalAttrib *rescale;
/*const RescaleNormalAttrib *rescale;
rs->get_attrib_def(rescale);
_normalize_normals = (rescale->get_mode() != RescaleNormalAttrib::M_none);
*/
// Actually, let's always normalize the normals for now. This helps to
// reduce combinatoric explosion of shaders.
_normalize_normals = true;
// Decide which material modes need to be calculated.
if (_lighting) {
if (_material->has_diffuse()) {
LColor d = _material->get_diffuse();
if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
_have_diffuse = true;
}
} else {
_have_diffuse = true;
}
_have_diffuse = true;
}
if (_lighting && (_material->has_emission())) {
LColor e = _material->get_emission();
if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
_have_emission = true;
}
if (_lighting && (_material_flags & Material::F_emission) != 0) {
_have_emission = true;
}
if (_lighting) {
if (_material->has_specular()) {
LColor s = _material->get_specular();
if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
_have_specular = true;
}
if (_material_flags & Material::F_specular) {
_have_specular = true;
} else if (_map_index_gloss >= 0) {
_have_specular = true;
}
@ -398,14 +377,10 @@ analyze_renderstate(const RenderState *rs) {
// Decide whether to separate ambient and diffuse calculations.
if (_have_ambient && _have_diffuse) {
if (_material->has_ambient()) {
if (_material->has_diffuse()) {
_separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
} else {
_separate_ambient_diffuse = true;
}
if (_material_flags & Material::F_ambient) {
_separate_ambient_diffuse = true;
} else {
if (_material->has_diffuse()) {
if (_material_flags & Material::F_diffuse) {
_separate_ambient_diffuse = true;
} else {
_separate_ambient_diffuse = false;
@ -427,10 +402,10 @@ analyze_renderstate(const RenderState *rs) {
// Does the shader need material properties as input?
_need_material_props =
(_have_ambient && (_material->has_ambient()))||
(_have_diffuse && (_material->has_diffuse()))||
(_have_emission && (_material->has_emission()))||
(_have_specular && (_material->has_specular()));
(_have_ambient && (_material_flags & Material::F_ambient) != 0) ||
(_have_diffuse && (_material_flags & Material::F_diffuse) != 0) ||
(_have_emission && (_material_flags & Material::F_emission) != 0) ||
(_have_specular && (_material_flags & Material::F_specular) != 0);
// Check for clip planes.
@ -490,7 +465,7 @@ clear_analysis() {
_out_aux_normal = false;
_out_aux_glow = false;
_out_aux_any = false;
_material = (Material*)NULL;
_material_flags = 0;
_need_material_props = false;
_need_world_position = false;
_need_world_normal = false;
@ -823,11 +798,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t in float4 l_" << it->first->join("_") << " : " << it->second << ",\n";
}
const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
for (int i=0; i<_num_textures; i++) {
for (int i = 0; i < _num_textures; ++i) {
TextureStage *stage = texture->get_on_stage(i);
Texture *tex = texture->get_on_texture(stage);
nassertr(tex != NULL, NULL);
text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n";
Texture::TextureType type = texture->get_on_texture_type(stage);
text << "\t uniform sampler" << texture_type_as_string(type) << " tex_" << i << ",\n";
if (tex_matrix->has_stage(stage)) {
text << "\t uniform float4x4 texmat_" << i << ",\n";
}
@ -864,7 +838,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t uniform float4x4 attr_material,\n";
}
if (_have_specular) {
if (_material->get_local()) {
if (_material_flags & Material::F_local) {
text << "\t uniform float4 mspos_view,\n";
} else {
text << "\t uniform float4 row1_view_to_model,\n";
@ -935,11 +909,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
text << "\t // Fetch all textures.\n";
if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height));
nassertr(tex != NULL, NULL);
text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type());
Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(_map_index_height));
text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(type);
text << "(tex_" << _map_index_height << ", texcoord" << _map_index_height << ".";
switch (tex->get_texture_type()) {
switch (type) {
case Texture::TT_cube_map:
case Texture::TT_3d_texture:
case Texture::TT_2d_texture_array:
@ -972,18 +945,17 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << " * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale << ";\n";
}
}
for (int i=0; i<_num_textures; i++) {
for (int i = 0; i < _num_textures; ++i) {
if (i != _map_index_height) {
Texture *tex = texture->get_on_texture(texture->get_on_stage(i));
nassertr(tex != NULL, NULL);
Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(i));
// Parallax mapping pushes the texture coordinates of the other textures
// away from the camera.
if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
text << "\t texcoord" << i << ".xyz -= parallax_offset;\n";
}
text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type());
text << "\t float4 tex" << i << " = tex" << texture_type_as_string(type);
text << "(tex_" << i << ", texcoord" << i << ".";
switch(tex->get_texture_type()) {
switch (type) {
case Texture::TT_cube_map:
case Texture::TT_3d_texture:
case Texture::TT_2d_texture_array:
@ -1040,7 +1012,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
if (_have_specular) {
text << "\t float4 tot_specular = float4(0,0,0,0);\n";
if (_material->has_specular()) {
if (_material_flags & Material::F_specular) {
text << "\t float shininess = attr_material[3].w;\n";
} else {
text << "\t float shininess = 50; // no shininess specified, using default\n";
@ -1072,7 +1044,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t tot_diffuse += lcolor;\n";
}
if (_have_specular) {
if (_material->get_local()) {
if (_material_flags & Material::F_local) {
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
} else {
text << "\t lhalf = dlight_light" << i << "_rel_view[3].xyz;\n";
@ -1102,7 +1074,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t tot_diffuse += lcolor;\n";
}
if (_have_specular) {
if (_material->get_local()) {
if (_material_flags & Material::F_local) {
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
} else {
text << "\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
@ -1140,7 +1112,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
text << "\t tot_diffuse += lcolor;\n";
}
if (_have_specular) {
if (_material->get_local()) {
if (_material_flags & Material::F_local) {
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
} else {
text << "\t lhalf = normalize(lvec - float3(0,1,0));\n";
@ -1198,7 +1170,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
}
if ((_have_ambient)&&(_separate_ambient_diffuse)) {
if (_material->has_ambient()) {
if (_material_flags & Material::F_ambient) {
text << "\t result += tot_ambient * attr_material[0];\n";
} else if (_vertex_colors) {
text << "\t result += tot_ambient * l_color;\n";
@ -1209,7 +1181,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
}
if (_have_diffuse) {
if (_material->has_diffuse()) {
if (_material_flags & Material::F_diffuse) {
text << "\t result += tot_diffuse * attr_material[1];\n";
} else if (_vertex_colors) {
text << "\t result += tot_diffuse * l_color;\n";
@ -1263,20 +1235,20 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
}
// Now loop through the textures to compose our magic blending formulas.
for (int i=0; i<_num_textures; i++) {
for (int i = 0; i < _num_textures; ++i) {
TextureStage *stage = texture->get_on_stage(i);
switch (stage->get_mode()) {
case TextureStage::M_modulate: {
int num_components = texture->get_on_texture(texture->get_on_stage(i))->get_num_components();
bool affects_rgb = texture->on_stage_affects_rgb(i);
bool affects_alpha = texture->on_stage_affects_alpha(i);
if (num_components == 1) {
text << "\t result.a *= tex" << i << ".a;\n";
} else if (num_components == 3) {
text << "\t result.rgb *= tex" << i << ".rgb;\n";
} else {
if (affects_rgb && affects_alpha) {
text << "\t result.rgba *= tex" << i << ".rgba;\n";
} else if (affects_alpha) {
text << "\t result.a *= tex" << i << ".a;\n";
} else if (affects_rgb) {
text << "\t result.rgb *= tex" << i << ".rgb;\n";
}
break; }
case TextureStage::M_modulate_glow:
case TextureStage::M_modulate_gloss:
@ -1388,7 +1360,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
if (_lighting) {
if (_have_specular) {
if (_material->has_specular()) {
if (_material_flags & Material::F_specular) {
text << "\t tot_specular *= attr_material[3];\n";
}
if (_map_index_gloss >= 0 && _auto_gloss_on) {

View File

@ -60,7 +60,7 @@ class GeomVertexAnimationSpec;
*/
class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedReferenceCount {
PUBLISHED:
ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host);
ShaderGenerator(GraphicsStateGuardianBase *gsg);
virtual ~ShaderGenerator();
virtual CPT(ShaderAttrib) synthesize_shader(const RenderState *rs,
const GeomVertexAnimationSpec &anim);
@ -87,7 +87,7 @@ protected:
// RenderState analysis information. Created by analyze_renderstate:
CPT(RenderState) _state;
Material *_material;
int _material_flags;
int _num_textures;
pvector<LightLensNode *> _lights;
@ -144,7 +144,6 @@ protected:
// This is not a PT() to prevent a circular reference.
GraphicsStateGuardianBase *_gsg;
GraphicsOutputBase *_host;
public:
static TypeHandle get_class_type() {