From 87d1048f7913834a2e78dc5b45182007d00e2253 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Sun, 30 Sep 2018 15:43:32 -0600 Subject: [PATCH 01/14] mathutil: mersenne.h parameters should not be an enum This makes no sense as an enum; they're constants, so they should be static const. --- panda/src/mathutil/mersenne.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/panda/src/mathutil/mersenne.h b/panda/src/mathutil/mersenne.h index 7bcb00cb8f..15d96029e4 100644 --- a/panda/src/mathutil/mersenne.h +++ b/panda/src/mathutil/mersenne.h @@ -69,14 +69,12 @@ PUBLISHED: }; private: - enum { - // Period parameters - N = 624, - M = 397, - MATRIX_A = 0x9908b0dfUL, // constant vector a - UPPER_MASK = 0x80000000UL, // most significant w-r bits - LOWER_MASK = 0x7fffffffUL, // least significant r bits - }; + // Period parameters + static const unsigned long N = 624; + static const unsigned long M = 397; + static const unsigned long MATRIX_A = 0x9908b0dfUL; // constant vector a + static const unsigned long UPPER_MASK = 0x80000000UL; // most significant w-r bits + static const unsigned long LOWER_MASK = 0x7fffffffUL; // least significant r bits unsigned long mt[N]; // the array for the state vector unsigned int mti; // mti==N+1 means mt[N] is not initialized From 51497da8fbe38985677d38f079b1cf79ae183020 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Sun, 7 Oct 2018 01:33:18 -0600 Subject: [PATCH 02/14] movies: Fix missing include --- panda/src/movies/movieTypeRegistry.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/panda/src/movies/movieTypeRegistry.cxx b/panda/src/movies/movieTypeRegistry.cxx index 51468ac2a4..5bc8228bb4 100644 --- a/panda/src/movies/movieTypeRegistry.cxx +++ b/panda/src/movies/movieTypeRegistry.cxx @@ -12,10 +12,12 @@ */ #include "movieTypeRegistry.h" + #include "string_utils.h" #include "config_movies.h" #include "config_putil.h" #include "load_dso.h" +#include "reMutexHolder.h" using std::endl; using std::string; From 8d147056894ab4af3936aa3200a5adee23781891 Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Sun, 7 Oct 2018 01:36:18 -0600 Subject: [PATCH 03/14] interrogate: Fix typo --- dtool/src/interrogate/interrogateBuilder.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index f579f1586d..15607c95ea 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -2943,7 +2943,7 @@ define_method(CPPInstance *function, InterrogateType &itype, // specifically flag get_class_type() as published. bool force_publish = false; if (function->get_simple_name() == "get_class_type" && - (function->_storage_class && CPPInstance::SC_static) != 0 && + (function->_storage_class & CPPInstance::SC_static) != 0 && function->_vis <= V_public) { force_publish = true; } From 83753405820bcf4884d78e116eb2f8f31c4151a7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 20:24:19 +0200 Subject: [PATCH 04/14] py_panda: fix TypeError being raised instead of AttributeError This prevented doing something like hasattr(vec3, "stuff") --- dtool/src/interrogatedb/py_panda.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index e900ab0e7f..42bcdb9a35 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -235,8 +235,8 @@ PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute) { "'%.100s' object has no attribute '%.200s'", Py_TYPE(obj)->tp_name, attribute); - Py_INCREF(PyExc_TypeError); - PyErr_Restore(PyExc_TypeError, message, nullptr); + Py_INCREF(PyExc_AttributeError); + PyErr_Restore(PyExc_AttributeError, message, nullptr); return nullptr; } From 8cb048022242db4be1fa18ef66fbc5fc934c107e Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 20:25:08 +0200 Subject: [PATCH 05/14] readme: update Win build instructions to mention MSVC 2017 --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cf45f0dfd2..3a088a5cc1 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,9 @@ Building Panda3D Windows ------- -We currently build using the Microsoft Visual C++ 2015 compiler. You will -also need to install the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk), +You can build Panda3D with the Microsoft Visual C++ 2015 or 2017 compiler, +which can be downloaded for free from the [Visual Studio site](https://visualstudio.microsoft.com/downloads/). +You will also need to install the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk), and if you intend to target Windows XP, you will also need the [Windows 7.1 SDK](https://www.microsoft.com/en-us/download/details.aspx?id=8279). @@ -58,11 +59,12 @@ http://rdb.name/thirdparty-vc14-x64.7z http://rdb.name/thirdparty-vc14.7z After acquiring these dependencies, you may simply build Panda3D from the -command prompt using the following command. (Add the `--windows-sdk=10` -option if you don't need to support Windows XP.) +command prompt using the following command. (Change `14.1` to `14` if you are +using Visual C++ 2015 instead of 2017. Add the `--windows-sdk=10` option if +you don't need to support Windows XP and did not install the Windows 7.1 SDK.) ```bash -makepanda\makepanda.bat --everything --installer --no-eigen --threads=2 +makepanda\makepanda.bat --everything --installer --msvc-version=14.1 --no-eigen --threads=2 ``` When the build succeeds, it will produce an .exe file that you can use to From 7d3b7036acec39082abc462f11b0a0dc18f14bae Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 20:25:53 +0200 Subject: [PATCH 06/14] readme: suggest libassimp-dev and libopenexr-dev on Ubuntu --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a088a5cc1..14ab95e8b1 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ If you are on Ubuntu, this command should cover the most frequently used third-party packages: ```bash -sudo apt-get install build-essential pkg-config python-dev libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit libgtk2.0-dev +sudo apt-get install build-essential pkg-config python-dev libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit libgtk2.0-dev libassimp-dev libopenexr-dev ``` Once Panda3D has built, you can either install the .deb or .rpm package that From 86c9d11a538d3485012de438419a1e1642b91941 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 20:26:24 +0200 Subject: [PATCH 07/14] readme: add Android/termux build instructions --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 14ab95e8b1..43feb9b19c 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,36 @@ python3.6 makepanda/makepanda.py --everything --installer --no-egl --no-gles --n If successful, this will produce a .pkg file in the root of the source directory which you can install using `pkg install`. +Android +------- + +Note: building on Android is very experimental and not guaranteed to work. + +You can experimentally build the Android Python runner via the [termux](https://termux.com/) +shell. You will need to install [Termux](https://play.google.com/store/apps/details?id=com.termux) +and [Termux API](https://play.google.com/store/apps/details?id=com.termux.api) +from the Play Store. Many of the dependencies can be installed by running the +following command in the Termux shell: + +```bash +pkg install python-dev termux-tools ndk-stl ndk-sysroot clang libvorbis-dev libopus-dev opusfile-dev openal-soft-dev freetype-dev harfbuzz-dev libpng-dev ecj4.6 dx patchelf aapt apksigner libcrypt-dev +``` + +Then, you can build and install the .apk right away using these commands: + +```bash +python makepanda/makepanda.py --everything --target android-21 --installer +xdg-open panda3d.apk +``` + +To launch a Python program from Termux, you can use the `run_python.sh` script +inside the `panda/src/android` directory. It will launch Python in a separate +activity, load it with the Python script you passed as argument, and use a +socket for returning the command-line output to the Termux shell. Do note +that this requires the Python application to reside on the SD card and that +Termux needs to be set up with access to the SD card (using the +`termux-setup-storage` command). + Running Tests ============= From b0c9000000f2da908478826e8e7614dfd5438e75 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 21:41:02 +0200 Subject: [PATCH 08/14] display: fix assert when app exits before window fully opens Possibly addressing #403 --- panda/src/display/graphicsEngine.cxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index dd637d7a9a..57a592f05d 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -593,8 +593,7 @@ remove_all_windows() { Windows old_windows; old_windows.swap(_windows); Windows::iterator wi; - for (wi = old_windows.begin(); wi != old_windows.end(); ++wi) { - GraphicsOutput *win = (*wi); + for (GraphicsOutput *win : old_windows) { nassertv(win != nullptr); do_remove_window(win, current_thread); GraphicsStateGuardian *gsg = win->get_gsg(); @@ -605,6 +604,14 @@ remove_all_windows() { { MutexHolder new_windows_holder(_new_windows_lock, current_thread); + for (GraphicsOutput *win : _new_windows) { + nassertv(win != nullptr); + do_remove_window(win, current_thread); + GraphicsStateGuardian *gsg = win->get_gsg(); + if (gsg != nullptr) { + gsg->release_all(); + } + } _new_windows.clear(); } From e1af4abf11ef1600ee686a8fa603506293c554c1 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 21:42:02 +0200 Subject: [PATCH 09/14] glgsg: fix sRGB for FBOs created from non-sRGB host window In this case _current_properties in begin_frame() will not have srgb_color set, as the current props are set by the host window --- panda/src/glstuff/glGraphicsBuffer_src.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 66a9e6d407..eab850bdba 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -283,6 +283,13 @@ begin_frame(FrameMode mode, Thread *current_thread) { rebuild_bitplanes(); } + // The host window may not have had sRGB enabled, so we need to do this. +#ifndef OPENGLES + if (get_fb_properties().get_srgb_color()) { + glEnable(GL_FRAMEBUFFER_SRGB); + } +#endif + _gsg->set_current_properties(&get_fb_properties()); report_my_gl_errors(); return true; From 51414466da2f241157e075c39da6ac35ac05b32d Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 22:52:49 +0200 Subject: [PATCH 10/14] display: ignore material if no lights are applied This fixes materials suddenly showing up when a color scale is applied and color-scale-via-lighting is set. Fixes #404 --- panda/src/display/standardMunger.cxx | 23 ++++++++++++++++++++++- panda/src/display/standardMunger.h | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 5d2a3f5102..94f376e99b 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -36,7 +36,8 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, _munge_color(false), _munge_color_scale(false), _auto_shader(false), - _shader_skinning(false) + _shader_skinning(false), + _remove_material(false) { const ShaderAttrib *shader_attrib; state->get_attrib_def(shader_attrib); @@ -94,6 +95,19 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, // effort to detect this contrived situation and handle it correctly. } } + + // If we have no lights but do have a material, we will need to remove it so + // that it won't appear when we enable color scale via lighting. + const LightAttrib *light_attrib; + const MaterialAttrib *material_attrib; + if (get_gsg()->get_color_scale_via_lighting() && + (!state->get_attrib(light_attrib) || !light_attrib->has_any_on_light()) && + state->get_attrib(material_attrib) && + material_attrib->get_material() != nullptr && + shader_attrib->get_shader() == nullptr) { + _remove_material = true; + _should_munge_state = true; + } } /** @@ -291,6 +305,9 @@ compare_to_impl(const GeomMunger *other) const { if (_auto_shader != om->_auto_shader) { return (int)_auto_shader - (int)om->_auto_shader; } + if (_remove_material != om->_remove_material) { + return (int)_remove_material - (int)om->_remove_material; + } return StateMunger::compare_to_impl(other); } @@ -344,5 +361,9 @@ munge_state_impl(const RenderState *state) { munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot()); } + if (_remove_material) { + munged_state = munged_state->remove_attrib(MaterialAttrib::get_class_slot()); + } + return munged_state; } diff --git a/panda/src/display/standardMunger.h b/panda/src/display/standardMunger.h index 05e8ee0344..5703fd01b5 100644 --- a/panda/src/display/standardMunger.h +++ b/panda/src/display/standardMunger.h @@ -55,6 +55,7 @@ private: bool _munge_color_scale; bool _auto_shader; bool _shader_skinning; + bool _remove_material; LColor _color; LVecBase4 _color_scale; From a9ff8a22f0e76218220010189de375dd48d2741b Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 23:00:17 +0200 Subject: [PATCH 11/14] makepanda: enable Assimp in default Confauto.prc if built --- makepanda/confauto.in | 5 +++++ makepanda/makepanda.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/makepanda/confauto.in b/makepanda/confauto.in index 608a6daf68..41655f1bbc 100644 --- a/makepanda/confauto.in +++ b/makepanda/confauto.in @@ -21,6 +21,11 @@ load-file-type egg pandaegg +# If we built with Assimp support, we can enable the Assimp loader, +# which allows us to load many model formats natively. + +load-file-type p3assimp + # These entries work very similar to load-file-type, except they are # used by the MovieVideo and MovieAudio code to determine which module # should be loaded in order to decode files of the given extension. diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index e371fbd3e8..a81ea7fe56 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2882,6 +2882,9 @@ else: # otherwise, disable it. confautoprc = confautoprc.replace('#st#', '#') +if PkgSkip("ASSIMP"): + confautoprc = confautoprc.replace("load-file-type p3assimp", "#load-file-type p3assimp") + if (os.path.isfile("makepanda/myconfig.in")): configprc = ReadFile("makepanda/myconfig.in") else: From 80951b3268a4894903b8cff0555bc535c79a7b36 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 23:02:50 +0200 Subject: [PATCH 12/14] task: provide more properties on AsyncTask --- panda/src/event/asyncTask.h | 21 +++++++++++++++++++++ panda/src/event/pythonTask.h | 7 ------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/panda/src/event/asyncTask.h b/panda/src/event/asyncTask.h index f5871ae2f2..5a7a2cd805 100644 --- a/panda/src/event/asyncTask.h +++ b/panda/src/event/asyncTask.h @@ -99,6 +99,27 @@ PUBLISHED: virtual void output(std::ostream &out) const; +PUBLISHED: + MAKE_PROPERTY(state, get_state); + MAKE_PROPERTY(alive, is_alive); + MAKE_PROPERTY(manager, get_manager); + + // The name of this task. + MAKE_PROPERTY(name, get_name, set_name); + + // This is a number guaranteed to be unique for each different AsyncTask + // object in the universe. + MAKE_PROPERTY(id, get_task_id); + + MAKE_PROPERTY(task_chain, get_task_chain, set_task_chain); + MAKE_PROPERTY(sort, get_sort, set_sort); + MAKE_PROPERTY(priority, get_priority, set_priority); + MAKE_PROPERTY(done_event, get_done_event, set_done_event); + + MAKE_PROPERTY(dt, get_dt); + MAKE_PROPERTY(max_dt, get_max_dt); + MAKE_PROPERTY(average_dt, get_average_dt); + protected: void jump_to_task_chain(AsyncTaskManager *manager); DoneStatus unlock_and_do_task(); diff --git a/panda/src/event/pythonTask.h b/panda/src/event/pythonTask.h index 3771d46d8b..06ff8b6fe4 100644 --- a/panda/src/event/pythonTask.h +++ b/panda/src/event/pythonTask.h @@ -61,9 +61,6 @@ PUBLISHED: int __clear__(); PUBLISHED: - // The name of this task. - MAKE_PROPERTY(name, get_name, set_name); - // The amount of seconds that have elapsed since the task was started, // according to the task manager's clock. MAKE_PROPERTY(time, get_elapsed_time); @@ -88,10 +85,6 @@ PUBLISHED: // according to the task manager's clock. MAKE_PROPERTY(frame, get_elapsed_frames); - // This is a number guaranteed to be unique for each different AsyncTask - // object in the universe. - MAKE_PROPERTY(id, get_task_id); - // This is a special variable to hold the instance dictionary in which // custom variables may be stored. PyObject *__dict__; From 102a256b05092f97a75a221b18dd3d86253a7625 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 7 Oct 2018 23:03:07 +0200 Subject: [PATCH 13/14] tests: remove accidentally added debug image output --- tests/display/test_depth_buffer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/display/test_depth_buffer.py b/tests/display/test_depth_buffer.py index 8581fe47ea..c655758703 100644 --- a/tests/display/test_depth_buffer.py +++ b/tests/display/test_depth_buffer.py @@ -91,8 +91,6 @@ def render_depth_pixel(region, distance, near, far, clear=None, write=True): region.window.engine.render_frame() region.window.clear_render_textures() - depth_texture.write("test2.png") - col = core.LColor() depth_texture.peek().lookup(col, 0.5, 0.5) return col[0] From 914ef2e13d497c0dec444fd82ab80dd08f15de61 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 Oct 2018 00:59:22 +0200 Subject: [PATCH 14/14] tests: add various unit tests for color-related render states --- tests/display/test_color_buffer.py | 271 +++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 tests/display/test_color_buffer.py diff --git a/tests/display/test_color_buffer.py b/tests/display/test_color_buffer.py new file mode 100644 index 0000000000..dab73cbbb8 --- /dev/null +++ b/tests/display/test_color_buffer.py @@ -0,0 +1,271 @@ +from panda3d import core +import pytest + +TEST_COLOR = core.LColor(1, 127/255.0, 0, 127/255.0) +TEST_COLOR_SCALE = core.LVecBase4(0.5, 0.5, 0.5, 0.5) +TEST_SCALED_COLOR = core.LColor(TEST_COLOR) +TEST_SCALED_COLOR.componentwise_mult(TEST_COLOR_SCALE) +FUZZ = 0.02 + + +@pytest.fixture(scope='session', params=[False, True], ids=["shader:off", "shader:auto"]) +def shader_attrib(request): + """Returns two ShaderAttribs: one with auto shader, one without.""" + if request.param: + return core.ShaderAttrib.make_default().set_shader_auto(True) + else: + return core.ShaderAttrib.make_off() + + +@pytest.fixture(scope='session', params=["mat:off", "mat:empty", "mat:amb", "mat:diff", "mat:both"]) +def material_attrib(request): + """Returns two MaterialAttribs: one with material, one without. It + shouldn't really matter what we set them to, since the tests in here do + not use lighting, and therefore the material should be ignored.""" + + if request.param == "mat:off": + return core.MaterialAttrib.make_off() + + elif request.param == "mat:empty": + return core.MaterialAttrib.make(core.Material()) + + elif request.param == "mat:amb": + mat = core.Material() + mat.ambient = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + elif request.param == "mat:diff": + mat = core.Material() + mat.diffuse = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + elif request.param == "mat:both": + mat = core.Material() + mat.diffuse = (0.1, 1, 0.5, 1) + mat.ambient = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + +@pytest.fixture(scope='module', params=[False, True], ids=["srgb:off", "srgb:on"]) +def color_region(request, graphics_pipe): + """Creates and returns a DisplayRegion with a depth buffer.""" + + engine = core.GraphicsEngine() + engine.set_threading_model("") + + host_fbprops = core.FrameBufferProperties() + host_fbprops.force_hardware = True + + host = engine.make_output( + graphics_pipe, + 'host', + 0, + host_fbprops, + core.WindowProperties.size(32, 32), + core.GraphicsPipe.BF_refuse_window, + ) + engine.open_windows() + + if host is None: + pytest.skip("GraphicsPipe cannot make offscreen buffers") + + fbprops = core.FrameBufferProperties() + fbprops.force_hardware = True + fbprops.set_rgba_bits(8, 8, 8, 8) + fbprops.srgb_color = request.param + + buffer = engine.make_output( + graphics_pipe, + 'buffer', + 0, + fbprops, + core.WindowProperties.size(32, 32), + core.GraphicsPipe.BF_refuse_window, + host.gsg, + host + ) + engine.open_windows() + + if buffer is None: + pytest.skip("Cannot make color buffer") + + if fbprops.srgb_color != buffer.get_fb_properties().srgb_color: + pytest.skip("Cannot make buffer with required srgb_color setting") + + buffer.set_clear_color_active(True) + buffer.set_clear_color((0, 0, 0, 1)) + + yield buffer.make_display_region() + + if buffer is not None: + engine.remove_window(buffer) + + +def render_color_pixel(region, state, vertex_color=None): + """Renders a fragment using the specified render settings, and returns the + resulting color value.""" + + # Set up the scene with a blank card rendering at specified distance. + scene = core.NodePath("root") + scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always)) + + camera = scene.attach_new_node(core.Camera("camera")) + camera.node().get_lens(0).set_near_far(1, 3) + camera.node().set_cull_bounds(core.OmniBoundingVolume()) + + cm = core.CardMaker("card") + cm.set_frame(-1, 1, -1, 1) + + if vertex_color is not None: + cm.set_color(vertex_color) + + card = scene.attach_new_node(cm.generate()) + card.set_state(state) + card.set_pos(0, 2, 0) + card.set_scale(60) + + region.active = True + region.camera = camera + + color_texture = core.Texture("color") + region.window.add_render_texture(color_texture, + core.GraphicsOutput.RTM_copy_ram, + core.GraphicsOutput.RTP_color) + + region.window.engine.render_frame() + region.window.clear_render_textures() + + col = core.LColor() + color_texture.peek().lookup(col, 0.5, 0.5) + return col + + +def test_color_write_mask(color_region): + state = core.RenderState.make( + core.ColorWriteAttrib.make(core.ColorWriteAttrib.C_green), + ) + result = render_color_pixel(color_region, state) + assert result == (0, 1, 0, 1) + + +def test_color_empty(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_color_off(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_color_flat(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_flat(TEST_COLOR), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_vertex(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_empty_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_off_vertex(color_region, shader_attrib, material_attrib): + #XXX This behaviour is really odd. + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_scaled_color_empty(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_scaled_color_off(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_scaled_color_flat(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_flat(TEST_COLOR), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_vertex(), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_empty_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_off_vertex(color_region, shader_attrib, material_attrib): + #XXX This behaviour is really odd. + state = core.RenderState.make( + core.ColorAttrib.make_off(), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) +