Add support for glLogicOp via LogicOpAttrib / NodePath::set_logic_op

This commit is contained in:
rdb 2016-03-25 17:33:30 +01:00
parent ba4c38112c
commit 82ab126ea7
10 changed files with 533 additions and 52 deletions

View File

@ -56,6 +56,7 @@
#include "depthWriteAttrib.h"
#include "fogAttrib.h"
#include "lightAttrib.h"
#include "logicOpAttrib.h"
#include "materialAttrib.h"
#include "rescaleNormalAttrib.h"
#include "scissorAttrib.h"
@ -475,6 +476,7 @@ reset() {
_inv_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
_inv_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
_inv_state_mask.clear_bit(ColorBlendAttrib::get_class_slot());
_inv_state_mask.clear_bit(LogicOpAttrib::get_class_slot());
_inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
_inv_state_mask.clear_bit(TexGenAttrib::get_class_slot());
_inv_state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
@ -6631,6 +6633,34 @@ do_issue_material() {
}
#endif // SUPPORT_FIXED_FUNCTION
/**
* Issues the logic operation attribute to the GL.
*/
#if !defined(OPENGLES) || defined(OPENGLES_1)
void CLP(GraphicsStateGuardian)::
do_issue_logic_op() {
const LogicOpAttrib *target_logic_op;
_target_rs->get_attrib_def(target_logic_op);
if (target_logic_op->get_operation() != LogicOpAttrib::O_none) {
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_CLEAR - 1 + (int)target_logic_op->get_operation());
if (GLCAT.is_spam()) {
GLCAT.spam() << "glEnable(GL_COLOR_LOGIC_OP)\n";
GLCAT.spam() << "glLogicOp(" << target_logic_op->get_operation() << ")\n";
}
} else {
glDisable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_COPY);
if (GLCAT.is_spam()) {
GLCAT.spam() << "glDisable(GL_COLOR_LOGIC_OP)\n";
}
}
}
#endif
/**
*
*/
@ -9660,6 +9690,16 @@ set_state_and_transform(const RenderState *target,
}
#endif
#if !defined(OPENGLES) || defined(OPENGLES_1)
int logic_op_slot = LogicOpAttrib::get_class_slot();
if (_target_rs->get_attrib(logic_op_slot) != _state_rs->get_attrib(logic_op_slot) ||
!_state_mask.get_bit(logic_op_slot)) {
// PStatGPUTimer timer(this, _draw_set_state_logic_op_pcollector);
do_issue_logic_op();
_state_mask.set_bit(logic_op_slot);
}
#endif
int transparency_slot = TransparencyAttrib::get_class_slot();
int color_write_slot = ColorWriteAttrib::get_class_slot();
int color_blend_slot = ColorBlendAttrib::get_class_slot();

View File

@ -405,6 +405,9 @@ protected:
void do_issue_material();
#endif
void do_issue_texture();
#if !defined(OPENGLES) || defined(OPENGLES_1)
void do_issue_logic_op();
#endif
void do_issue_blending();
#ifdef SUPPORT_FIXED_FUNCTION
void do_issue_tex_gen();

View File

@ -50,6 +50,7 @@
#include "loaderFileType.h"
#include "loaderFileTypeBam.h"
#include "loaderFileTypeRegistry.h"
#include "logicOpAttrib.h"
#include "materialAttrib.h"
#include "modelFlattenRequest.h"
#include "modelLoadRequest.h"
@ -419,6 +420,7 @@ init_libpgraph() {
Loader::init_type();
LoaderFileType::init_type();
LoaderFileTypeBam::init_type();
LogicOpAttrib::init_type();
MaterialAttrib::init_type();
ModelFlattenRequest::init_type();
ModelLoadRequest::init_type();
@ -483,6 +485,7 @@ init_libpgraph() {
LensNode::register_with_read_factory();
LightAttrib::register_with_read_factory();
LightRampAttrib::register_with_read_factory();
LogicOpAttrib::register_with_read_factory();
MaterialAttrib::register_with_read_factory();
ModelNode::register_with_read_factory();
ModelRoot::register_with_read_factory();

View File

@ -0,0 +1,29 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file logicOpAttrib.I
* @author rdb
* @date 2016-03-24
*/
/**
* Use LogicOpAttrib::make() to construct a new LogicOpAttrib object.
*/
INLINE LogicOpAttrib::
LogicOpAttrib(LogicOpAttrib::Operation op) :
_op(op)
{
}
/**
* Returns the logic operation specified by this attribute.
*/
INLINE LogicOpAttrib::Operation LogicOpAttrib::
get_operation() const {
return _op;
}

View File

@ -0,0 +1,205 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file logicOpAttrib.I
* @author rdb
* @date 2016-03-24
*/
#include "logicOpAttrib.h"
#include "graphicsStateGuardianBase.h"
#include "dcast.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle LogicOpAttrib::_type_handle;
int LogicOpAttrib::_attrib_slot;
/**
* Constructs a new LogicOpAttrib object that disables special-effect
* blending, allowing normal transparency to be used instead.
*/
CPT(RenderAttrib) LogicOpAttrib::
make_off() {
return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
}
/**
* Constructs a new LogicOpAttrib object with the given logic operation.
*/
CPT(RenderAttrib) LogicOpAttrib::
make(LogicOpAttrib::Operation op) {
LogicOpAttrib *attrib = new LogicOpAttrib(op);
return return_new(attrib);
}
/**
* Returns a RenderAttrib that corresponds to whatever the standard default
* properties for render attributes of this type ought to be.
*/
CPT(RenderAttrib) LogicOpAttrib::
make_default() {
return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
}
/**
*
*/
void LogicOpAttrib::
output(ostream &out) const {
out << get_type() << ":" << get_operation();
}
/**
* Intended to be overridden by derived LogicOpAttrib types to return a
* unique number indicating whether this LogicOpAttrib is equivalent to the
* other one.
*
* This should return 0 if the two LogicOpAttrib objects are equivalent, a
* number less than zero if this one should be sorted before the other one,
* and a number greater than zero otherwise.
*
* This will only be called with two LogicOpAttrib objects whose get_type()
* functions return the same.
*/
int LogicOpAttrib::
compare_to_impl(const RenderAttrib *other) const {
const LogicOpAttrib *la = (const LogicOpAttrib *)other;
return (int)_op - (int)la->_op;
}
/**
* Intended to be overridden by derived RenderAttrib types to return a unique
* hash for these particular properties. RenderAttribs that compare the same
* with compare_to_impl(), above, should return the same hash; RenderAttribs
* that compare differently should return a different hash.
*/
size_t LogicOpAttrib::
get_hash_impl() const {
size_t hash = 0;
hash = int_hash::add_hash(hash, (int)_op);
return hash;
}
/**
*
*/
CPT(RenderAttrib) LogicOpAttrib::
get_auto_shader_attrib_impl(const RenderState *state) const {
return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
}
/**
* Tells the BamReader how to create objects of type LogicOpAttrib.
*/
void LogicOpAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
/**
* Writes the contents of this object to the datagram for shipping out to a
* Bam file.
*/
void LogicOpAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_uint8(_op);
}
/**
* This function is called by the BamReader's factory when a new object of
* type LogicOpAttrib is encountered in the Bam file. It should create the
* LogicOpAttrib and extract its information from the file.
*/
TypedWritable *LogicOpAttrib::
make_from_bam(const FactoryParams &params) {
LogicOpAttrib *attrib = new LogicOpAttrib(O_none);
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return attrib;
}
/**
* This internal function is called by make_from_bam to read in all of the
* relevant data from the BamFile for the new LogicOpAttrib.
*/
void LogicOpAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_op = (Operation)scan.get_uint8();
}
/**
*
*/
ostream &
operator << (ostream &out, LogicOpAttrib::Operation op) {
switch (op) {
case LogicOpAttrib::O_none:
return out << "none";
case LogicOpAttrib::O_clear:
return out << "clear";
case LogicOpAttrib::O_and:
return out << "and";
case LogicOpAttrib::O_and_reverse:
return out << "and_reverse";
case LogicOpAttrib::O_copy:
return out << "copy";
case LogicOpAttrib::O_and_inverted:
return out << "and_inverted";
case LogicOpAttrib::O_noop:
return out << "noop";
case LogicOpAttrib::O_xor:
return out << "xor";
case LogicOpAttrib::O_or:
return out << "or";
case LogicOpAttrib::O_nor:
return out << "nor";
case LogicOpAttrib::O_equivalent:
return out << "equivalent";
case LogicOpAttrib::O_invert:
return out << "invert";
case LogicOpAttrib::O_or_reverse:
return out << "or_reverse";
case LogicOpAttrib::O_copy_inverted:
return out << "copy_inverted";
case LogicOpAttrib::O_or_inverted:
return out << "or_inverted";
case LogicOpAttrib::O_nand:
return out << "nand";
case LogicOpAttrib::O_set:
return out << "set";
}
return out << "**invalid LogicOpAttrib::Operation(" << (int)op << ")**";
}

View File

@ -0,0 +1,112 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file logicOpAttrib.I
* @author rdb
* @date 2016-03-24
*/
#ifndef LOGICOPATTRIB_H
#define LOGICOPATTRIB_H
#include "pandabase.h"
#include "luse.h"
#include "renderAttrib.h"
class FactoryParams;
/**
* If enabled, specifies that a custom logical operation be performed instead
* of any color blending. Setting it to a value other than M_none will cause
* color blending to be disabled and the given logic operation to be performed.
*/
class EXPCL_PANDA_PGRAPH LogicOpAttrib : public RenderAttrib {
PUBLISHED:
enum Operation {
O_none, // LogicOp disabled, regular blending occurs.
O_clear, // Clears framebuffer value.
O_and,
O_and_reverse,
O_copy, // Writes the incoming color to the framebuffer.
O_and_inverted,
O_noop, // Leaves the framebuffer value unaltered.
O_xor,
O_or,
O_nor,
O_equivalent,
O_invert,
O_or_reverse,
O_copy_inverted,
O_or_inverted,
O_nand,
O_set, // Sets all the bits in the framebuffer to 1.
};
private:
INLINE LogicOpAttrib(Operation op);
PUBLISHED:
static CPT(RenderAttrib) make_off();
static CPT(RenderAttrib) make(Operation op);
static CPT(RenderAttrib) make_default();
INLINE Operation get_operation() const;
MAKE_PROPERTY(operation, get_operation);
public:
virtual void output(ostream &out) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual size_t get_hash_impl() const;
virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
private:
Operation _op;
PUBLISHED:
static int get_class_slot() {
return _attrib_slot;
}
virtual int get_slot() const {
return get_class_slot();
}
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "LogicOpAttrib",
RenderAttrib::get_class_type());
_attrib_slot = register_slot(_type_handle, 100, new LogicOpAttrib(O_none));
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
static int _attrib_slot;
};
EXPCL_PANDA_PGRAPH ostream &operator << (ostream &out, LogicOpAttrib::Operation op);
#include "logicOpAttrib.I"
#endif

View File

@ -4832,6 +4832,62 @@ get_transparency() const {
return TransparencyAttrib::M_none;
}
/**
* Specifically sets or disables a logical operation on this particular node.
* If no other nodes override, this will cause geometry to be rendered without
* color blending but instead using the given logical operator.
*/
void NodePath::
set_logic_op(LogicOpAttrib::Operation op, int priority) {
nassertv_always(!is_empty());
node()->set_attrib(LogicOpAttrib::make(op), priority);
}
/**
* Completely removes any logical operation that may have been set on this
* node via set_logic_op(). The geometry at this level and below will
* subsequently be rendered using standard color blending.
*/
void NodePath::
clear_logic_op() {
nassertv_always(!is_empty());
node()->clear_attrib(LogicOpAttrib::get_class_slot());
}
/**
* Returns true if a logical operation has been explicitly set on this
* particular node via set_logic_op(). If this returns true, then
* get_logic_op() may be called to determine whether a logical operation has
* been explicitly disabled for this node or set to particular operation.
*/
bool NodePath::
has_logic_op() const {
nassertr_always(!is_empty(), false);
return node()->has_attrib(LogicOpAttrib::get_class_slot());
}
/**
* Returns the logical operation that has been specifically set on this node
* via set_logic_op(), or O_none if standard color blending has been
* specifically set, or if nothing has been specifically set. See also
* has_logic_op(). This does not necessarily imply that the geometry will
* or will not be rendered with the given logical operation, as there may be
* other nodes that override.
*/
LogicOpAttrib::Operation NodePath::
get_logic_op() const {
nassertr_always(!is_empty(), LogicOpAttrib::O_none);
const RenderAttrib *attrib =
node()->get_attrib(LogicOpAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) {
const LogicOpAttrib *ta = DCAST(LogicOpAttrib, attrib);
return ta->get_operation();
}
return LogicOpAttrib::O_none;
}
/**
* Specifies the antialiasing type that should be applied at this node and
* below. See AntialiasAttrib.

View File

@ -26,6 +26,7 @@
#include "transformState.h"
#include "renderModeAttrib.h"
#include "transparencyAttrib.h"
#include "logicOpAttrib.h"
#include "nodePathComponent.h"
#include "pointerTo.h"
#include "referenceCount.h"
@ -62,57 +63,83 @@ class SamplerState;
class Shader;
class ShaderInput;
/*
* A NodePath is the fundamental unit of high-level interaction with the scene
* graph. It encapsulates the complete path down to a node from some other
* node, usually the root of the scene graph. This is used to resolve
* ambiguities associated with instancing. NodePath also contains a number of
* handy high-level methods for common scene-graph manipulations, such as
* reparenting, and common state changes, such as repositioning. There are
* also a number of NodePath methods for finding nodes deep within the tree by
* name or by type. These take a path string, which at its simplest consists
* of a series of node names separated by slashes, like a directory pathname.
* Each component of the path string may optionally consist of one of the
* following special names, instead of a node name: * -- matches
* exactly one node, with any name. ** -- matches any sequence of
* zero or more nodes. +typename -- matches any node that is or derives from
* the given type. -typename -- matches any node that is the given type
* exactly. =tag -- matches any node that has the indicated tag.
* =tag=value -- matches any node whose tag matches the indicated value.
* Furthermore, a node name may itself contain standard filename globbing
* characters, like *, ?, and [a-z], that will be accepted as a partial match.
* (In fact, the '*' special name may be seen as just a special case of this.)
* The globbing characters may not be used with the typename matches or with
* tag matches, but they may be used to match a tag's value in the =tag=value
* syntax. The special characters "@@", appearing at the beginning of a node
* name, indicate a stashed node. Normally, stashed nodes are not returned by
* a find (but see the special flags, below), but a stashed node may be found
* if it is explicitly named with its leading @@ characters. By extension,
* "@@*" may be used to identify any stashed node. Examples: "roomgraph" will
* look for a node named "graph", which is a child of an unnamed node, which
* is a child of a node named "room", which is a child of the starting path.
* "**red*" will look for any node anywhere in the tree (below the starting
* path) with a name that begins with "red". "**+PartBundleNode**head" will
* look for a node named "head", somewhere below a PartBundleNode anywhere in
* the tree. The search is always potentially ambiguous, even if the special
* wildcard operators are not used, because there may be multiple nodes in the
* tree with the same name. In general, in the case of an ambiguity, the
* shortest path is preferred; when a method (such as extend_by) must choose
* only only one of several possible paths, it will choose the shortest
* available; on the other hand, when a method (such as find_all_matches) is
* to return all of the matching paths, it will sort them so that the shortest
* paths appear first in the output. Special flags. The entire string may
* optionally be followed by the ";" character, followed by one or more of the
* following special control flags, with no intervening spaces or punctuation:
* -h Do not return hidden nodes. +h Do return hidden nodes. -s Do
* not return stashed nodes unless explicitly referenced with @@. +s Return
* stashed nodes even without any explicit @@ characters. -i Node name
* comparisons are not case insensitive: case must match exactly. +i Node
* name comparisons are case insensitive: case is not important. This affects
* matches against the node name only; node type and tag strings are always
* case sensitive. The default flags are +h-s-i.
*/
//
// A NodePath is the fundamental unit of high-level interaction with the scene
// graph. It encapsulates the complete path down to a node from some other
// node, usually the root of the scene graph. This is used to resolve
// ambiguities associated with instancing.
//
// NodePath also contains a number of handy high-level methods for common
// scene-graph manipulations, such as reparenting, and common state changes,
// such as repositioning.
//
// There are also a number of NodePath methods for finding nodes deep within
// the tree by name or by type. These take a path string, which at its
// simplest consists of a series of node names separated by slashes, like a
// directory pathname.
//
// Each component of the path string may optionally consist of one of the
// following special names, instead of a node name:
//
// * -- matches exactly one node, with any name.
// ** -- matches any sequence of zero or more nodes.
// +typename -- matches any node that is or derives from the given type.
// -typename -- matches any node that is the given type exactly.
// =tag -- matches any node that has the indicated tag.
// =tag=value -- matches any node whose tag matches the indicated value.
//
// Furthermore, a node name may itself contain standard filename globbing
// characters, like *, ?, and [a-z], that will be accepted as a partial match.
// (In fact, the '*' special name may be seen as just a special case of this.)
// The globbing characters may not be used with the typename matches or with
// tag matches, but they may be used to match a tag's value in the =tag=value
// syntax.
//
// The special characters "@@", appearing at the beginning of a node name,
// indicate a stashed node. Normally, stashed nodes are not returned by a
// find (but see the special flags, below), but a stashed node may be found if
// it is explicitly named with its leading @@ characters. By extension, "@@*"
// may be used to identify any stashed node.
//
// Examples:
//
// "room//graph" will look for a node named "graph", which is a child of an
// unnamed node, which is a child of a node named "room", which is a child of
// the starting path.
//
// "**/red*" will look for any node anywhere in the tree (below the starting
// path) with a name that begins with "red".
//
// "**/+PartBundleNode/**/head" will look for a node named "head", somewhere
// below a PartBundleNode anywhere in the tree.
//
//
// The search is always potentially ambiguous, even if the special wildcard
// operators are not used, because there may be multiple nodes in the tree
// with the same name. In general, in the case of an ambiguity, the shortest
// path is preferred; when a method (such as extend_by) must choose only only
// one of several possible paths, it will choose the shortest available; on
// the other hand, when a method (such as find_all_matches) is to return all
// of the matching paths, it will sort them so that the shortest paths appear
// first in the output.
//
//
// Special flags. The entire string may optionally be followed by the ";"
// character, followed by one or more of the following special control flags,
// with no intervening spaces or punctuation:
//
// -h Do not return hidden nodes.
// +h Do return hidden nodes.
// -s Do not return stashed nodes unless explicitly referenced with @@.
// +s Return stashed nodes even without any explicit @@ characters.
// -i Node name comparisons are not case insensitive: case must match
// exactly.
// +i Node name comparisons are case insensitive: case is not important.
// This affects matches against the node name only; node type and tag
// strings are always case sensitive.
//
// The default flags are +h-s-i.
//
/**
* NodePath is the fundamental system for disambiguating instances, and also
@ -786,6 +813,11 @@ PUBLISHED:
bool has_transparency() const;
TransparencyAttrib::Mode get_transparency() const;
void set_logic_op(LogicOpAttrib::Operation op, int priority = 0);
void clear_logic_op();
bool has_logic_op() const;
LogicOpAttrib::Operation get_logic_op() const;
void set_antialias(unsigned short mode, int priority = 0);
void clear_antialias();
bool has_antialias() const;

View File

@ -7,6 +7,7 @@
#include "loaderFileType.cxx"
#include "loaderFileTypeBam.cxx"
#include "loaderFileTypeRegistry.cxx"
#include "logicOpAttrib.cxx"
#include "materialAttrib.cxx"
#include "materialCollection.cxx"
#include "modelFlattenRequest.cxx"

View File

@ -47,7 +47,7 @@ public:
// Raise this number whenever we add a new attrib. This used to be
// determined at runtime, but it's better to have it as a constexpr.
static const int _max_slots = 29;
static const int _max_slots = 32;
int register_slot(TypeHandle type_handle, int sort,
RenderAttrib *default_attrib);