mirror of
https://github.com/panda3d/panda3d.git
synced 2026-05-06 14:40:26 -05:00
Merge branch 'release/1.10.x'
This commit is contained in:
@@ -100,6 +100,11 @@ void fshader(out float4 o_color : COLOR,
|
||||
"""
|
||||
|
||||
|
||||
class ToneMap:
|
||||
ACES = object()
|
||||
PBR_NEUTRAL = object()
|
||||
|
||||
|
||||
class FilterConfig:
|
||||
pass
|
||||
|
||||
@@ -279,16 +284,19 @@ class CommonFilters:
|
||||
|
||||
text = "//Cg\n"
|
||||
if "HighDynamicRange" in configuration:
|
||||
text += "static const float3x3 aces_input_mat = {\n"
|
||||
text += " {0.59719, 0.35458, 0.04823},\n"
|
||||
text += " {0.07600, 0.90834, 0.01566},\n"
|
||||
text += " {0.02840, 0.13383, 0.83777},\n"
|
||||
text += "};\n"
|
||||
text += "static const float3x3 aces_output_mat = {\n"
|
||||
text += " { 1.60475, -0.53108, -0.07367},\n"
|
||||
text += " {-0.10208, 1.10813, -0.00605},\n"
|
||||
text += " {-0.00327, -0.07276, 1.07602},\n"
|
||||
text += "};\n"
|
||||
tonemap = configuration["HighDynamicRange"]
|
||||
if tonemap is ToneMap.ACES:
|
||||
text += "static const float3x3 aces_input_mat = {\n"
|
||||
text += " {0.59719, 0.35458, 0.04823},\n"
|
||||
text += " {0.07600, 0.90834, 0.01566},\n"
|
||||
text += " {0.02840, 0.13383, 0.83777},\n"
|
||||
text += "};\n"
|
||||
text += "static const float3x3 aces_output_mat = {\n"
|
||||
text += " { 1.60475, -0.53108, -0.07367},\n"
|
||||
text += " {-0.10208, 1.10813, -0.00605},\n"
|
||||
text += " {-0.00327, -0.07276, 1.07602},\n"
|
||||
text += "};\n"
|
||||
|
||||
text += "void vshader(float4 vtx_position : POSITION,\n"
|
||||
text += " out float4 l_position : POSITION,\n"
|
||||
|
||||
@@ -381,10 +389,30 @@ class CommonFilters:
|
||||
if "ExposureAdjust" in configuration:
|
||||
text += " o_color.rgb *= k_exposure;\n"
|
||||
|
||||
# With thanks to Stephen Hill!
|
||||
if "HighDynamicRange" in configuration:
|
||||
text += " float3 aces_color = mul(aces_input_mat, o_color.rgb);\n"
|
||||
text += " o_color.rgb = saturate(mul(aces_output_mat, (aces_color * (aces_color + 0.0245786f) - 0.000090537f) / (aces_color * (0.983729f * aces_color + 0.4329510f) + 0.238081f)));\n"
|
||||
tonemap = configuration["HighDynamicRange"]
|
||||
if tonemap is ToneMap.ACES:
|
||||
# With thanks to Stephen Hill!
|
||||
text += " float3 aces_color = mul(aces_input_mat, o_color.rgb);\n"
|
||||
text += " o_color.rgb = saturate(mul(aces_output_mat, (aces_color * (aces_color + 0.0245786f) - 0.000090537f) / (aces_color * (0.983729f * aces_color + 0.4329510f) + 0.238081f)));\n"
|
||||
elif tonemap is ToneMap.PBR_NEUTRAL:
|
||||
text += " const float start_compression = 0.8 - 0.04;\n"
|
||||
text += " const float desaturation = 0.15;\n"
|
||||
|
||||
text += " float x = min(o_color.r, min(o_color.g, o_color.b));\n"
|
||||
text += " float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n"
|
||||
text += " o_color.rgb -= offset;\n"
|
||||
|
||||
text += " float peak = max(o_color.r, max(o_color.g, o_color.b));\n"
|
||||
|
||||
text += " if (peak >= start_compression) {\n"
|
||||
text += " const float d = 1.0 - start_compression;\n"
|
||||
text += " float new_peak = 1.0 - d * d / (peak + d - start_compression);\n"
|
||||
text += " o_color.rgb *= new_peak / peak;\n"
|
||||
text += " float g = 1.0 - 1.0 / (desaturation * (peak - new_peak) + 1.0);\n"
|
||||
|
||||
text += " o_color.rgb = lerp(o_color.rgb, new_peak * float3(1, 1, 1), g);\n"
|
||||
text += "}\n"
|
||||
|
||||
if "GammaAdjust" in configuration:
|
||||
gamma = configuration["GammaAdjust"]
|
||||
@@ -668,10 +696,10 @@ class CommonFilters:
|
||||
return self.reconfigure(old_enable, "SrgbEncode")
|
||||
return True
|
||||
|
||||
def setHighDynamicRange(self):
|
||||
def setHighDynamicRange(self, tonemap=ToneMap.ACES):
|
||||
""" Enables HDR rendering by using a floating-point framebuffer,
|
||||
disabling color clamping on the main scene, and applying a tone map
|
||||
operator (ACES).
|
||||
operator (ACES or Khronos PBR Neutral).
|
||||
|
||||
It may also be necessary to use setExposureAdjust to perform exposure
|
||||
compensation on the scene, depending on the lighting intensity.
|
||||
@@ -679,8 +707,11 @@ class CommonFilters:
|
||||
.. versionadded:: 1.10.7
|
||||
"""
|
||||
|
||||
fullrebuild = (("HighDynamicRange" in self.configuration) is False)
|
||||
self.configuration["HighDynamicRange"] = 1
|
||||
fullrebuild = "HighDynamicRange" not in self.configuration or \
|
||||
self.configuration["HighDynamicRange"] is not tonemap
|
||||
if tonemap is not ToneMap.ACES and tonemap is not ToneMap.PBR_NEUTRAL:
|
||||
raise ValueError("Invalid value for tonemap")
|
||||
self.configuration["HighDynamicRange"] = tonemap
|
||||
return self.reconfigure(fullrebuild, "HighDynamicRange")
|
||||
|
||||
def delHighDynamicRange(self):
|
||||
|
||||
@@ -485,9 +485,8 @@ class FSM(DirectObject):
|
||||
new_index = (cur_index + 1) % len(self.stateArray)
|
||||
return self.request(self.stateArray[new_index], args)
|
||||
else:
|
||||
assert self.notifier.debug(
|
||||
assert self.notify.debug(
|
||||
"stateArray empty. Can't switch to next.")
|
||||
|
||||
finally:
|
||||
self.fsmLock.release()
|
||||
|
||||
@@ -503,7 +502,7 @@ class FSM(DirectObject):
|
||||
new_index = (cur_index - 1) % len(self.stateArray)
|
||||
return self.request(self.stateArray[new_index], args)
|
||||
else:
|
||||
assert self.notifier.debug(
|
||||
assert self.notify.debug(
|
||||
"stateArray empty. Can't switch to next.")
|
||||
finally:
|
||||
self.fsmLock.release()
|
||||
|
||||
@@ -679,7 +679,7 @@ write(std::ostream &out, int indent_level) const {
|
||||
int total_digits = num_decimals + 4;
|
||||
static const int max_digits = 32; // totally arbitrary
|
||||
nassertv(total_digits <= max_digits);
|
||||
char format_str[16];
|
||||
char format_str[26];
|
||||
sprintf(format_str, "%%%d.%df", total_digits, num_decimals);
|
||||
|
||||
indent(out, indent_level) << get_name() << ":\n";
|
||||
@@ -708,7 +708,7 @@ timeline(std::ostream &out) const {
|
||||
int total_digits = num_decimals + 4;
|
||||
static const int max_digits = 32; // totally arbitrary
|
||||
nassertv(total_digits <= max_digits);
|
||||
char format_str[16];
|
||||
char format_str[26];
|
||||
sprintf(format_str, "%%%d.%df", total_digits, num_decimals);
|
||||
|
||||
int extra_indent_level = 0;
|
||||
|
||||
@@ -52,7 +52,7 @@ def glob1(dirname, pattern):
|
||||
if not dirname:
|
||||
dirname = os.curdir
|
||||
try:
|
||||
names = os.listdir(dirname)
|
||||
names = file.listdir(dirname)
|
||||
except os.error:
|
||||
return []
|
||||
if pattern[0] != '.':
|
||||
|
||||
@@ -1839,7 +1839,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
||||
<< " is bound to image unit " << binding << "\n";
|
||||
}
|
||||
|
||||
if (binding >= _glsl_img_inputs.size()) {
|
||||
if (binding >= (GLint)_glsl_img_inputs.size()) {
|
||||
_glsl_img_inputs.resize(binding + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -775,9 +775,14 @@ move(const MouseWatcherParameter ¶m) {
|
||||
*/
|
||||
void PGItem::
|
||||
background_press(const MouseWatcherParameter ¶m) {
|
||||
for (PGItem *item : _background_focus) {
|
||||
// We have to be careful, because objects may remove themselves from the set
|
||||
// while we're iterating over it.
|
||||
auto it = _background_focus.begin();
|
||||
while (it != _background_focus.end()) {
|
||||
PGItem *item = *it++;
|
||||
if (!item->get_focus()) {
|
||||
item->press(param, true);
|
||||
PT(PGItem) item_ref(item);
|
||||
item_ref->press(param, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -787,9 +792,12 @@ background_press(const MouseWatcherParameter ¶m) {
|
||||
*/
|
||||
void PGItem::
|
||||
background_release(const MouseWatcherParameter ¶m) {
|
||||
for (PGItem *item : _background_focus) {
|
||||
auto it = _background_focus.begin();
|
||||
while (it != _background_focus.end()) {
|
||||
PGItem *item = *it++;
|
||||
if (!item->get_focus()) {
|
||||
item->release(param, true);
|
||||
PT(PGItem) item_ref(item);
|
||||
item_ref->release(param, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -799,9 +807,12 @@ background_release(const MouseWatcherParameter ¶m) {
|
||||
*/
|
||||
void PGItem::
|
||||
background_keystroke(const MouseWatcherParameter ¶m) {
|
||||
for (PGItem *item : _background_focus) {
|
||||
auto it = _background_focus.begin();
|
||||
while (it != _background_focus.end()) {
|
||||
PGItem *item = *it++;
|
||||
if (!item->get_focus()) {
|
||||
item->keystroke(param, true);
|
||||
PT(PGItem) item_ref(item);
|
||||
item_ref->keystroke(param, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -811,9 +822,12 @@ background_keystroke(const MouseWatcherParameter ¶m) {
|
||||
*/
|
||||
void PGItem::
|
||||
background_candidate(const MouseWatcherParameter ¶m) {
|
||||
for (PGItem *item : _background_focus) {
|
||||
auto it = _background_focus.begin();
|
||||
while (it != _background_focus.end()) {
|
||||
PGItem *item = *it++;
|
||||
if (!item->get_focus()) {
|
||||
item->candidate(param, true);
|
||||
PT(PGItem) item_ref(item);
|
||||
item_ref->candidate(param, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,8 +292,8 @@ remove(const Key &key) {
|
||||
|
||||
// Now remove this element.
|
||||
size_t last = _num_entries - 1;
|
||||
size_t index = (size_t)index_array[slot];
|
||||
if (index < _num_entries) {
|
||||
int index = index_array[slot];
|
||||
if ((size_t)index < _num_entries) {
|
||||
// Find the last element in the index array.
|
||||
int other_slot = find_slot(_table[last]._key);
|
||||
nassertr(other_slot != -1, false);
|
||||
@@ -301,7 +301,7 @@ remove(const Key &key) {
|
||||
|
||||
// Swap it with the last one, so that we don't get any gaps in the table
|
||||
// of entries.
|
||||
_table[index] = std::move(_table[last]);
|
||||
_table[(size_t)index] = std::move(_table[last]);
|
||||
index_array[(size_t)other_slot] = index;
|
||||
}
|
||||
|
||||
@@ -321,13 +321,13 @@ remove(const Key &key) {
|
||||
// Now we have put a hole in the index array. If there was a hash conflict
|
||||
// in the slot after this one, we have to move it down to close the hole.
|
||||
slot = next_hash(slot);
|
||||
while (has_slot(slot)) {
|
||||
size_t index = (size_t)index_array[slot];
|
||||
index = index_array[slot];
|
||||
while (index >= 0) {
|
||||
size_t wants_slot = get_hash(_table[index]._key);
|
||||
if (wants_slot != slot) {
|
||||
// This one was a hash conflict; try to put it where it belongs. We
|
||||
// can't just put it in n, since maybe it belongs somewhere after n.
|
||||
while (wants_slot != slot && has_slot(wants_slot)) {
|
||||
while (wants_slot != slot && index_array[wants_slot] >= 0) {
|
||||
wants_slot = next_hash(wants_slot);
|
||||
}
|
||||
if (wants_slot != slot) {
|
||||
@@ -341,6 +341,7 @@ remove(const Key &key) {
|
||||
// Continue until we encounter the next unused slot. Until we do, we
|
||||
// can't be sure we've found all of the potential hash conflicts.
|
||||
slot = next_hash(slot);
|
||||
index = index_array[slot];
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
@@ -427,14 +427,14 @@ calc_r_c(int &r, int &c, int n) const {
|
||||
c = 0;
|
||||
int i = row._row_start;
|
||||
while (i < n - 1) {
|
||||
if (_text_string[i]._character != text_soft_hyphen_key &&
|
||||
_text_string[i]._character != text_soft_break_key) {
|
||||
if (_text_string[i]._character != (char32_t)text_soft_hyphen_key &&
|
||||
_text_string[i]._character != (char32_t)text_soft_break_key) {
|
||||
++c;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (_text_string[n - 1]._character != text_soft_hyphen_key &&
|
||||
_text_string[n - 1]._character != text_soft_break_key) {
|
||||
if (_text_string[n - 1]._character != (char32_t)text_soft_hyphen_key &&
|
||||
_text_string[n - 1]._character != (char32_t)text_soft_break_key) {
|
||||
++c;
|
||||
if (_text_string[n - 1]._character == '\n') {
|
||||
is_real_char = false;
|
||||
@@ -478,8 +478,8 @@ calc_index(int r, int c) const {
|
||||
// we have to scan past them to get n precisely.
|
||||
int n = row._row_start;
|
||||
while (c > 0) {
|
||||
if (_text_string[n]._character != text_soft_hyphen_key &&
|
||||
_text_string[n]._character != text_soft_break_key) {
|
||||
if (_text_string[n]._character != (char32_t)text_soft_hyphen_key &&
|
||||
_text_string[n]._character != (char32_t)text_soft_break_key) {
|
||||
--c;
|
||||
}
|
||||
++n;
|
||||
@@ -798,13 +798,13 @@ scan_wtext(TextAssembler::TextString &output_string,
|
||||
const wstring::const_iterator &send,
|
||||
TextAssembler::ComputedProperties *current_cprops) {
|
||||
while (si != send) {
|
||||
if ((*si) == text_push_properties_key) {
|
||||
if ((*si) == (wchar_t)text_push_properties_key) {
|
||||
// This indicates a nested properties structure. Pull off the name of
|
||||
// the TextProperties structure, which is everything until the next
|
||||
// text_push_properties_key.
|
||||
wstring wname;
|
||||
++si;
|
||||
while (si != send && (*si) != text_push_properties_key) {
|
||||
while (si != send && (*si) != (wchar_t)text_push_properties_key) {
|
||||
wname += (*si);
|
||||
++si;
|
||||
}
|
||||
@@ -835,20 +835,20 @@ scan_wtext(TextAssembler::TextString &output_string,
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*si) == text_pop_properties_key) {
|
||||
} else if ((*si) == (wchar_t)text_pop_properties_key) {
|
||||
// This indicates the undoing of a previous push_properties_key. We
|
||||
// simply return to the previous level.
|
||||
++si;
|
||||
return;
|
||||
|
||||
} else if ((*si) == text_embed_graphic_key) {
|
||||
} else if ((*si) == (wchar_t)text_embed_graphic_key) {
|
||||
// This indicates an embedded graphic. Pull off the name of the
|
||||
// TextGraphic structure, which is everything until the next
|
||||
// text_embed_graphic_key.
|
||||
|
||||
wstring graphic_wname;
|
||||
++si;
|
||||
while (si != send && (*si) != text_embed_graphic_key) {
|
||||
while (si != send && (*si) != (wchar_t)text_embed_graphic_key) {
|
||||
graphic_wname += (*si);
|
||||
++si;
|
||||
}
|
||||
@@ -980,7 +980,7 @@ wordwrap_text() {
|
||||
}
|
||||
|
||||
if (isspacew(_text_string[q]._character) ||
|
||||
_text_string[q]._character == text_soft_break_key) {
|
||||
_text_string[q]._character == (char32_t)text_soft_break_key) {
|
||||
if (!last_was_space) {
|
||||
any_spaces = true;
|
||||
// We only care about logging whether there is a soft-hyphen
|
||||
@@ -997,7 +997,7 @@ wordwrap_text() {
|
||||
|
||||
// A soft hyphen character is not printed, but marks a point at which we
|
||||
// might hyphenate a word if we need to.
|
||||
if (_text_string[q]._character == text_soft_hyphen_key) {
|
||||
if (_text_string[q]._character == (char32_t)text_soft_hyphen_key) {
|
||||
if (wordwrap_width > 0.0f) {
|
||||
// We only consider this as a possible hyphenation point if (a) it
|
||||
// is not the very first character, and (b) there is enough room for
|
||||
@@ -1104,8 +1104,8 @@ wordwrap_text() {
|
||||
}
|
||||
|
||||
for (size_t pi = p; pi < q; pi++) {
|
||||
if (_text_string[pi]._character != text_soft_hyphen_key &&
|
||||
_text_string[pi]._character != text_soft_break_key) {
|
||||
if (_text_string[pi]._character != (char32_t)text_soft_hyphen_key &&
|
||||
_text_string[pi]._character != (char32_t)text_soft_break_key) {
|
||||
_text_block.back()._string.push_back(_text_string[pi]);
|
||||
} else {
|
||||
_text_block.back()._got_soft_hyphens = true;
|
||||
@@ -1577,7 +1577,7 @@ assemble_row(TextAssembler::TextRow &row,
|
||||
xpos = (floor(xpos / tab_width) + 1.0f) * tab_width;
|
||||
prev_char = -1;
|
||||
|
||||
} else if (character == text_soft_hyphen_key) {
|
||||
} else if (character == (char32_t)text_soft_hyphen_key) {
|
||||
// And so is the 'soft-hyphen' key character.
|
||||
|
||||
} else if (graphic != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user