initial rough pass at hierarchical z-buffer visibility. experimental.

This commit is contained in:
David Rose 2006-03-29 20:28:33 +00:00
parent f594fa67ad
commit c0844239f1
35 changed files with 1646 additions and 77 deletions

View File

@ -9,13 +9,15 @@
#define TARGET cull
#define SOURCES \
binCullHandler.h \
binCullHandler.h binCullHandler.I \
config_cull.h \
cullBinBackToFront.h cullBinFixed.h \
cullBinFrontToBack.h cullBinStateSorted.h cullBinUnsorted.h \
drawCullHandler.h binCullHandler.I cullBinBackToFront.I \
cullBinFixed.I cullBinFrontToBack.I cullBinStateSorted.I \
cullBinUnsorted.I drawCullHandler.I
cullBinBackToFront.h cullBinBackToFront.I \
cullBinFixed.h cullBinFixed.I \
cullBinFrontToBack.h cullBinFrontToBack.I \
cullBinHierarchicalZBuffer.h cullBinHierarchicalZBuffer.I \
cullBinStateSorted.h cullBinStateSorted.I \
cullBinUnsorted.h cullBinUnsorted.I \
drawCullHandler.h drawCullHandler.I
#define COMBINED_SOURCES \
$[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
@ -26,18 +28,21 @@
cullBinBackToFront.cxx \
cullBinFixed.cxx \
cullBinFrontToBack.cxx \
cullBinHierarchicalZBuffer.cxx \
cullBinStateSorted.cxx \
cullBinUnsorted.cxx \
drawCullHandler.cxx
#define INSTALL_HEADERS \
binCullHandler.h \
binCullHandler.h binCullHandler.I \
config_cull.h \
cullBinBackToFront.h cullBinFixed.h \
cullBinFrontToBack.h cullBinStateSorted.h cullBinUnsorted.h \
drawCullHandler.h binCullHandler.I cullBinBackToFront.I \
cullBinFixed.I cullBinFrontToBack.I cullBinStateSorted.I \
cullBinUnsorted.I drawCullHandler.I
cullBinBackToFront.h cullBinBackToFront.I \
cullBinFixed.h cullBinFixed.I \
cullBinFrontToBack.h cullBinFrontToBack.I \
cullBinHierarchicalZBuffer.h cullBinHierarchicalZBuffer.I \
cullBinStateSorted.h cullBinStateSorted.I \
cullBinUnsorted.h cullBinUnsorted.I \
drawCullHandler.h drawCullHandler.I
#define IGATESCAN all

View File

@ -21,6 +21,7 @@
#include "cullBinBackToFront.h"
#include "cullBinFixed.h"
#include "cullBinFrontToBack.h"
#include "cullBinHierarchicalZBuffer.h"
#include "cullBinStateSorted.h"
#include "cullBinUnsorted.h"
@ -34,6 +35,18 @@ ConfigureFn(config_cull) {
init_libcull();
}
ConfigVariableInt max_objects_per_octree_node
("max-objects-per-octree-node", 10,
PRC_DESC("Specifies the maximum number of objects collected per octree "
"node, by the hierarchical-z cull bin algorithm."));
ConfigVariableDouble octree_multiassign_ratio
("octree-multiassign-ratio", 0.1,
PRC_DESC("Objects that intersect a bisecting plane of an octree node must "
"be at least this fraction of the node's linear dimension in "
"order to be assigned to the node itself. If the object is smaller "
"than this, it will be multiply assigned to the node's children."));
////////////////////////////////////////////////////////////////////
// Function: init_libcull
// Description: Initializes the library. This must be called at
@ -53,6 +66,7 @@ init_libcull() {
CullBinBackToFront::init_type();
CullBinFixed::init_type();
CullBinFrontToBack::init_type();
CullBinHierarchicalZBuffer::init_type();
CullBinStateSorted::init_type();
CullBinUnsorted::init_type();
@ -67,4 +81,6 @@ init_libcull() {
CullBinFrontToBack::make_bin);
bin_manager->register_bin_type(CullBinManager::BT_fixed,
CullBinFixed::make_bin);
bin_manager->register_bin_type(CullBinManager::BT_hierarchical_z,
CullBinHierarchicalZBuffer::make_bin);
}

View File

@ -22,12 +22,17 @@
#include "pandabase.h"
#include "notifyCategoryProxy.h"
#include "dconfig.h"
#include "configVariableInt.h"
#include "configVariableDouble.h"
class DSearchPath;
ConfigureDecl(config_cull, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(cull, EXPCL_PANDA, EXPTP_PANDA);
extern ConfigVariableInt max_objects_per_octree_node;
extern ConfigVariableDouble octree_multiassign_ratio;
extern EXPCL_PANDA void init_libcull();
#endif

View File

@ -63,8 +63,7 @@ add_object(CullableObject *object) {
// Determine the center of the bounding volume.
CPT(BoundingVolume) volume = object->_geom->get_bounds();
if (!volume->is_empty() &&
volume->is_of_type(GeometricBoundingVolume::get_class_type())) {
if (!volume->is_empty()) {
const GeometricBoundingVolume *gbv;
DCAST_INTO_V(gbv, volume);

View File

@ -63,8 +63,7 @@ add_object(CullableObject *object) {
// Determine the center of the bounding volume.
CPT(BoundingVolume) volume = object->_geom->get_bounds();
if (!volume->is_empty() &&
volume->is_of_type(GeometricBoundingVolume::get_class_type())) {
if (!volume->is_empty()) {
const GeometricBoundingVolume *gbv;
DCAST_INTO_V(gbv, volume);

View File

@ -0,0 +1,111 @@
// Filename: cullBinHierarchicalZBuffer.I
// Created by: drose (24Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::ObjectData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CullBinHierarchicalZBuffer::ObjectData::
ObjectData(CullableObject *object, BoundingSphere *bounds) :
_object(object),
_bounds(bounds)
{
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::ObjectData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CullBinHierarchicalZBuffer::ObjectData::
ObjectData(const CullBinHierarchicalZBuffer::ObjectData &copy) :
_object(copy._object),
_bounds(copy._bounds)
{
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::ObjectData::Copy Assignment
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void CullBinHierarchicalZBuffer::ObjectData::
operator = (const CullBinHierarchicalZBuffer::ObjectData &copy) {
_object = copy._object;
_bounds = copy._bounds;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CullBinHierarchicalZBuffer::
CullBinHierarchicalZBuffer(const string &name, GraphicsStateGuardianBase *gsg) :
CullBin(name, gsg)
{
nassertv(_gsg->get_supports_occlusion_query());
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::initial_assign
// Access: Public
// Description: Assigns the object to the node, in preparation for
// calling group_objects().
////////////////////////////////////////////////////////////////////
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
initial_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
_objects.push_back(object_data);
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::reassign
// Access: Public
// Description: After determining that the object bisects one of the
// major planes of the node, reassigns it back to the
// same node.
////////////////////////////////////////////////////////////////////
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
reassign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
if (object_data._bounds->get_radius() / _half_side >= octree_multiassign_ratio) {
// The object is large enough to keep in this node.
//cerr << " reassigning.\n";
_objects.push_back(object_data);
} else {
//cerr << " multidistributing.\n";
multi_assign(object_data);
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::assign_to_corner
// Access: Private
// Description: Assigns the object to the octree node in the
// indicated corner.
////////////////////////////////////////////////////////////////////
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
assign_to_corner(int index, const CullBinHierarchicalZBuffer::ObjectData &object_data) {
//cerr << " Assigning to corner " << hex << index << dec << ".\n";
nassertv(index >= 0 && index < 8);
if (_corners[index] == NULL) {
make_corner(index);
}
_corners[index]->initial_assign(object_data);
}

View File

@ -0,0 +1,779 @@
// Filename: cullBinHierarchicalZBuffer.cxx
// Created by: drose (24Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "cullBinHierarchicalZBuffer.h"
#include "graphicsStateGuardianBase.h"
#include "geometricBoundingVolume.h"
#include "geomLines.h"
#include "geomTriangles.h"
#include "geomVertexWriter.h"
#include "depthWriteAttrib.h"
#include "depthTestAttrib.h"
#include "colorWriteAttrib.h"
#include "cullableObject.h"
#include "cullHandler.h"
#include "pStatTimer.h"
#include "config_cull.h"
#include "thread.h"
PStatCollector CullBinHierarchicalZBuffer::_wait_occlusion_pcollector("Wait:Occlusion test");
PT(Geom) CullBinHierarchicalZBuffer::_octree_solid_test;
PT(Geom) CullBinHierarchicalZBuffer::_octree_wireframe_viz;
CPT(RenderState) CullBinHierarchicalZBuffer::_octree_solid_test_state;
TypeHandle CullBinHierarchicalZBuffer::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CullBinHierarchicalZBuffer::
~CullBinHierarchicalZBuffer() {
ObjectPointers::iterator pi;
for (pi = _object_pointers.begin(); pi != _object_pointers.end(); ++pi) {
delete (*pi);
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::make_bin
// Access: Public, Static
// Description: Factory constructor for passing to the CullBinManager.
////////////////////////////////////////////////////////////////////
CullBin *CullBinHierarchicalZBuffer::
make_bin(const string &name, GraphicsStateGuardianBase *gsg) {
return new CullBinHierarchicalZBuffer(name, gsg);
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::make_next
// Access: Public, Virtual
// Description: Returns a newly-allocated CullBin object that
// contains a copy of just the subset of the data from
// this CullBin object that is worth keeping around
// for next frame.
//
// If a particular CullBin object has no data worth
// preserving till next frame, it is acceptable to
// return NULL (which is the default behavior of this
// method).
////////////////////////////////////////////////////////////////////
PT(CullBin) CullBinHierarchicalZBuffer::
make_next() const {
return (CullBin *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::add_object
// Access: Public, Virtual
// Description: Adds a geom, along with its associated state, to
// the bin for rendering.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::
add_object(CullableObject *object) {
// Determine the world-space bounding sphere for the object.
CPT(BoundingVolume) volume = object->_geom->get_bounds();
if (volume->is_empty()) {
return;
}
PT(BoundingSphere) sphere;
if (volume->is_exact_type(BoundingSphere::get_class_type())) {
sphere = DCAST(BoundingSphere, volume->make_copy());
} else {
const GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, volume);
PT(BoundingSphere) sphere = new BoundingSphere;
sphere->around(&gbv, &gbv + 1);
}
object->_already_drawn = false;
sphere->xform(object->_net_transform->get_mat());
_root.initial_assign(ObjectData(object, sphere));
_object_pointers.push_back(object);
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::finish_cull
// Access: Public
// Description: Called after all the geoms have been added, this
// indicates that the cull process is finished for this
// frame and gives the bins a chance to do any
// post-processing (like sorting) before moving on to
// draw.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::
finish_cull() {
PStatTimer timer(_cull_this_pcollector);
// Now we have a loose list of objects that are to be rendered.
// We'd rather have them in an octree, which has much better
// grouping properties for the purpose of this algorithm.
// For now, we'll just build an octree here at runtime, a new one
// fresh for each frame. Maybe it won't be *too* bad. But later,
// we can optimize this to take advantage of temporal coherence by
// starting from the previous frame's octree.
_root.make_initial_bounds();
_root.group_objects();
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::draw
// Access: Public
// Description: Draws all the geoms in the bin, in the appropriate
// order.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::
draw() {
PStatTimer timer(_draw_this_pcollector);
_root.draw(*this);
while (!_pending_nodes.empty()) {
PendingNode &pending = _pending_nodes.front();
bool is_occluded;
if (!pending._query->is_answer_ready()) {
// The answer isn't ready yet. We have to wait.
PStatTimer timer(_wait_occlusion_pcollector);
is_occluded = (pending._query->get_num_fragments() == 0);
} else {
// The answer is ready right now. There will be no waiting.
is_occluded = (pending._query->get_num_fragments() == 0);
}
if (!is_occluded) {
// The octree cell is at least partially visible. Draw it, and
// continue recursion.
pending._octree_node->draw(*this);
} else {
pending._octree_node->draw_wireframe(*this);
}
_pending_nodes.pop_front();
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CullBinHierarchicalZBuffer::OctreeNode::
OctreeNode() {
for (int i = 0; i < 8; ++i) {
_corners[i] = (OctreeNode *)NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CullBinHierarchicalZBuffer::OctreeNode::
OctreeNode(float mid_x, float mid_y, float mid_z, float half_side) :
_mid(mid_x, mid_y, mid_z),
_half_side(half_side)
{
for (int i = 0; i < 8; ++i) {
_corners[i] = (OctreeNode *)NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CullBinHierarchicalZBuffer::OctreeNode::
~OctreeNode() {
for (int i = 0; i < 8; ++i) {
if (_corners[i] != (OctreeNode *)NULL) {
delete _corners[i];
}
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::make_initial_bounds
// Access: Public
// Description: Determines the minmax bounding volume of the root
// OctreeNode, based on the objects it contains.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::OctreeNode::
make_initial_bounds() {
if (_objects.empty()) {
return;
}
LPoint3f scene_min = _objects[0]._bounds->get_center();
LPoint3f scene_max = _objects[0]._bounds->get_center();
Objects::const_iterator oi;
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
LPoint3f object_min = (*oi)._bounds->get_min();
LPoint3f object_max = (*oi)._bounds->get_max();
scene_min[0] = min(scene_min[0], object_min[0]);
scene_min[1] = min(scene_min[1], object_min[1]);
scene_min[2] = min(scene_min[2], object_min[2]);
scene_max[0] = max(scene_max[0], object_max[0]);
scene_max[1] = max(scene_max[1], object_max[1]);
scene_max[2] = max(scene_max[2], object_max[2]);
}
float side = max(max(scene_max[0] - scene_min[0],
scene_max[1] - scene_min[1]),
scene_max[2] - scene_min[2]);
_mid.set((scene_min[0] + scene_max[0]) * 0.5f,
(scene_min[1] + scene_max[1]) * 0.5f,
(scene_min[2] + scene_max[2]) * 0.5f);
_half_side = side * 0.5f;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::group_objects
// Access: Public
// Description: Recursively groups the objects assigned to this node
// into smaller octree nodes, as appropriate.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::OctreeNode::
group_objects() {
//cerr << "group_objects, " << _objects.size() << " objects.\n";
if ((int)_objects.size() <= max_objects_per_octree_node) {
// No need to do any more subdividing.
//cerr << " small enough.\n";
return;
}
// Assign all objects to one or more corners.
Objects old_objects;
old_objects.swap(_objects);
Objects::const_iterator oi;
for (oi = old_objects.begin(); oi != old_objects.end(); ++oi) {
//cerr << " object " << (oi - old_objects.begin()) << "\n";
const ObjectData &object_data = (*oi);
const LPoint3f &c = object_data._bounds->get_center();
float r = object_data._bounds->get_radius();
if (c[0] + r <= _mid[0]) {
// -X
if (c[1] + r <= _mid[1]) {
// -X, -Y
if (c[2] + r <= _mid[2]) {
// -X, -Y, -Z
assign_to_corner(0, object_data);
} else if (c[2] - r >= _mid[2]) {
// -X, -Y, +Z
assign_to_corner(OC_z, object_data);
} else {
// -X, -Y, 0
reassign(object_data);
}
} else if (c[1] - r >= _mid[1]) {
// -X, +Y
if (c[2] + r <= _mid[2]) {
// -X, +Y, -Z
assign_to_corner(OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// -X, +Y, +Z
assign_to_corner(OC_y | OC_z, object_data);
} else {
// -X, +Y, 0
reassign(object_data);
}
} else {
// -X, 0
reassign(object_data);
}
} else if (c[0] - r >= _mid[0]) {
// +X
if (c[1] + r <= _mid[1]) {
// +X, -Y
if (c[2] + r <= _mid[2]) {
// +X, -Y, -Z
assign_to_corner(OC_x, object_data);
} else if (c[2] - r >= _mid[2]) {
// +X, -Y, +Z
assign_to_corner(OC_x | OC_z, object_data);
} else {
// +X, -Y, 0
reassign(object_data);
}
} else if (c[1] - r >= _mid[1]) {
// +X, +Y
if (c[2] + r <= _mid[2]) {
// +X, +Y, -Z
assign_to_corner(OC_x | OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// +X, +Y, +Z
assign_to_corner(OC_x | OC_y | OC_z, object_data);
} else {
// +X, +Y, 0
reassign(object_data);
}
} else {
// +X, 0
reassign(object_data);
}
} else {
// 0
reassign(object_data);
}
}
for (int i = 0; i < 8; ++i) {
if (_corners[i] != (OctreeNode *)NULL) {
_corners[i]->group_objects();
}
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::occlusion_test
// Access: Public
// Description: Tests the octree node for visibility by rendering the
// octree cube, invisibly, with a query. Returns the
// occlusion query object representing this test.
////////////////////////////////////////////////////////////////////
PT(OcclusionQueryContext) CullBinHierarchicalZBuffer::OctreeNode::
occlusion_test(GraphicsStateGuardianBase *gsg) {
// Draw the bounding volume for visualization. This is
// complicated because we're doing this at such a low level, here
// in the middle of the draw task--we've already completed the
// cull traversal, so we can't just create a CullableObject or do
// anything else that requires a pointer to a CullTraverser.
// Instead, we have to do the relevant code by hand.
CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale
(_mid, LVecBase3f(0.0f, 0.0f, 0.0f),
LVecBase3f(_half_side, _half_side, _half_side));
CPT(TransformState) world_transform = gsg->get_scene()->get_world_transform();
CPT(TransformState) modelview_transform = world_transform->compose(net_transform);
CPT(RenderState) state = get_octree_solid_test_state();
PT(GeomMunger) munger = gsg->get_geom_munger(state);
CPT(Geom) viz = get_octree_solid_test();
CPT(GeomVertexData) munged_data = viz->get_vertex_data();
munger->munge_geom(viz, munged_data);
gsg->set_state_and_transform(state, modelview_transform);
gsg->begin_occlusion_query();
viz->draw(gsg, munger, munged_data);
return gsg->end_occlusion_query();
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::draw
// Access: Public
// Description: Draws all of the objects in this node, and
// recursively performs occlusion tests on all of the
// nested nodes.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::OctreeNode::
draw(CullBinHierarchicalZBuffer &bin) {
if (!_objects.empty()) {
// Now draw the objects within the octree node.
Objects::const_iterator oi;
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
CullableObject *object = (*oi)._object;
if (object->_already_drawn) {
//cerr << "skipping object.\n";
} else {
//cerr << "drawing object.\n";
CullHandler::draw(object, bin._gsg);
object->_already_drawn = true;
}
}
}
for (int i = 0; i < 8; ++i) {
if (_corners[i] != (OctreeNode *)NULL) {
PendingNode pending;
pending._octree_node = _corners[i];
pending._query = _corners[i]->occlusion_test(bin._gsg);
bin._pending_nodes.push_back(pending);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::draw_wireframe
// Access: Public
// Description: Draws a wireframe representation of the octree cube,
// for debugging and visualization purposes.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::OctreeNode::
draw_wireframe(CullBinHierarchicalZBuffer &bin) {
// As above, this is complicated because we're doing this at such a
// low level.
CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale
(_mid, LVecBase3f(0.0f, 0.0f, 0.0f),
LVecBase3f(_half_side, _half_side, _half_side));
CPT(TransformState) world_transform = bin._gsg->get_scene()->get_world_transform();
CPT(TransformState) modelview_transform = world_transform->compose(net_transform);
CPT(RenderState) state = RenderState::make_empty();
PT(GeomMunger) munger = bin._gsg->get_geom_munger(state);
CPT(Geom) viz = get_octree_wireframe_viz();
CPT(GeomVertexData) munged_data = viz->get_vertex_data();
munger->munge_geom(viz, munged_data);
bin._gsg->set_state_and_transform(state, modelview_transform);
viz->draw(bin._gsg, munger, munged_data);
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::get_octree_solid_test
// Access: Private, Static
// Description: Returns a Geom that may be used to render the solid
// faces of octree cube, presumably invisibly. This
// returns a cube over the range (-1, -1, -1) - (1, 1,
// 1).
////////////////////////////////////////////////////////////////////
CPT(Geom) CullBinHierarchicalZBuffer::
get_octree_solid_test() {
if (_octree_solid_test == (Geom *)NULL) {
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3();
PT(GeomVertexData) vdata =
new GeomVertexData("octree", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.add_data3f(-1.0f, -1.0f, -1.0f);
vertex.add_data3f(1.0f, -1.0f, -1.0f);
vertex.add_data3f(-1.0f, -1.0f, 1.0f);
vertex.add_data3f(1.0f, -1.0f, 1.0f);
vertex.add_data3f(-1.0f, 1.0f, -1.0f);
vertex.add_data3f(1.0f, 1.0f, -1.0f);
vertex.add_data3f(-1.0f, 1.0f, 1.0f);
vertex.add_data3f(1.0f, 1.0f, 1.0f);
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
tris->add_vertices(2, 0, 3); tris->close_primitive();
tris->add_vertices(0, 1, 3); tris->close_primitive();
tris->add_vertices(3, 1, 7); tris->close_primitive();
tris->add_vertices(1, 5, 7); tris->close_primitive();
tris->add_vertices(7, 5, 6); tris->close_primitive();
tris->add_vertices(5, 4, 6); tris->close_primitive();
tris->add_vertices(6, 4, 2); tris->close_primitive();
tris->add_vertices(4, 0, 2); tris->close_primitive();
tris->add_vertices(6, 2, 7); tris->close_primitive();
tris->add_vertices(2, 3, 7); tris->close_primitive();
tris->add_vertices(0, 4, 1); tris->close_primitive();
tris->add_vertices(4, 5, 1); tris->close_primitive();
_octree_solid_test = new Geom(vdata);
_octree_solid_test->add_primitive(tris);
}
return _octree_solid_test;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::get_octree_wireframe_viz
// Access: Private, Static
// Description: Returns a Geom that may be used to render an
// OctreeNode in wireframe. This actually draws a
// wireframe cube in the range (-1, -1, -1) - (1, 1, 1).
////////////////////////////////////////////////////////////////////
CPT(Geom) CullBinHierarchicalZBuffer::
get_octree_wireframe_viz() {
if (_octree_wireframe_viz == (Geom *)NULL) {
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3cp();
PT(GeomVertexData) vdata =
new GeomVertexData("octree", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.add_data3f(-1.0f, -1.0f, -1.0f);
vertex.add_data3f(1.0f, -1.0f, -1.0f);
vertex.add_data3f(-1.0f, -1.0f, 1.0f);
vertex.add_data3f(1.0f, -1.0f, 1.0f);
vertex.add_data3f(-1.0f, 1.0f, -1.0f);
vertex.add_data3f(1.0f, 1.0f, -1.0f);
vertex.add_data3f(-1.0f, 1.0f, 1.0f);
vertex.add_data3f(1.0f, 1.0f, 1.0f);
CPT(GeomVertexData) cvdata = vdata->set_color(Colorf(1.0f, 0.5f, 0.0f, 1.0f));
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
lines->add_vertices(0, 1); lines->close_primitive();
lines->add_vertices(1, 3); lines->close_primitive();
lines->add_vertices(3, 2); lines->close_primitive();
lines->add_vertices(2, 0); lines->close_primitive();
lines->add_vertices(0, 4); lines->close_primitive();
lines->add_vertices(4, 6); lines->close_primitive();
lines->add_vertices(6, 7); lines->close_primitive();
lines->add_vertices(7, 5); lines->close_primitive();
lines->add_vertices(5, 4); lines->close_primitive();
lines->add_vertices(1, 5); lines->close_primitive();
lines->add_vertices(3, 7); lines->close_primitive();
lines->add_vertices(2, 6); lines->close_primitive();
_octree_wireframe_viz = new Geom(cvdata);
_octree_wireframe_viz->add_primitive(lines);
}
return _octree_wireframe_viz;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::get_octree_solid_test_state
// Access: Private, Static
// Description: Returns the RenderState appropriate to rendering the
// octree test invisibly.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullBinHierarchicalZBuffer::
get_octree_solid_test_state() {
if (_octree_solid_test_state == (RenderState *)NULL) {
_octree_solid_test_state = RenderState::make
(DepthWriteAttrib::make(DepthWriteAttrib::M_off),
DepthTestAttrib::make(DepthTestAttrib::M_less),
ColorWriteAttrib::make(ColorWriteAttrib::C_off));
}
return _octree_solid_test_state;
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::multi_assign
// Access: Public
// Description: The object intersects a center plane, but is too
// small to justify keeping within this big node.
// Duplicate it into the sub-nodes.
////////////////////////////////////////////////////////////////////
void CullBinHierarchicalZBuffer::OctreeNode::
multi_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
const LPoint3f &c = object_data._bounds->get_center();
float r = object_data._bounds->get_radius();
//cerr << "multi_assigning " << c << " vs. " << _mid << "\n";
if (c[0] + r <= _mid[0]) {
// -X
if (c[1] + r <= _mid[1]) {
// -X, -Y
if (c[2] + r <= _mid[2]) {
// -X, -Y, -Z
nassertv(false);
} else if (c[2] - r >= _mid[2]) {
// -X, -Y, +Z
nassertv(false);
} else {
// -X, -Y, 0
assign_to_corner(0, object_data);
assign_to_corner(OC_z, object_data);
}
} else if (c[1] - r >= _mid[1]) {
// -X, +Y
if (c[2] + r <= _mid[2]) {
// -X, +Y, -Z
nassertv(false);
} else if (c[2] - r >= _mid[2]) {
// -X, +Y, +Z
nassertv(false);
} else {
// -X, +Y, 0
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_y | OC_z, object_data);
}
} else {
// -X, 0
if (c[2] + r <= _mid[2]) {
// -X, 0, -Z
assign_to_corner(0, object_data);
assign_to_corner(OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// -X, 0, +Z
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_y | OC_z, object_data);
} else {
// -X, 0, 0
assign_to_corner(0, object_data);
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_y | OC_z, object_data);
}
}
} else if (c[0] - r >= _mid[0]) {
// +X
if (c[1] + r <= _mid[1]) {
// +X, -Y
if (c[2] + r <= _mid[2]) {
// +X, -Y, -Z
nassertv(false);
} else if (c[2] - r >= _mid[2]) {
// +X, -Y, +Z
nassertv(false);
} else {
// +X, -Y, 0
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_z, object_data);
}
} else if (c[1] - r >= _mid[1]) {
// +X, +Y
if (c[2] + r <= _mid[2]) {
// +X, +Y, -Z
nassertv(false);
} else if (c[2] - r >= _mid[2]) {
// +X, +Y, +Z
nassertv(false);
} else {
// +X, +Y, 0
assign_to_corner(OC_x | OC_y, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
}
} else {
// +X, 0
if (c[2] + r <= _mid[2]) {
// +X, 0, -Z
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// +X, 0, +Z
assign_to_corner(OC_x | OC_z, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
} else {
// +X, 0, 0
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_z, object_data);
assign_to_corner(OC_x | OC_y, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
}
}
} else {
// 0
if (c[1] + r <= _mid[1]) {
// 0, -Y
if (c[2] + r <= _mid[2]) {
// 0, -Y, -Z
assign_to_corner(0, object_data);
assign_to_corner(OC_x, object_data);
} else if (c[2] - r >= _mid[2]) {
// 0, -Y, +Z
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_x | OC_z, object_data);
} else {
// 0, -Y, 0
assign_to_corner(0, object_data);
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_z, object_data);
}
} else if (c[1] - r >= _mid[1]) {
// 0, +Y
if (c[2] + r <= _mid[2]) {
// 0, +Y, -Z
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_x | OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// 0, +Y, +Z
assign_to_corner(OC_y | OC_z, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
} else {
// 0, +Y, 0
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_y | OC_z, object_data);
assign_to_corner(OC_x | OC_y, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
}
} else {
// 0, 0
if (c[2] + r <= _mid[2]) {
// 0, 0, -Z
assign_to_corner(0, object_data);
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_y, object_data);
} else if (c[2] - r >= _mid[2]) {
// 0, 0, +Z
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_y | OC_z, object_data);
assign_to_corner(OC_x | OC_z, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
} else {
// 0, 0, 0
assign_to_corner(0, object_data);
assign_to_corner(OC_z, object_data);
assign_to_corner(OC_y, object_data);
assign_to_corner(OC_y | OC_z, object_data);
assign_to_corner(OC_x, object_data);
assign_to_corner(OC_x | OC_z, object_data);
assign_to_corner(OC_x | OC_y, object_data);
assign_to_corner(OC_x | OC_y | OC_z, object_data);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: CullBinHierarchicalZBuffer::OctreeNode::make_corner
// Access: Private
// Description: Makes a new octree node for the indicated corner.
////////////////////////////////////////////////////////////////////
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
make_corner(int index) {
//cerr << "making corner " << hex << index << dec << "\n";
nassertv(_corners[index] == NULL);
OctreeNode *node = NULL;
double q = _half_side * 0.5f;
switch (index) {
case 0:
// -X, -Y, -Z
node = new OctreeNode(_mid[0] - q, _mid[1] - q, _mid[2] - q, q);
break;
case OC_x:
// +X, -Y, -Z
node = new OctreeNode(_mid[0] + q, _mid[1] - q, _mid[2] - q, q);
break;
case OC_y:
// -X, +Y, -Z
node = new OctreeNode(_mid[0] - q, _mid[1] + q, _mid[2] - q, q);
break;
case OC_x | OC_y:
// +X, +Y, -Z
node = new OctreeNode(_mid[0] + q, _mid[1] + q, _mid[2] - q, q);
break;
case OC_z:
// -X, -Y, +Z
node = new OctreeNode(_mid[0] - q, _mid[1] - q, _mid[2] + q, q);
break;
case OC_x | OC_z:
// +X, -Y, +Z
node = new OctreeNode(_mid[0] + q, _mid[1] - q, _mid[2] + q, q);
break;
case OC_y | OC_z:
// -X, +Y, +Z
node = new OctreeNode(_mid[0] - q, _mid[1] + q, _mid[2] + q, q);
break;
case OC_x | OC_y | OC_z:
// +X, +Y, +Z
node = new OctreeNode(_mid[0] + q, _mid[1] + q, _mid[2] + q, q);
break;
}
nassertv(node != (OctreeNode *)NULL);
_corners[index] = node;
}

View File

@ -0,0 +1,163 @@
// Filename: cullBinHierarchicalZBuffer.h
// Created by: drose (24Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef CULLBINHIERARCHICALZBUFFER_H
#define CULLBINHIERARCHICALZBUFFER_H
#include "pandabase.h"
#include "cullBin.h"
#include "geom.h"
#include "transformState.h"
#include "renderState.h"
#include "pointerTo.h"
#include "boundingSphere.h"
#include "config_cull.h"
#include "occlusionQueryContext.h"
#include "pdeque.h"
#include "pStatCollector.h"
////////////////////////////////////////////////////////////////////
// Class : CullBinHierarchicalZBuffer
// Description : This cull bin uses a hierarchical Z-buffer algorithm
// to attempt to further eliminate geometry that is
// obscured behind walls, etc. It imposes some
// significant overhead over most of the other kinds of
// CullBins, and requires additional support from the
// graphics card, so it is most appropriate for scenes
// in which there might be a large amount of geometry,
// within the viewing frustum, but obscured behind large
// objects or walls.
//
// This code is still experimental. Use with caution.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA CullBinHierarchicalZBuffer : public CullBin {
public:
INLINE CullBinHierarchicalZBuffer(const string &name, GraphicsStateGuardianBase *gsg);
virtual ~CullBinHierarchicalZBuffer();
static CullBin *make_bin(const string &name, GraphicsStateGuardianBase *gsg);
virtual PT(CullBin) make_next() const;
virtual void add_object(CullableObject *object);
virtual void finish_cull();
virtual void draw();
private:
void draw_next();
static CPT(Geom) get_octree_solid_test();
static CPT(Geom) get_octree_wireframe_viz();
static CPT(RenderState) get_octree_solid_test_state();
// We keep the original list of CullableObjects here in the bin
// class, so we can delete them on destruction. This allows us to
// duplicate pointers between different OctreeNodes.
typedef pvector<CullableObject *> ObjectPointers;
ObjectPointers _object_pointers;
class ObjectData {
public:
INLINE ObjectData(CullableObject *object, BoundingSphere *bounds);
INLINE ObjectData(const ObjectData &copy);
INLINE void operator = (const ObjectData &copy);
CullableObject *_object;
PT(BoundingSphere) _bounds;
};
typedef pvector<ObjectData> Objects;
enum OctreeCorners {
OC_x = 0x01,
OC_y = 0x02,
OC_z = 0x04,
};
class OctreeNode {
public:
OctreeNode();
OctreeNode(float mid_x, float mid_y, float mid_z, float half_side);
~OctreeNode();
void make_initial_bounds();
void group_objects();
PT(OcclusionQueryContext) occlusion_test(GraphicsStateGuardianBase *gsg);
void draw(CullBinHierarchicalZBuffer &bin);
void draw_wireframe(CullBinHierarchicalZBuffer &bin);
INLINE void initial_assign(const ObjectData &object_data);
private:
INLINE void reassign(const ObjectData &object_data);
INLINE void assign_to_corner(int index, const ObjectData &object_data);
void multi_assign(const ObjectData &object_data);
void make_corner(int index);
Objects _objects;
OctreeNode *_corners[8];
LPoint3f _mid;
float _half_side;
};
OctreeNode _root;
// During draw(), we maintain a list of OctreeNodes that have been
// tested and have yet to pass the occlusion query and be drawn (or
// fail and be omitted).
class PendingNode {
public:
OctreeNode *_octree_node;
PT(OcclusionQueryContext) _query;
};
typedef pdeque<PendingNode> PendingNodes;
PendingNodes _pending_nodes;
static PStatCollector _wait_occlusion_pcollector;
static PT(Geom) _octree_solid_test;
static PT(Geom) _octree_wireframe_viz;
static CPT(RenderState) _octree_solid_test_state;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
CullBin::init_type();
register_type(_type_handle, "CullBinHierarchicalZBuffer",
CullBin::get_class_type());
}
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;
friend class OctreeNode;
};
#include "cullBinHierarchicalZBuffer.I"
#endif

View File

@ -18,7 +18,6 @@
#include "cullBinStateSorted.h"
#include "graphicsStateGuardianBase.h"
#include "geometricBoundingVolume.h"
#include "cullableObject.h"
#include "cullHandler.h"
#include "pStatTimer.h"

View File

@ -1,4 +1,5 @@
#include "cullBinFrontToBack.cxx"
#include "cullBinHierarchicalZBuffer.cxx"
#include "cullBinStateSorted.cxx"
#include "cullBinUnsorted.cxx"
#include "drawCullHandler.cxx"

View File

@ -593,17 +593,6 @@ get_global_gsg() {
return _global_gsg;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_scene
// Access: Public
// Description: Returns the SceneSetup object.
////////////////////////////////////////////////////////////////////
INLINE SceneSetup *GraphicsStateGuardian::
get_scene() const {
return _scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::reset_if_new
// Access: Public

View File

@ -35,6 +35,7 @@
#include "geomLinestrips.h"
#include "colorWriteAttrib.h"
#include "shader.h"
#include "pnotify.h"
#include <algorithm>
#include <limits.h>
@ -137,6 +138,8 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_max_vertex_transforms = 0;
_max_vertex_transform_indices = 0;
_supports_occlusion_query = false;
// Initially, we set this to false; a GSG that knows it has this
// property should set it to true.
_copy_texture_inverted = false;
@ -362,6 +365,16 @@ set_scene(SceneSetup *scene_setup) {
return prepare_lens();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_scene
// Access: Public, Virtual
// Description: Returns the current SceneSetup object.
////////////////////////////////////////////////////////////////////
SceneSetup *GraphicsStateGuardian::
get_scene() const {
return _scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_prepared_objects
// Access: Public, Virtual
@ -511,6 +524,58 @@ void GraphicsStateGuardian::
release_index_buffer(IndexBufferContext *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_occlusion_query
// Access: Public, Virtual
// Description: Returns true if this GSG supports an occlusion query.
// If this is true, then begin_occlusion_query() and
// end_occlusion_query() may be called to bracket a
// sequence of draw_triangles() (or whatever) calls to
// measure pixels that pass the depth test.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
get_supports_occlusion_query() const {
return _supports_occlusion_query;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::begin_occlusion_query
// Access: Public, Virtual
// Description: Begins a new occlusion query. After this call, you
// may call begin_draw_primitives() and
// draw_triangles()/draw_whatever() repeatedly.
// Eventually, you should call end_occlusion_query()
// before the end of the frame; that will return a new
// OcclusionQueryContext object that will tell you how
// many pixels represented by the bracketed geometry
// passed the depth test.
//
// It is not valid to call begin_occlusion_query()
// between another begin_occlusion_query()
// .. end_occlusion_query() sequence.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
begin_occlusion_query() {
nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::end_occlusion_query
// Access: Public, Virtual
// Description: Ends a previous call to begin_occlusion_query().
// This call returns the OcclusionQueryContext object
// that will (eventually) report the number of pixels
// that passed the depth test between the call to
// begin_occlusion_query() and end_occlusion_query().
////////////////////////////////////////////////////////////////////
PT(OcclusionQueryContext) GraphicsStateGuardian::
end_occlusion_query() {
nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
PT(OcclusionQueryContext) result = _current_occlusion_query;
_current_occlusion_query = NULL;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_geom_munger
// Access: Public

View File

@ -45,6 +45,7 @@
#include "shaderContext.h"
#include "bitMask.h"
#include "texture.h"
#include "occlusionQueryContext.h"
class DrawableRegion;
class GraphicsEngine;
@ -132,7 +133,7 @@ PUBLISHED:
public:
bool set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
virtual SceneSetup *get_scene() const;
virtual PreparedGraphicsObjects *get_prepared_objects();
@ -152,6 +153,10 @@ public:
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual bool get_supports_occlusion_query() const;
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
PT(GeomMunger) get_geom_munger(const RenderState *state);
virtual PT(GeomMunger) make_geom_munger(const RenderState *state);
@ -338,6 +343,9 @@ protected:
int _max_vertex_transforms;
int _max_vertex_transform_indices;
bool _supports_occlusion_query;
PT(OcclusionQueryContext) _current_occlusion_query;
bool _copy_texture_inverted;
bool _supports_multisample;
bool _supports_generate_mipmap;

View File

@ -13,36 +13,39 @@
#define INSTALL_HEADERS \
panda_glext.h \
glGeomContext_src.I \
glGeomContext_src.cxx \
glGeomContext_src.h \
glGeomMunger_src.I \
glGeomMunger_src.cxx \
glGeomMunger_src.h \
glGraphicsStateGuardian_src.I \
glGraphicsStateGuardian_src.cxx \
glGraphicsStateGuardian_src.h \
glImmediateModeSender_src.I \
glImmediateModeSender_src.cxx \
glImmediateModeSender_src.h \
glIndexBufferContext_src.I \
glIndexBufferContext_src.cxx \
glIndexBufferContext_src.h \
glOcclusionQueryContext_src.I \
glOcclusionQueryContext_src.cxx \
glOcclusionQueryContext_src.h \
glShaderContext_src.I \
glShaderContext_src.cxx \
glShaderContext_src.h \
glTextureContext_src.I \
glTextureContext_src.cxx \
glTextureContext_src.h \
glVertexBufferContext_src.I \
glVertexBufferContext_src.cxx \
glVertexBufferContext_src.h \
glmisc_src.cxx \
glmisc_src.h \
glstuff_src.cxx \
glstuff_src.h \
glstuff_undef_src.h \
glVertexBufferContext_src.cxx \
glVertexBufferContext_src.I \
glVertexBufferContext_src.h \
glImmediateModeSender_src.cxx \
glImmediateModeSender_src.I \
glImmediateModeSender_src.h \
glIndexBufferContext_src.cxx \
glIndexBufferContext_src.I \
glIndexBufferContext_src.h \
glGeomContext_src.cxx \
glGeomContext_src.I \
glGeomContext_src.h \
glGeomMunger_src.cxx \
glGeomMunger_src.I \
glGeomMunger_src.h \
glGraphicsStateGuardian_src.cxx \
glGraphicsStateGuardian_src.I \
glGraphicsStateGuardian_src.h \
glTextureContext_src.cxx \
glTextureContext_src.I \
glTextureContext_src.h \
glShaderContext_src.cxx \
glShaderContext_src.h \
glShaderContext_src.I \
panda_glext.h
#define SOURCES \
$[INSTALL_HEADERS] glpure.cxx

View File

@ -721,11 +721,52 @@ reset() {
}
_glDrawBuffers = NULL;
if (has_extension("GL_ARB_draw_buffers")) {
_glDrawBuffers = (PFNGLDRAWBUFFERSARBPROC)
if (is_at_least_version(2, 0)) {
_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawBuffers");
} else if (has_extension("GL_ARB_draw_buffers")) {
_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawBuffersARB");
}
_supports_occlusion_query = false;
if (CLP(support_occlusion_query)) {
if (is_at_least_version(1, 5)) {
_supports_occlusion_query = true;
_glGenQueries = (PFNGLGENQUERIESPROC)
get_extension_func(GLPREFIX_QUOTED, "GenQueries");
_glBeginQuery = (PFNGLBEGINQUERYPROC)
get_extension_func(GLPREFIX_QUOTED, "BeginQuery");
_glEndQuery = (PFNGLENDQUERYPROC)
get_extension_func(GLPREFIX_QUOTED, "EndQuery");
_glDeleteQueries = (PFNGLDELETEQUERIESPROC)
get_extension_func(GLPREFIX_QUOTED, "DeleteQueries");
_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)
get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuiv");
} else if (has_extension("GL_ARB_occlusion_query")) {
_supports_occlusion_query = true;
_glGenQueries = (PFNGLGENQUERIESPROC)
get_extension_func(GLPREFIX_QUOTED, "GenQueriesARB");
_glBeginQuery = (PFNGLBEGINQUERYPROC)
get_extension_func(GLPREFIX_QUOTED, "BeginQueryARB");
_glEndQuery = (PFNGLENDQUERYPROC)
get_extension_func(GLPREFIX_QUOTED, "EndQueryARB");
_glDeleteQueries = (PFNGLDELETEQUERIESPROC)
get_extension_func(GLPREFIX_QUOTED, "DeleteQueriesARB");
_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)
get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuivARB");
}
}
if (_supports_occlusion_query &&
(_glGenQueries == NULL || _glBeginQuery == NULL ||
_glEndQuery == NULL || _glDeleteQueries == NULL ||
_glGetQueryObjectuiv == NULL)) {
GLCAT.warning()
<< "Occlusion queries advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
_supports_occlusion_query = false;
}
_glBlendEquation = NULL;
bool supports_blend_equation = false;
if (is_at_least_version(1, 2)) {
@ -1265,12 +1306,27 @@ end_frame() {
++ddli) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "releasing index " << (*ddli) << "\n";
<< "releasing display list index " << (*ddli) << "\n";
}
GLP(DeleteLists)((*ddli), 1);
}
_deleted_display_lists.clear();
}
// And deleted occlusion queries, too.
if (!_deleted_queries.empty()) {
DeletedDisplayLists::iterator ddli;
for (ddli = _deleted_queries.begin();
ddli != _deleted_queries.end();
++ddli) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "releasing query index " << (*ddli) << "\n";
}
_glDeleteQueries(1, &(*ddli));
}
_deleted_queries.clear();
}
}
{
@ -2845,6 +2901,53 @@ setup_primitive(const GeomPrimitive *data) {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::begin_occlusion_query
// Access: Public, Virtual
// Description: Begins a new occlusion query. After this call, you
// may call begin_draw_primitives() and
// draw_triangles()/draw_whatever() repeatedly.
// Eventually, you should call end_occlusion_query()
// before the end of the frame; that will return a new
// OcclusionQueryContext object that will tell you how
// many pixels represented by the bracketed geometry
// passed the depth test.
//
// It is not valid to call begin_occlusion_query()
// between another begin_occlusion_query()
// .. end_occlusion_query() sequence.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
begin_occlusion_query() {
nassertv(_supports_occlusion_query);
nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
PT(CLP(OcclusionQueryContext)) query = new CLP(OcclusionQueryContext)(this);
_glGenQueries(1, &query->_index);
_glBeginQuery(GL_SAMPLES_PASSED, query->_index);
_current_occlusion_query = query;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::end_occlusion_query
// Access: Public, Virtual
// Description: Ends a previous call to begin_occlusion_query().
// This call returns the OcclusionQueryContext object
// that will (eventually) report the number of pixels
// that passed the depth test between the call to
// begin_occlusion_query() and end_occlusion_query().
////////////////////////////////////////////////////////////////////
PT(OcclusionQueryContext) CLP(GraphicsStateGuardian)::
end_occlusion_query() {
nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
PT(OcclusionQueryContext) result = _current_occlusion_query;
_current_occlusion_query = NULL;
_glEndQuery(GL_SAMPLES_PASSED);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::make_geom_munger
// Access: Public, Virtual

View File

@ -62,7 +62,7 @@ typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
@ -82,8 +82,6 @@ class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian {
public:
CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties);
virtual ~CLP(GraphicsStateGuardian)();
friend class CLP(ShaderContext);
friend class CLP(GraphicsBuffer);
virtual void reset();
@ -131,6 +129,9 @@ public:
virtual void release_index_buffer(IndexBufferContext *ibc);
const unsigned char *setup_primitive(const GeomPrimitive *data);
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
virtual PT(GeomMunger) make_geom_munger(const RenderState *state);
virtual void framebuffer_copy_to_texture
@ -424,7 +425,13 @@ public:
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC _glGetFramebufferAttachmentParameteriv;
PFNGLGENERATEMIPMAPEXTPROC _glGenerateMipmap;
PFNGLDRAWBUFFERSARBPROC _glDrawBuffers;
PFNGLDRAWBUFFERSPROC _glDrawBuffers;
PFNGLGENQUERIESPROC _glGenQueries;
PFNGLBEGINQUERYPROC _glBeginQuery;
PFNGLENDQUERYPROC _glEndQuery;
PFNGLDELETEQUERIESPROC _glDeleteQueries;
PFNGLGETQUERYOBJECTUIVPROC _glGetQueryObjectuiv;
GLenum _edge_clamp;
GLenum _border_clamp;
@ -436,6 +443,7 @@ public:
Mutex _lock;
typedef pvector<GLuint> DeletedDisplayLists;
DeletedDisplayLists _deleted_display_lists;
DeletedDisplayLists _deleted_queries;
static PStatCollector _load_display_list_pcollector;
static PStatCollector _primitive_batches_display_list_pcollector;
@ -461,6 +469,10 @@ public:
private:
static TypeHandle _type_handle;
friend class CLP(ShaderContext);
friend class CLP(GraphicsBuffer);
friend class CLP(OcclusionQueryContext);
};
#include "glGraphicsStateGuardian_src.I"

View File

@ -62,6 +62,13 @@ ConfigVariableBool CLP(color_mask)
"is broken (some are). This will force the use of a (presumably) "
"more expensive blending operation instead."));
ConfigVariableBool CLP(support_occlusion_query)
("gl-support-occlusion-query", true,
PRC_DESC("Configure this true to enable the use of the occlusion_query "
"extension if the GL claims to support it, or false not to "
"use it even if it appears to be available. (On some OpenGL "
"drivers, enabling this mode can force software rendering.)"));
ConfigVariableBool CLP(compile_and_execute)
("gl-compile-and-execute", false,
PRC_DESC("Configure this true if you know your GL's implementation of "
@ -73,13 +80,14 @@ ConfigVariableBool CLP(compile_and_execute)
"rendered at the same time it is being compiled."));
void CLP(init_classes)() {
CLP(GraphicsStateGuardian)::init_type();
CLP(TextureContext)::init_type();
CLP(GeomContext)::init_type();
CLP(VertexBufferContext)::init_type();
CLP(IndexBufferContext)::init_type();
CLP(GeomMunger)::init_type();
CLP(GraphicsStateGuardian)::init_type();
CLP(IndexBufferContext)::init_type();
CLP(OcclusionQueryContext)::init_type();
CLP(ShaderContext)::init_type();
CLP(TextureContext)::init_type();
CLP(VertexBufferContext)::init_type();
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->add_system(GLSYSTEM_NAME);

View File

@ -28,6 +28,7 @@ extern ConfigVariableBool CLP(ignore_filters);
extern ConfigVariableBool CLP(ignore_mipmaps);
extern ConfigVariableBool CLP(force_mipmaps);
extern ConfigVariableBool CLP(color_mask);
extern ConfigVariableBool CLP(support_occlusion_query);
extern ConfigVariableBool CLP(compile_and_execute);
extern EXPCL_GL void CLP(init_classes)();

View File

@ -25,6 +25,7 @@
#include "glTextureContext_src.cxx"
#include "glVertexBufferContext_src.cxx"
#include "glIndexBufferContext_src.cxx"
#include "glOcclusionQueryContext_src.cxx"
#include "glGeomContext_src.cxx"
#include "glGeomMunger_src.cxx"
#include "glShaderContext_src.cxx"

View File

@ -61,6 +61,7 @@
#include "glTextureContext_src.h"
#include "glVertexBufferContext_src.h"
#include "glIndexBufferContext_src.h"
#include "glOcclusionQueryContext_src.h"
#include "glGeomContext_src.h"
#include "glGeomMunger_src.h"
#include "glShaderContext_src.h"

View File

@ -41,10 +41,12 @@
internalName.I internalName.h \
material.I material.h materialPool.I materialPool.h \
matrixLens.I matrixLens.h \
occlusionQueryContext.I occlusionQueryContext.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
perspectiveLens.h \
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
queryContext.I queryContext.h \
savedContext.I savedContext.h \
shaderContext.h shaderContext.I \
shaderExpansion.h shaderExpansion.I \
@ -93,10 +95,13 @@
indexBufferContext.cxx \
material.cxx \
internalName.cxx \
materialPool.cxx matrixLens.cxx orthographicLens.cxx \
materialPool.cxx matrixLens.cxx \
occlusionQuery.cxx \
orthographicLens.cxx \
perspectiveLens.cxx \
preparedGraphicsObjects.cxx \
lens.cxx \
queryContext.cxx \
savedContext.cxx \
shaderContext.cxx \
shaderExpansion.cxx \
@ -146,10 +151,12 @@
internalName.I internalName.h \
material.I material.h \
materialPool.I materialPool.h matrixLens.I matrixLens.h \
occlusionQueryContext.I occlusionQueryContext.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
perspectiveLens.h \
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
queryContext.I queryContext.h \
savedContext.I savedContext.h \
shaderContext.h shaderContext.I \
shaderExpansion.h shaderExpansion.I \

View File

@ -33,10 +33,12 @@
#include "geomVertexData.h"
#include "geomVertexFormat.h"
#include "material.h"
#include "occlusionQueryContext.h"
#include "orthographicLens.h"
#include "matrixLens.h"
#include "perspectiveLens.h"
#include "lens.h"
#include "queryContext.h"
#include "sliderTable.h"
#include "texture.h"
#include "textureStage.h"
@ -263,10 +265,12 @@ ConfigureFn(config_gobj) {
VertexBufferContext::init_type();
IndexBufferContext::init_type();
Material::init_type();
OcclusionQueryContext::init_type();
OrthographicLens::init_type();
MatrixLens::init_type();
PerspectiveLens::init_type();
Lens::init_type();
QueryContext::init_type();
SliderTable::init_type();
Texture::init_type();
TextureStage::init_type();

View File

@ -1,4 +1,3 @@
#include "config_gobj.cxx"
#include "indexBufferContext.cxx"
#include "internalName.cxx"
@ -6,9 +5,11 @@
#include "material.cxx"
#include "materialPool.cxx"
#include "matrixLens.cxx"
#include "occlusionQueryContext.cxx"
#include "orthographicLens.cxx"
#include "perspectiveLens.cxx"
#include "preparedGraphicsObjects.cxx"
#include "queryContext.cxx"
#include "savedContext.cxx"
#include "sliderTable.cxx"
#include "texture.cxx"

View File

@ -0,0 +1,27 @@
// Filename: occlusionQueryContext.I
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: OcclusionQueryContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE OcclusionQueryContext::
OcclusionQueryContext() {
}

View File

@ -0,0 +1,36 @@
// Filename: occlusionQueryContext.cxx
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "occlusionQueryContext.h"
TypeHandle OcclusionQueryContext::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: OcclusionQueryContext::get_num_fragments
// Access: Public, Virtual
// Description: Returns the number of fragments (pixels) of the
// specified geometry that passed the depth test.
// If is_answer_ready() did not return true, this
// function may block before it returns.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
int OcclusionQueryContext::
get_num_fragments() const {
return 0;
}

View File

@ -0,0 +1,61 @@
// Filename: occlusionQueryContext.h
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef OCCLUSIONQUERYCONTEXT_H
#define OCCLUSIONQUERYCONTEXT_H
#include "pandabase.h"
#include "queryContext.h"
////////////////////////////////////////////////////////////////////
// Class : OcclusionQueryContext
// Description : Returned from a GSG in response to
// begin_occlusion_query() .. end_occlusion_query(),
// this records the number of fragments (pixels) that
// passed the depth test between the bracketing calls.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA OcclusionQueryContext : public QueryContext {
public:
INLINE OcclusionQueryContext();
virtual int get_num_fragments() const=0;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
QueryContext::init_type();
register_type(_type_handle, "OcclusionQueryContext",
QueryContext::get_class_type());
}
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;
friend class PreparedGraphicsObjects;
};
#include "occlusionQueryContext.I"
#endif

View File

@ -0,0 +1,27 @@
// Filename: queryContext.I
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: QueryContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE QueryContext::
QueryContext() {
}

View File

@ -0,0 +1,57 @@
// Filename: queryContext.cxx
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "queryContext.h"
TypeHandle QueryContext::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: QueryContext::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
QueryContext::
~QueryContext() {
}
////////////////////////////////////////////////////////////////////
// Function: QueryContext::is_answer_ready
// Access: Public, Virtual
// Description: Returns true if the query's answer is ready, false
// otherwise. If this returns false, the application
// must continue to poll until it returns true.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
bool QueryContext::
is_answer_ready() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: QueryContext::waiting_for_answer
// Access: Public, Virtual
// Description: Requests the graphics engine to expedite the pending
// answer--the application is now waiting until the
// answer is ready.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
void QueryContext::
waiting_for_answer() {
}

View File

@ -0,0 +1,71 @@
// Filename: queryContext.h
// Created by: drose (27Mar06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef QUERYCONTEXT_H
#define QUERYCONTEXT_H
#include "pandabase.h"
#include "typedReferenceCount.h"
class PreparedGraphicsObjects;
////////////////////////////////////////////////////////////////////
// Class : QueryContext
// Description : This is a base class for queries that might require a
// round-trip to the graphics engine. The idea is that
// when you ask the GSG to make a particular query, it
// returns a QueryContext, which does not necessarily
// have the answer right away (but it will eventually).
//
// Unlike SavedContext, QueryContext is
// reference-counted. It removes itself from the GSG
// when the last reference goes away. You're
// responsible for keeping the pointer to the
// QueryContext as long as you are interested in the
// answer.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA QueryContext : public TypedReferenceCount {
public:
INLINE QueryContext();
virtual ~QueryContext();
virtual bool is_answer_ready() const=0;
virtual void waiting_for_answer();
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
register_type(_type_handle, "QueryContext",
TypedReferenceCount::get_class_type());
}
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;
};
#include "queryContext.I"
#endif

View File

@ -32,6 +32,7 @@ class NodePath;
class VertexBufferContext;
class IndexBufferContext;
class OcclusionQueryContext;
class GeomContext;
class GeomNode;
class Geom;
@ -57,6 +58,7 @@ class GeomLinestrips;
class GeomPoints;
class GeomMunger;
class SceneSetup;
class PreparedGraphicsObjects;
class GraphicsOutput;
class Texture;
@ -118,11 +120,13 @@ class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount
PUBLISHED:
virtual bool get_supports_multisample() const=0;
virtual int get_supported_geom_rendering() const=0;
virtual bool get_supports_occlusion_query() const=0;
public:
// These are some general interface functions; they're defined here
// mainly to make it easy to call these from code in some directory
// that display depends on.
virtual SceneSetup *get_scene() const=0;
virtual PreparedGraphicsObjects *get_prepared_objects()=0;
virtual TextureContext *prepare_texture(Texture *tex)=0;
@ -140,6 +144,9 @@ public:
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data)=0;
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
virtual void begin_occlusion_query()=0;
virtual PT(OcclusionQueryContext) end_occlusion_query()=0;
virtual PT(GeomMunger) get_geom_munger(const RenderState *state)=0;
virtual void set_state_and_transform(const RenderState *state,

View File

@ -41,6 +41,7 @@ PUBLISHED:
C_red = 0x001,
C_green = 0x002,
C_blue = 0x004,
C_rgb = 0x007, // == C_red | C_green | C_blue
C_alpha = 0x008,
C_all = 0x00f,
};

View File

@ -338,23 +338,17 @@ parse_bin_type(const string &bin_type) {
} else if (cmp_nocase_uh(bin_type, "state_sorted") == 0) {
return BT_state_sorted;
} else if (cmp_nocase_uh(bin_type, "statesorted") == 0) {
return BT_state_sorted;
} else if (cmp_nocase_uh(bin_type, "fixed") == 0) {
return BT_fixed;
} else if (cmp_nocase_uh(bin_type, "back_to_front") == 0) {
return BT_back_to_front;
} else if (cmp_nocase_uh(bin_type, "backtofront") == 0) {
return BT_back_to_front;
} else if (cmp_nocase_uh(bin_type, "front_to_back") == 0) {
return BT_front_to_back;
} else if (cmp_nocase_uh(bin_type, "fronttoback") == 0) {
return BT_front_to_back;
} else if (cmp_nocase_uh(bin_type, "hierarchical_z") == 0) {
return BT_hierarchical_z;
} else {
return BT_invalid;
@ -385,6 +379,9 @@ operator << (ostream &out, CullBinManager::BinType bin_type) {
case CullBinManager::BT_fixed:
return out << "fixed";
case CullBinManager::BT_hierarchical_z:
return out << "hierarchical_z";
}
return out << "**invalid BinType(" << (int)bin_type << ")**";

View File

@ -47,6 +47,7 @@ PUBLISHED:
BT_back_to_front,
BT_front_to_back,
BT_fixed,
BT_hierarchical_z,
};
int add_bin(const string &name, BinType type, int sort);

View File

@ -86,6 +86,10 @@ public:
CPT(TransformState) _modelview_transform;
CullableObject *_next;
// This flag is only used by certain CullBin types. In particular,
// it is used by CullBinHierarchicalZBuffer.
bool _already_drawn;
private:
void munge_points_to_quads(const CullTraverser *traverser);
void munge_texcoord_light_vector(const CullTraverser *traverser);

View File

@ -99,9 +99,9 @@ PortalNode(const PortalNode &copy) :
_vertices(copy._vertices),
_cell_in(copy._cell_in),
_cell_out(copy._cell_out),
_clip_plane(copy._clip_plane),
_visible(copy._visible),
_open(copy._open),
_clip_plane(copy._clip_plane)
_open(copy._open)
{
}