mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
Merge branch 'master' into input-overhaul
This commit is contained in:
commit
14042faa3d
44
README.md
44
README.md
@ -43,8 +43,9 @@ Building Panda3D
|
|||||||
Windows
|
Windows
|
||||||
-------
|
-------
|
||||||
|
|
||||||
We currently build using the Microsoft Visual C++ 2015 compiler. You will
|
You can build Panda3D with the Microsoft Visual C++ 2015 or 2017 compiler,
|
||||||
also need to install the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk),
|
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
|
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).
|
[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
|
http://rdb.name/thirdparty-vc14.7z
|
||||||
|
|
||||||
After acquiring these dependencies, you may simply build Panda3D from the
|
After acquiring these dependencies, you may simply build Panda3D from the
|
||||||
command prompt using the following command. (Add the `--windows-sdk=10`
|
command prompt using the following command. (Change `14.1` to `14` if you are
|
||||||
option if you don't need to support Windows XP.)
|
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
|
```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
|
When the build succeeds, it will produce an .exe file that you can use to
|
||||||
@ -101,7 +103,7 @@ If you are on Ubuntu, this command should cover the most frequently
|
|||||||
used third-party packages:
|
used third-party packages:
|
||||||
|
|
||||||
```bash
|
```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
|
Once Panda3D has built, you can either install the .deb or .rpm package that
|
||||||
@ -163,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
|
If successful, this will produce a .pkg file in the root of the source
|
||||||
directory which you can install using `pkg install`.
|
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
|
Running Tests
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -2943,7 +2943,7 @@ define_method(CPPInstance *function, InterrogateType &itype,
|
|||||||
// specifically flag get_class_type() as published.
|
// specifically flag get_class_type() as published.
|
||||||
bool force_publish = false;
|
bool force_publish = false;
|
||||||
if (function->get_simple_name() == "get_class_type" &&
|
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) {
|
function->_vis <= V_public) {
|
||||||
force_publish = true;
|
force_publish = true;
|
||||||
}
|
}
|
||||||
|
@ -235,8 +235,8 @@ PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute) {
|
|||||||
"'%.100s' object has no attribute '%.200s'",
|
"'%.100s' object has no attribute '%.200s'",
|
||||||
Py_TYPE(obj)->tp_name, attribute);
|
Py_TYPE(obj)->tp_name, attribute);
|
||||||
|
|
||||||
Py_INCREF(PyExc_TypeError);
|
Py_INCREF(PyExc_AttributeError);
|
||||||
PyErr_Restore(PyExc_TypeError, message, nullptr);
|
PyErr_Restore(PyExc_AttributeError, message, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@
|
|||||||
|
|
||||||
load-file-type egg pandaegg
|
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
|
# These entries work very similar to load-file-type, except they are
|
||||||
# used by the MovieVideo and MovieAudio code to determine which module
|
# used by the MovieVideo and MovieAudio code to determine which module
|
||||||
# should be loaded in order to decode files of the given extension.
|
# should be loaded in order to decode files of the given extension.
|
||||||
|
@ -2884,6 +2884,9 @@ else:
|
|||||||
# otherwise, disable it.
|
# otherwise, disable it.
|
||||||
confautoprc = confautoprc.replace('#st#', '#')
|
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")):
|
if (os.path.isfile("makepanda/myconfig.in")):
|
||||||
configprc = ReadFile("makepanda/myconfig.in")
|
configprc = ReadFile("makepanda/myconfig.in")
|
||||||
else:
|
else:
|
||||||
|
@ -593,8 +593,7 @@ remove_all_windows() {
|
|||||||
Windows old_windows;
|
Windows old_windows;
|
||||||
old_windows.swap(_windows);
|
old_windows.swap(_windows);
|
||||||
Windows::iterator wi;
|
Windows::iterator wi;
|
||||||
for (wi = old_windows.begin(); wi != old_windows.end(); ++wi) {
|
for (GraphicsOutput *win : old_windows) {
|
||||||
GraphicsOutput *win = (*wi);
|
|
||||||
nassertv(win != nullptr);
|
nassertv(win != nullptr);
|
||||||
do_remove_window(win, current_thread);
|
do_remove_window(win, current_thread);
|
||||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||||
@ -605,6 +604,14 @@ remove_all_windows() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
MutexHolder new_windows_holder(_new_windows_lock, current_thread);
|
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();
|
_new_windows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||||||
_munge_color(false),
|
_munge_color(false),
|
||||||
_munge_color_scale(false),
|
_munge_color_scale(false),
|
||||||
_auto_shader(false),
|
_auto_shader(false),
|
||||||
_shader_skinning(false)
|
_shader_skinning(false),
|
||||||
|
_remove_material(false)
|
||||||
{
|
{
|
||||||
const ShaderAttrib *shader_attrib;
|
const ShaderAttrib *shader_attrib;
|
||||||
state->get_attrib_def(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.
|
// 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) {
|
if (_auto_shader != om->_auto_shader) {
|
||||||
return (int)_auto_shader - (int)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);
|
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());
|
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;
|
return munged_state;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ private:
|
|||||||
bool _munge_color_scale;
|
bool _munge_color_scale;
|
||||||
bool _auto_shader;
|
bool _auto_shader;
|
||||||
bool _shader_skinning;
|
bool _shader_skinning;
|
||||||
|
bool _remove_material;
|
||||||
|
|
||||||
LColor _color;
|
LColor _color;
|
||||||
LVecBase4 _color_scale;
|
LVecBase4 _color_scale;
|
||||||
|
@ -99,6 +99,27 @@ PUBLISHED:
|
|||||||
|
|
||||||
virtual void output(std::ostream &out) const;
|
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:
|
protected:
|
||||||
void jump_to_task_chain(AsyncTaskManager *manager);
|
void jump_to_task_chain(AsyncTaskManager *manager);
|
||||||
DoneStatus unlock_and_do_task();
|
DoneStatus unlock_and_do_task();
|
||||||
|
@ -61,9 +61,6 @@ PUBLISHED:
|
|||||||
int __clear__();
|
int __clear__();
|
||||||
|
|
||||||
PUBLISHED:
|
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,
|
// The amount of seconds that have elapsed since the task was started,
|
||||||
// according to the task manager's clock.
|
// according to the task manager's clock.
|
||||||
MAKE_PROPERTY(time, get_elapsed_time);
|
MAKE_PROPERTY(time, get_elapsed_time);
|
||||||
@ -88,10 +85,6 @@ PUBLISHED:
|
|||||||
// according to the task manager's clock.
|
// according to the task manager's clock.
|
||||||
MAKE_PROPERTY(frame, get_elapsed_frames);
|
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
|
// This is a special variable to hold the instance dictionary in which
|
||||||
// custom variables may be stored.
|
// custom variables may be stored.
|
||||||
PyObject *__dict__;
|
PyObject *__dict__;
|
||||||
|
@ -283,6 +283,13 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
|||||||
rebuild_bitplanes();
|
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());
|
_gsg->set_current_properties(&get_fb_properties());
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
return true;
|
return true;
|
||||||
|
@ -69,14 +69,12 @@ PUBLISHED:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
// Period parameters
|
||||||
// Period parameters
|
static const unsigned long N = 624;
|
||||||
N = 624,
|
static const unsigned long M = 397;
|
||||||
M = 397,
|
static const unsigned long MATRIX_A = 0x9908b0dfUL; // constant vector a
|
||||||
MATRIX_A = 0x9908b0dfUL, // constant vector a
|
static const unsigned long UPPER_MASK = 0x80000000UL; // most significant w-r bits
|
||||||
UPPER_MASK = 0x80000000UL, // most significant w-r bits
|
static const unsigned long LOWER_MASK = 0x7fffffffUL; // least significant r bits
|
||||||
LOWER_MASK = 0x7fffffffUL, // least significant r bits
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned long mt[N]; // the array for the state vector
|
unsigned long mt[N]; // the array for the state vector
|
||||||
unsigned int mti; // mti==N+1 means mt[N] is not initialized
|
unsigned int mti; // mti==N+1 means mt[N] is not initialized
|
||||||
|
@ -12,10 +12,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "movieTypeRegistry.h"
|
#include "movieTypeRegistry.h"
|
||||||
|
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
#include "config_movies.h"
|
#include "config_movies.h"
|
||||||
#include "config_putil.h"
|
#include "config_putil.h"
|
||||||
#include "load_dso.h"
|
#include "load_dso.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
|
|
||||||
using std::endl;
|
using std::endl;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
271
tests/display/test_color_buffer.py
Normal file
271
tests/display/test_color_buffer.py
Normal file
@ -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)
|
||||||
|
|
@ -91,8 +91,6 @@ def render_depth_pixel(region, distance, near, far, clear=None, write=True):
|
|||||||
region.window.engine.render_frame()
|
region.window.engine.render_frame()
|
||||||
region.window.clear_render_textures()
|
region.window.clear_render_textures()
|
||||||
|
|
||||||
depth_texture.write("test2.png")
|
|
||||||
|
|
||||||
col = core.LColor()
|
col = core.LColor()
|
||||||
depth_texture.peek().lookup(col, 0.5, 0.5)
|
depth_texture.peek().lookup(col, 0.5, 0.5)
|
||||||
return col[0]
|
return col[0]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user