diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 29db4290bd..5a64c1fe2a 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -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 diff --git a/direct/src/controls/InputState.py b/direct/src/controls/InputState.py index 38b0d78892..68608e9bea 100755 --- a/direct/src/controls/InputState.py +++ b/direct/src/controls/InputState.py @@ -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 diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index e6b96f36f1..9f49069a23 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -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 diff --git a/direct/src/filter/FilterManager.py b/direct/src/filter/FilterManager.py index bf35abf3c9..1de63c702d 100644 --- a/direct/src/filter/FilterManager.py +++ b/direct/src/filter/FilterManager.py @@ -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 diff --git a/direct/src/filter/filterBloomX.py b/direct/src/filter/filterBloomX.py index 38bc368101..220cd776b7 100644 --- a/direct/src/filter/filterBloomX.py +++ b/direct/src/filter/filterBloomX.py @@ -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); } diff --git a/direct/src/filter/filterBloomY.py b/direct/src/filter/filterBloomY.py index 19ba36ae29..18e2885b1e 100644 --- a/direct/src/filter/filterBloomY.py +++ b/direct/src/filter/filterBloomY.py @@ -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); } diff --git a/direct/src/filter/filterBlurX.py b/direct/src/filter/filterBlurX.py index 6517b3ad55..b472a5d7a7 100644 --- a/direct/src/filter/filterBlurX.py +++ b/direct/src/filter/filterBlurX.py @@ -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; } diff --git a/direct/src/filter/filterBlurY.py b/direct/src/filter/filterBlurY.py index abbf1d09ee..173c7a73b5 100644 --- a/direct/src/filter/filterBlurY.py +++ b/direct/src/filter/filterBlurY.py @@ -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; } diff --git a/direct/src/showbase/Audio3DManager.py b/direct/src/showbase/Audio3DManager.py index 07407c822b..463d3b5bf0 100644 --- a/direct/src/showbase/Audio3DManager.py +++ b/direct/src/showbase/Audio3DManager.py @@ -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 + diff --git a/direct/src/showbase/DirectObject.py b/direct/src/showbase/DirectObject.py index 9106637134..778328ea50 100644 --- a/direct/src/showbase/DirectObject.py +++ b/direct/src/showbase/DirectObject.py @@ -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 diff --git a/direct/src/showbase/Messenger.py b/direct/src/showbase/Messenger.py index 09ceb9cd0a..08062e4a3e 100644 --- a/direct/src/showbase/Messenger.py +++ b/direct/src/showbase/Messenger.py @@ -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 + diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index b0232dcd4d..c8a69acc03 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -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): diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 045c534ebe..a9ce3abbcb 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -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; } diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index b6bc1ada2a..4b6aa01f67 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -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. diff --git a/panda/src/express/virtualFile.h b/panda/src/express/virtualFile.h index 0719f3f8d1..5322fce670 100644 --- a/panda/src/express/virtualFile.h +++ b/panda/src/express/virtualFile.h @@ -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); diff --git a/panda/src/express/virtualFileSystem.h b/panda/src/express/virtualFileSystem.h index 22d6316ce7..2ff1fa4e95 100644 --- a/panda/src/express/virtualFileSystem.h +++ b/panda/src/express/virtualFileSystem.h @@ -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); diff --git a/panda/src/express/virtualFileSystem_ext.cxx b/panda/src/express/virtualFileSystem_ext.cxx index dc50751c52..6bc375c0d9 100644 --- a/panda/src/express/virtualFileSystem_ext.cxx +++ b/panda/src/express/virtualFileSystem_ext.cxx @@ -26,9 +26,22 @@ */ PyObject *Extension:: 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()) { diff --git a/panda/src/express/virtualFile_ext.cxx b/panda/src/express/virtualFile_ext.cxx index d81672cc50..db1a9a62ab 100644 --- a/panda/src/express/virtualFile_ext.cxx +++ b/panda/src/express/virtualFile_ext.cxx @@ -26,9 +26,23 @@ */ PyObject *Extension:: 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); } diff --git a/panda/src/gobj/material.h b/panda/src/gobj/material.h index 1a37415294..eb1a36747e 100644 --- a/panda/src/gobj/material.h +++ b/panda/src/gobj/material.h @@ -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); diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index f0cb8e0506..7147a108c0 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -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) || diff --git a/panda/src/pgraph/alphaTestAttrib.cxx b/panda/src/pgraph/alphaTestAttrib.cxx index 5a37a23531..8d31c57b12 100644 --- a/panda/src/pgraph/alphaTestAttrib.cxx +++ b/panda/src/pgraph/alphaTestAttrib.cxx @@ -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; + } } /** diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 7b850fafc6..11d319212f 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -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. } } diff --git a/panda/src/pgraph/materialAttrib.I b/panda/src/pgraph/materialAttrib.I index 2f2652f43c..3cb7f9e6be 100644 --- a/panda/src/pgraph/materialAttrib.I +++ b/panda/src/pgraph/materialAttrib.I @@ -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; +} diff --git a/panda/src/pgraph/materialAttrib.cxx b/panda/src/pgraph/materialAttrib.cxx index c3facc7bb4..d8eee605d7 100644 --- a/panda/src/pgraph/materialAttrib.cxx +++ b/panda/src/pgraph/materialAttrib.cxx @@ -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; diff --git a/panda/src/pgraph/materialAttrib.h b/panda/src/pgraph/materialAttrib.h index f984b699b3..28bd90f8bd 100644 --- a/panda/src/pgraph/materialAttrib.h +++ b/panda/src/pgraph/materialAttrib.h @@ -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() { diff --git a/panda/src/pgraph/rescaleNormalAttrib.cxx b/panda/src/pgraph/rescaleNormalAttrib.cxx index 36af8ebafb..e9d081e43c 100644 --- a/panda/src/pgraph/rescaleNormalAttrib.cxx +++ b/panda/src/pgraph/rescaleNormalAttrib.cxx @@ -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; } /** diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index 6435ceed5d..04d6196aa2 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -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"; diff --git a/panda/src/pgraph/textureAttrib.I b/panda/src/pgraph/textureAttrib.I index da1feca0be..6649c8d87a 100644 --- a/panda/src/pgraph/textureAttrib.I +++ b/panda/src/pgraph/textureAttrib.I @@ -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(); } } diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 157bf1d146..8c1b4833ff 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -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); } /** diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index 2cc5270536..9f1c13e3c8 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -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 { diff --git a/panda/src/pgraph/transparencyAttrib.cxx b/panda/src/pgraph/transparencyAttrib.cxx index 4dd7d0a1c2..d998004f09 100644 --- a/panda/src/pgraph/transparencyAttrib.cxx +++ b/panda/src/pgraph/transparencyAttrib.cxx @@ -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; + } } /** diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 63973c6bc3..e78ac65f3a 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -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) { diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index a1d83f0919..9042291631 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -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 _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() {