immediate mode
This commit is contained in:
parent
8e71577259
commit
01bd239ce7
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
glext.h \
|
||||
panda_glext.h \
|
||||
glmisc_src.cxx \
|
||||
glmisc_src.h \
|
||||
glstuff_src.cxx \
|
||||
|
|
@ -22,6 +22,9 @@
|
|||
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 \
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ TypeHandle CLP(GraphicsStateGuardian)::_type_handle;
|
|||
PStatCollector CLP(GraphicsStateGuardian)::_load_display_list_pcollector("Draw:Transfer data:Display lists");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_primitive_batches_display_list_pcollector("Primitive batches:Display lists");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_vertices_display_list_pcollector("Vertices:Display lists");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_vertices_immediate_pcollector("Vertices:Immediate mode");
|
||||
|
||||
// The following noop functions are assigned to the corresponding
|
||||
// glext function pointers in the class, in case the functions are not
|
||||
|
|
@ -108,6 +109,7 @@ static void APIENTRY
|
|||
null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: uchar_bgr_to_rgb
|
||||
// Description: Recopies the given array of pixels, converting from
|
||||
|
|
@ -489,8 +491,14 @@ reset() {
|
|||
get_extension_func(GLPREFIX_QUOTED, "ActiveTexture");
|
||||
_glClientActiveTexture = (PFNGLACTIVETEXTUREPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "ClientActiveTexture");
|
||||
_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2fv");
|
||||
_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1f");
|
||||
_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2f");
|
||||
_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3f");
|
||||
_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4f");
|
||||
|
||||
} else if (has_extension("GL_ARB_multitexture")) {
|
||||
_supports_multitexture = true;
|
||||
|
|
@ -499,13 +507,20 @@ reset() {
|
|||
get_extension_func(GLPREFIX_QUOTED, "ActiveTextureARB");
|
||||
_glClientActiveTexture = (PFNGLACTIVETEXTUREPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "ClientActiveTextureARB");
|
||||
_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2fvARB");
|
||||
_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1fARB");
|
||||
_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2fARB");
|
||||
_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3fARB");
|
||||
_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4fARB");
|
||||
}
|
||||
|
||||
if (_supports_multitexture) {
|
||||
if (_glActiveTexture == NULL || _glClientActiveTexture == NULL ||
|
||||
_glMultiTexCoord2fv == NULL) {
|
||||
_glMultiTexCoord1f == NULL || _glMultiTexCoord2f == NULL ||
|
||||
_glMultiTexCoord3f == NULL || _glMultiTexCoord4f == NULL) {
|
||||
GLCAT.warning()
|
||||
<< "Multitexture advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
|
||||
_supports_multitexture = false;
|
||||
|
|
@ -687,6 +702,11 @@ reset() {
|
|||
GLCAT.debug()
|
||||
<< "vertex buffer objects are NOT supported.\n";
|
||||
}
|
||||
|
||||
if (!vertex_arrays) {
|
||||
GLCAT.debug()
|
||||
<< "immediate mode commands will be used instead of vertex arrays.\n";
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
|
|
@ -1270,125 +1290,192 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
|
|||
#endif
|
||||
}
|
||||
|
||||
const GeomVertexArrayData *array_data;
|
||||
int num_values;
|
||||
Geom::NumericType numeric_type;
|
||||
int start;
|
||||
int stride;
|
||||
if (!vertex_arrays) {
|
||||
// We must use immediate mode to render primitives.
|
||||
_sender.clear();
|
||||
_use_sender = true;
|
||||
|
||||
if (_vertex_data->get_vertex_info(array_data, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(VertexPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
if (_vertex_data->get_normal_info(array_data, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(NormalPointer)(get_numeric_type(numeric_type), stride,
|
||||
client_pointer + start);
|
||||
GLP(EnableClientState)(GL_NORMAL_ARRAY);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
if (_vertex_data->get_color_info(array_data, num_values, numeric_type,
|
||||
start, stride) &&
|
||||
numeric_type != Geom::NT_packed_dabc) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(ColorPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_COLOR_ARRAY);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_COLOR_ARRAY);
|
||||
|
||||
// Since we don't have per-vertex color, the implicit color is
|
||||
// white.
|
||||
GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Now set up each of the active texture coordinate stages--or at
|
||||
// least those for which we're not generating texture coordinates
|
||||
// automatically.
|
||||
const Geom::ActiveTextureStages &active_stages =
|
||||
_current_texture->get_on_stages();
|
||||
const Geom::NoTexCoordStages &no_texcoords =
|
||||
_current_tex_gen->get_no_texcoords();
|
||||
|
||||
int max_stage_index = (int)active_stages.size();
|
||||
int stage_index = 0;
|
||||
while (stage_index < max_stage_index) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
TextureStage *stage = active_stages[stage_index];
|
||||
if (no_texcoords.find(stage) == no_texcoords.end()) {
|
||||
// This stage is not one of the stages that doesn't need
|
||||
// texcoords issued for it.
|
||||
const InternalName *name = stage->get_texcoord_name();
|
||||
|
||||
if (_vertex_data->get_array_info(name, array_data, num_values,
|
||||
numeric_type, start, stride)) {
|
||||
// The vertex data does have texcoords for this stage.
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(TexCoordPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
} else {
|
||||
// The vertex data doesn't have texcoords for this stage (even
|
||||
// though they're needed).
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
} else {
|
||||
// No texcoords are needed for this stage.
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
_sender.add_column(_vertex_data, InternalName::get_normal(),
|
||||
NULL, NULL, GLP(Normal3f), NULL);
|
||||
if (!_sender.add_column(_vertex_data, InternalName::get_color(),
|
||||
NULL, NULL, GLP(Color3f), GLP(Color4f))) {
|
||||
// If we didn't have a color column, the item color is white.
|
||||
GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
++stage_index;
|
||||
}
|
||||
// Now set up each of the active texture coordinate stages--or at
|
||||
// least those for which we're not generating texture coordinates
|
||||
// automatically.
|
||||
const Geom::ActiveTextureStages &active_stages =
|
||||
_current_texture->get_on_stages();
|
||||
const Geom::NoTexCoordStages &no_texcoords =
|
||||
_current_tex_gen->get_no_texcoords();
|
||||
|
||||
int max_stage_index = (int)active_stages.size();
|
||||
int stage_index = 0;
|
||||
while (stage_index < max_stage_index) {
|
||||
TextureStage *stage = active_stages[stage_index];
|
||||
if (no_texcoords.find(stage) == no_texcoords.end()) {
|
||||
// This stage is not one of the stages that doesn't need
|
||||
// texcoords issued for it.
|
||||
const InternalName *name = stage->get_texcoord_name();
|
||||
if (stage_index == 0) {
|
||||
// Use the original functions for stage 0, in case we don't
|
||||
// support multitexture.
|
||||
_sender.add_column(_vertex_data, name,
|
||||
GLP(TexCoord1f), GLP(TexCoord2f),
|
||||
GLP(TexCoord3f), GLP(TexCoord4f));
|
||||
|
||||
// Be sure also to disable any texture stages we had enabled before.
|
||||
while (stage_index < _last_max_stage_index) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
++stage_index;
|
||||
}
|
||||
_last_max_stage_index = max_stage_index;
|
||||
|
||||
if (_supports_vertex_blend) {
|
||||
if (hardware_animation) {
|
||||
// Issue the weights and/or transform indices for vertex blending.
|
||||
if (_vertex_data->get_array_info(InternalName::get_transform_weight(),
|
||||
array_data, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
_glWeightPointerARB(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
} else {
|
||||
// Other stages require the multitexture functions.
|
||||
_sender.add_texcoord_column(_vertex_data, name, stage_index,
|
||||
_glMultiTexCoord1f, _glMultiTexCoord2f,
|
||||
_glMultiTexCoord3f, _glMultiTexCoord4f);
|
||||
}
|
||||
}
|
||||
|
||||
++stage_index;
|
||||
}
|
||||
|
||||
// Be sure also to disable any texture stages we had enabled before.
|
||||
while (stage_index < _last_max_stage_index) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
++stage_index;
|
||||
}
|
||||
_last_max_stage_index = max_stage_index;
|
||||
|
||||
if (animation.get_indexed_transforms()) {
|
||||
// Issue the matrix palette indices.
|
||||
if (_vertex_data->get_array_info(InternalName::get_transform_index(),
|
||||
// We must add vertex last, because glVertex3f() is the key
|
||||
// function call that actually issues the vertex.
|
||||
_sender.add_column(_vertex_data, InternalName::get_vertex(),
|
||||
NULL, GLP(Vertex2f), GLP(Vertex3f), GLP(Vertex4f));
|
||||
|
||||
} else {
|
||||
// We may use vertex arrays or buffers to render primitives.
|
||||
_use_sender = false;
|
||||
|
||||
const GeomVertexArrayData *array_data;
|
||||
int num_values;
|
||||
Geom::NumericType numeric_type;
|
||||
int start;
|
||||
int stride;
|
||||
|
||||
if (_vertex_data->get_normal_info(array_data, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(NormalPointer)(get_numeric_type(numeric_type), stride,
|
||||
client_pointer + start);
|
||||
GLP(EnableClientState)(GL_NORMAL_ARRAY);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
if (_vertex_data->get_color_info(array_data, num_values, numeric_type,
|
||||
start, stride) &&
|
||||
numeric_type != Geom::NT_packed_dabc) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(ColorPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_COLOR_ARRAY);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_COLOR_ARRAY);
|
||||
|
||||
// Since we don't have per-vertex color, the implicit color is
|
||||
// white.
|
||||
GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Now set up each of the active texture coordinate stages--or at
|
||||
// least those for which we're not generating texture coordinates
|
||||
// automatically.
|
||||
const Geom::ActiveTextureStages &active_stages =
|
||||
_current_texture->get_on_stages();
|
||||
const Geom::NoTexCoordStages &no_texcoords =
|
||||
_current_tex_gen->get_no_texcoords();
|
||||
|
||||
int max_stage_index = (int)active_stages.size();
|
||||
int stage_index = 0;
|
||||
while (stage_index < max_stage_index) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
TextureStage *stage = active_stages[stage_index];
|
||||
if (no_texcoords.find(stage) == no_texcoords.end()) {
|
||||
// This stage is not one of the stages that doesn't need
|
||||
// texcoords issued for it.
|
||||
const InternalName *name = stage->get_texcoord_name();
|
||||
|
||||
if (_vertex_data->get_array_info(name, array_data, num_values,
|
||||
numeric_type, start, stride)) {
|
||||
// The vertex data does have texcoords for this stage.
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(TexCoordPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
} else {
|
||||
// The vertex data doesn't have texcoords for this stage (even
|
||||
// though they're needed).
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
} else {
|
||||
// No texcoords are needed for this stage.
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
++stage_index;
|
||||
}
|
||||
|
||||
// Be sure also to disable any texture stages we had enabled before.
|
||||
while (stage_index < _last_max_stage_index) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
++stage_index;
|
||||
}
|
||||
_last_max_stage_index = max_stage_index;
|
||||
|
||||
if (_supports_vertex_blend) {
|
||||
if (hardware_animation) {
|
||||
// Issue the weights and/or transform indices for vertex blending.
|
||||
if (_vertex_data->get_array_info(InternalName::get_transform_weight(),
|
||||
array_data, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
_glMatrixIndexPointerARB(num_values, get_numeric_type(numeric_type),
|
||||
_glWeightPointerARB(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
|
||||
GLP(EnableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
}
|
||||
|
||||
if (animation.get_indexed_transforms()) {
|
||||
// Issue the matrix palette indices.
|
||||
if (_vertex_data->get_array_info(InternalName::get_transform_index(),
|
||||
array_data, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
_glMatrixIndexPointerARB(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
if (_supports_matrix_palette) {
|
||||
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
|
||||
if (_supports_matrix_palette) {
|
||||
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
|
||||
}
|
||||
// There's no requirement that we add vertices last, but we do
|
||||
// anyway.
|
||||
if (_vertex_data->get_vertex_info(array_data, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
const unsigned char *client_pointer = setup_array_data(array_data);
|
||||
GLP(VertexPointer)(num_values, get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
GLP(EnableClientState)(GL_VERTEX_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1412,21 +1499,26 @@ draw_triangles(const GeomTriangles *primitive) {
|
|||
_vertices_tri_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_tri_pcollector.add_level(1);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
|
||||
_glDrawRangeElements(GL_TRIANGLES,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLES,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
if (_use_sender) {
|
||||
draw_immediate_simple_primitives(primitive, GL_TRIANGLES);
|
||||
|
||||
} else {
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
|
||||
_glDrawRangeElements(GL_TRIANGLES,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLES,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
|
||||
|
|
@ -1443,57 +1535,62 @@ draw_tristrips(const GeomTristrips *primitive) {
|
|||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) {
|
||||
// One long triangle strip, connected by the degenerate vertices
|
||||
// that have already been set up within the primitive.
|
||||
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_tristrip_pcollector.add_level(1);
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
if (_use_sender) {
|
||||
draw_immediate_composite_primitives(primitive, GL_TRIANGLE_STRIP);
|
||||
|
||||
} else {
|
||||
// Send the individual triangle strips, stepping over the
|
||||
// degenerate vertices.
|
||||
CPTA_int ends = primitive->get_ends();
|
||||
|
||||
_primitive_batches_tristrip_pcollector.add_level(ends.size());
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
int index_stride = primitive->get_index_stride();
|
||||
GeomVertexReader mins(primitive->get_mins(), 0);
|
||||
GeomVertexReader maxs(primitive->get_maxs(), 0);
|
||||
nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
primitive->get_maxs()->get_num_rows() == (int)ends.size());
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
if (connect_triangle_strips && _render_mode != RenderModeAttrib::M_wireframe) {
|
||||
// One long triangle strip, connected by the degenerate vertices
|
||||
// that have already been set up within the primitive.
|
||||
_vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_tristrip_pcollector.add_level(1);
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
mins.get_data1i(), maxs.get_data1i(),
|
||||
ends[i] - start,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
start = ends[i] + 2;
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = primitive->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start,
|
||||
ends[i] - start);
|
||||
start = ends[i] + 2;
|
||||
// Send the individual triangle strips, stepping over the
|
||||
// degenerate vertices.
|
||||
CPTA_int ends = primitive->get_ends();
|
||||
|
||||
_primitive_batches_tristrip_pcollector.add_level(ends.size());
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
int index_stride = primitive->get_index_stride();
|
||||
GeomVertexReader mins(primitive->get_mins(), 0);
|
||||
GeomVertexReader maxs(primitive->get_maxs(), 0);
|
||||
nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
primitive->get_maxs()->get_num_rows() == (int)ends.size());
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
mins.get_data1i(), maxs.get_data1i(),
|
||||
ends[i] - start,
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
start = ends[i] + 2;
|
||||
}
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = primitive->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start,
|
||||
ends[i] - start);
|
||||
start = ends[i] + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1514,36 +1611,41 @@ draw_trifans(const GeomTrifans *primitive) {
|
|||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
// Send the individual triangle fans. There's no connecting fans
|
||||
// with degenerate vertices, so no worries about that.
|
||||
CPTA_int ends = primitive->get_ends();
|
||||
if (_use_sender) {
|
||||
draw_immediate_composite_primitives(primitive, GL_TRIANGLE_FAN);
|
||||
|
||||
_primitive_batches_trifan_pcollector.add_level(ends.size());
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
int index_stride = primitive->get_index_stride();
|
||||
GeomVertexReader mins(primitive->get_mins(), 0);
|
||||
GeomVertexReader maxs(primitive->get_maxs(), 0);
|
||||
nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
primitive->get_maxs()->get_num_rows() == (int)ends.size());
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
_glDrawRangeElements(GL_TRIANGLE_FAN,
|
||||
mins.get_data1i(), maxs.get_data1i(), ends[i] - start,
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
start = ends[i];
|
||||
}
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = primitive->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
GLP(DrawArrays)(GL_TRIANGLE_FAN, first_vertex + start,
|
||||
ends[i] - start);
|
||||
start = ends[i];
|
||||
// Send the individual triangle fans. There's no connecting fans
|
||||
// with degenerate vertices, so no worries about that.
|
||||
CPTA_int ends = primitive->get_ends();
|
||||
|
||||
_primitive_batches_trifan_pcollector.add_level(ends.size());
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
int index_stride = primitive->get_index_stride();
|
||||
GeomVertexReader mins(primitive->get_mins(), 0);
|
||||
GeomVertexReader maxs(primitive->get_maxs(), 0);
|
||||
nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
primitive->get_maxs()->get_num_rows() == (int)ends.size());
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
_glDrawRangeElements(GL_TRIANGLE_FAN,
|
||||
mins.get_data1i(), maxs.get_data1i(), ends[i] - start,
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
start = ends[i];
|
||||
}
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = primitive->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
GLP(DrawArrays)(GL_TRIANGLE_FAN, first_vertex + start,
|
||||
ends[i] - start);
|
||||
start = ends[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1563,21 +1665,26 @@ draw_lines(const GeomLines *primitive) {
|
|||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
if (_use_sender) {
|
||||
draw_immediate_simple_primitives(primitive, GL_LINES);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_LINES,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_LINES,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_LINES,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_LINES,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
|
|
@ -1611,21 +1718,26 @@ draw_points(const GeomPoints *primitive) {
|
|||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
if (_use_sender) {
|
||||
draw_immediate_simple_primitives(primitive, GL_POINTS);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_POINTS,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_POINTS,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
_vertices_other_pcollector.add_level(primitive->get_num_vertices());
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
const unsigned char *client_pointer = setup_primitive(primitive);
|
||||
_glDrawRangeElements(GL_POINTS,
|
||||
primitive->get_min_vertex(),
|
||||
primitive->get_max_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
get_numeric_type(primitive->get_index_type()),
|
||||
client_pointer);
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_POINTS,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices());
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
|
|
@ -2950,7 +3062,81 @@ wants_texcoords() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: report_errors_loop
|
||||
// Function: GLGraphicsStateGuardian::draw_immediate_simple_primitives
|
||||
// Access: Protected
|
||||
// Description: Uses the ImmediateModeSender to draw a series of
|
||||
// primitives of the indicated type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
draw_immediate_simple_primitives(const GeomPrimitive *primitive, GLenum mode) {
|
||||
_vertices_immediate_pcollector.add_level(primitive->get_num_vertices());
|
||||
GLP(Begin)(mode);
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
for (int v = 0; v < primitive->get_num_vertices(); ++v) {
|
||||
_sender.set_vertex(primitive->get_vertex(v));
|
||||
_sender.issue_vertex();
|
||||
}
|
||||
|
||||
} else {
|
||||
_sender.set_vertex(primitive->get_first_vertex());
|
||||
for (int v = 0; v < primitive->get_num_vertices(); ++v) {
|
||||
_sender.issue_vertex();
|
||||
}
|
||||
}
|
||||
|
||||
GLP(End)();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::draw_immediate_composite_primitives
|
||||
// Access: Protected
|
||||
// Description: Uses the ImmediateModeSender to draw a series of
|
||||
// primitives of the indicated type. This form is for
|
||||
// primitive types like tristrips which must involve
|
||||
// several begin/end groups.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
draw_immediate_composite_primitives(const GeomPrimitive *primitive, GLenum mode) {
|
||||
_vertices_immediate_pcollector.add_level(primitive->get_num_vertices());
|
||||
CPTA_int ends = primitive->get_ends();
|
||||
|
||||
if (primitive->is_indexed()) {
|
||||
int begin = 0;
|
||||
CPTA_int::const_iterator ei;
|
||||
for (ei = ends.begin(); ei != ends.end(); ++ei) {
|
||||
int end = (*ei);
|
||||
|
||||
GLP(Begin)(mode);
|
||||
for (int v = begin; v < end; ++v) {
|
||||
_sender.set_vertex(primitive->get_vertex(v));
|
||||
_sender.issue_vertex();
|
||||
}
|
||||
GLP(End)();
|
||||
|
||||
begin = end;
|
||||
}
|
||||
|
||||
} else {
|
||||
_sender.set_vertex(primitive->get_first_vertex());
|
||||
int begin = 0;
|
||||
CPTA_int::const_iterator ei;
|
||||
for (ei = ends.begin(); ei != ends.end(); ++ei) {
|
||||
int end = (*ei);
|
||||
|
||||
GLP(Begin)(mode);
|
||||
for (int v = begin; v < end; ++v) {
|
||||
_sender.issue_vertex();
|
||||
}
|
||||
GLP(End)();
|
||||
|
||||
begin = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::report_errors_loop
|
||||
// Access: Protected, Static
|
||||
// Description: The internal implementation of report_errors().
|
||||
// Don't call this function; use report_errors()
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start,
|
|||
typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, const GLfloat s);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, const GLfloat s, const GLfloat t);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, const GLfloat s, const GLfloat t, const GLfloat r);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, const GLfloat s, const GLfloat t, const GLfloat r, const GLfloat q);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
|
||||
|
|
@ -154,6 +157,8 @@ public:
|
|||
void dump_state(void);
|
||||
|
||||
const float *get_light_color(Light *light) const;
|
||||
void draw_immediate_simple_primitives(const GeomPrimitive *primitive, GLenum mode);
|
||||
void draw_immediate_composite_primitives(const GeomPrimitive *primitive, GLenum mode);
|
||||
|
||||
INLINE static bool report_errors(int line, const char *source_file);
|
||||
INLINE void report_my_errors(int line, const char *source_file);
|
||||
|
|
@ -301,6 +306,9 @@ protected:
|
|||
bool _vertex_blending_enabled;
|
||||
|
||||
CPT(DisplayRegion) _actual_display_region;
|
||||
CLP(ImmediateModeSender) _sender;
|
||||
bool _use_sender;
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
PT(CgShader) _cg_shader; // The current CgShader object
|
||||
typedef pmap< PT(CgShader), PT(CLP(CgShaderContext)) > CGSHADERCONTEXTS;
|
||||
|
|
@ -346,7 +354,10 @@ public:
|
|||
bool _supports_multitexture;
|
||||
PFNGLACTIVETEXTUREPROC _glActiveTexture;
|
||||
PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
|
||||
PFNGLMULTITEXCOORD2FVPROC _glMultiTexCoord2fv;
|
||||
PFNGLMULTITEXCOORD1FPROC _glMultiTexCoord1f;
|
||||
PFNGLMULTITEXCOORD2FPROC _glMultiTexCoord2f;
|
||||
PFNGLMULTITEXCOORD3FPROC _glMultiTexCoord3f;
|
||||
PFNGLMULTITEXCOORD4FPROC _glMultiTexCoord4f;
|
||||
|
||||
bool _supports_buffers;
|
||||
PFNGLGENBUFFERSPROC _glGenBuffers;
|
||||
|
|
@ -372,6 +383,7 @@ public:
|
|||
static PStatCollector _load_display_list_pcollector;
|
||||
static PStatCollector _primitive_batches_display_list_pcollector;
|
||||
static PStatCollector _vertices_display_list_pcollector;
|
||||
static PStatCollector _vertices_immediate_pcollector;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
// Filename: glImmediateModeSender_src.I
|
||||
// Created by: drose (15Aug05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CLP(ImmediateModeSender)::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::
|
||||
CLP(ImmediateModeSender)() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender::Constructor
|
||||
// Access: Public
|
||||
// Description: The ComponentSender becomes the owner of the
|
||||
// GeomVertexReader pointer, and will delete it when it
|
||||
// is done.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::ComponentSender::
|
||||
ComponentSender(GeomVertexReader *reader) :
|
||||
_reader(reader)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender::set_vertex
|
||||
// Access: Public
|
||||
// Description: Specifies the vertex index of the next vertex to
|
||||
// send. If this is not called, the next consecutive
|
||||
// vertex will be sent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLP(ImmediateModeSender)::ComponentSender::
|
||||
set_vertex(int vertex_index) {
|
||||
_reader->set_row(vertex_index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender1f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::ComponentSender1f::
|
||||
ComponentSender1f(GeomVertexReader *reader, Func1f *func) :
|
||||
ComponentSender(reader),
|
||||
_func(func)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender2f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::ComponentSender2f::
|
||||
ComponentSender2f(GeomVertexReader *reader, Func2f *func) :
|
||||
ComponentSender(reader),
|
||||
_func(func)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender3f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::ComponentSender3f::
|
||||
ComponentSender3f(GeomVertexReader *reader, Func3f *func) :
|
||||
ComponentSender(reader),
|
||||
_func(func)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender4f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::ComponentSender4f::
|
||||
ComponentSender4f(GeomVertexReader *reader, Func4f *func) :
|
||||
ComponentSender(reader),
|
||||
_func(func)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender1f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::TexcoordSender1f::
|
||||
TexcoordSender1f(GeomVertexReader *reader, TexcoordFunc1f *func,
|
||||
int stage_index) :
|
||||
ComponentSender(reader),
|
||||
_func(func),
|
||||
_stage_index(stage_index)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender2f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::TexcoordSender2f::
|
||||
TexcoordSender2f(GeomVertexReader *reader, TexcoordFunc2f *func,
|
||||
int stage_index) :
|
||||
ComponentSender(reader),
|
||||
_func(func),
|
||||
_stage_index(stage_index)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender3f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::TexcoordSender3f::
|
||||
TexcoordSender3f(GeomVertexReader *reader, TexcoordFunc3f *func,
|
||||
int stage_index) :
|
||||
ComponentSender(reader),
|
||||
_func(func),
|
||||
_stage_index(stage_index)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender4f::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(ImmediateModeSender)::TexcoordSender4f::
|
||||
TexcoordSender4f(GeomVertexReader *reader, TexcoordFunc4f *func,
|
||||
int stage_index) :
|
||||
ComponentSender(reader),
|
||||
_func(func),
|
||||
_stage_index(stage_index)
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
// Filename: glImmediateModeSender_src.cxx
|
||||
// Created by: drose (15Aug05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CLP(ImmediateModeSender)::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CLP(ImmediateModeSender)::
|
||||
~CLP(ImmediateModeSender)() {
|
||||
clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::clear
|
||||
// Access: Public
|
||||
// Description: Removes (and deletes) all of the senders from the
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::
|
||||
clear() {
|
||||
ComponentSenders::iterator si;
|
||||
for (si = _senders.begin(); si != _senders.end(); ++si) {
|
||||
delete (*si);
|
||||
}
|
||||
_senders.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::set_vertex
|
||||
// Access: Public
|
||||
// Description: Specifies the vertex index of the next vertex to
|
||||
// send. If this is not called, the next consecutive
|
||||
// vertex will be sent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::
|
||||
set_vertex(int vertex_index) {
|
||||
ComponentSenders::iterator si;
|
||||
for (si = _senders.begin(); si != _senders.end(); ++si) {
|
||||
(*si)->set_vertex(vertex_index);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::issue_vertex
|
||||
// Access: Public
|
||||
// Description: Sends the next vertex to the OpenGL API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::
|
||||
issue_vertex() {
|
||||
ComponentSenders::iterator si;
|
||||
for (si = _senders.begin(); si != _senders.end(); ++si) {
|
||||
(*si)->issue_vertex();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::add_column
|
||||
// Access: Public
|
||||
// Description: Creates a new ComponentSender for the named data
|
||||
// column, if it exists in the vertex data, and adds it
|
||||
// to the list of senders for this object.
|
||||
//
|
||||
// The four function pointers are the four variants on
|
||||
// the function pointer for the possible number of
|
||||
// components of the data column. The appropriate
|
||||
// pointer will be used, depending on the number of
|
||||
// components the data column actually uses.
|
||||
//
|
||||
// The return value is true if the column is added,
|
||||
// false if it is not for some reason (for instance, the
|
||||
// named column doesn't exist in the vertex data).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(ImmediateModeSender)::
|
||||
add_column(const GeomVertexData *vertex_data, const InternalName *name,
|
||||
Func1f *func1f, Func2f *func2f, Func3f *func3f, Func4f *func4f) {
|
||||
if (vertex_data->has_column(name)) {
|
||||
GeomVertexReader *reader = new GeomVertexReader(vertex_data, name);
|
||||
ComponentSender *sender = NULL;
|
||||
const GeomVertexColumn *column = reader->get_column();
|
||||
switch (column->get_num_components()) {
|
||||
case 1:
|
||||
if (func1f != (Func1f *)NULL) {
|
||||
sender = new ComponentSender1f(reader, func1f);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (func2f != (Func2f *)NULL) {
|
||||
sender = new ComponentSender2f(reader, func2f);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (func3f != (Func3f *)NULL) {
|
||||
sender = new ComponentSender3f(reader, func3f);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (func4f != (Func4f *)NULL) {
|
||||
sender = new ComponentSender4f(reader, func4f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sender != (ComponentSender *)NULL) {
|
||||
// Ok, we've got a valid sender; add it to the list.
|
||||
_senders.push_back(sender);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// We didn't get a valid sender; clean up and return.
|
||||
delete reader;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::add_texcoord_column
|
||||
// Access: Public
|
||||
// Description: Creates a new ComponentSender for the named data
|
||||
// column, if it exists in the vertex data, and adds it
|
||||
// to the list of senders for this object.
|
||||
//
|
||||
// This works like add_column(), but it specifically
|
||||
// handles a texcoord-style column, which requires one
|
||||
// additional parameter to OpenGL: the texture stage.
|
||||
//
|
||||
// The return value is true if the column is added,
|
||||
// false if it is not for some reason (for instance, the
|
||||
// named column doesn't exist in the vertex data).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(ImmediateModeSender)::
|
||||
add_texcoord_column(const GeomVertexData *vertex_data,
|
||||
const InternalName *name, int stage_index,
|
||||
TexcoordFunc1f *func1f, TexcoordFunc2f *func2f,
|
||||
TexcoordFunc3f *func3f, TexcoordFunc4f *func4f) {
|
||||
if (vertex_data->has_column(name)) {
|
||||
GeomVertexReader *reader = new GeomVertexReader(vertex_data, name);
|
||||
ComponentSender *sender = NULL;
|
||||
const GeomVertexColumn *column = reader->get_column();
|
||||
switch (column->get_num_components()) {
|
||||
case 1:
|
||||
sender = new TexcoordSender1f(reader, func1f, stage_index);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
sender = new TexcoordSender2f(reader, func2f, stage_index);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
sender = new TexcoordSender3f(reader, func3f, stage_index);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
sender = new TexcoordSender4f(reader, func4f, stage_index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sender != (ComponentSender *)NULL) {
|
||||
// Ok, we've got a valid sender; add it to the list.
|
||||
_senders.push_back(sender);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// We didn't get a valid sender; clean up and return.
|
||||
delete reader;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::add_sender
|
||||
// Access: Public
|
||||
// Description: Adds a new ComponentSender to the list of senders for
|
||||
// this object. The GLImmediateModeSender object
|
||||
// becomes the owner of the ComponentSender pointer and
|
||||
// will delete it when it is done.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::
|
||||
add_sender(ComponentSender *sender) {
|
||||
_senders.push_back(sender);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CLP(ImmediateModeSender)::ComponentSender::
|
||||
~ComponentSender() {
|
||||
delete _reader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender1f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::ComponentSender1f::
|
||||
issue_vertex() {
|
||||
float d = _reader->get_data1f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender2f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::ComponentSender2f::
|
||||
issue_vertex() {
|
||||
const LVecBase2f &d = _reader->get_data2f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(d[0], d[1]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender3f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::ComponentSender3f::
|
||||
issue_vertex() {
|
||||
const LVecBase3f &d = _reader->get_data3f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(d[0], d[1], d[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::ComponentSender4f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::ComponentSender4f::
|
||||
issue_vertex() {
|
||||
const LVecBase4f &d = _reader->get_data4f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(d[0], d[1], d[2], d[3]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender1f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::TexcoordSender1f::
|
||||
issue_vertex() {
|
||||
float d = _reader->get_data1f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ", stage " << _stage_index
|
||||
<< ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(GL_TEXTURE0 + _stage_index, d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender2f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::TexcoordSender2f::
|
||||
issue_vertex() {
|
||||
const LVecBase2f &d = _reader->get_data2f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ", stage " << _stage_index
|
||||
<< ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(GL_TEXTURE0 + _stage_index, d[0], d[1]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender3f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::TexcoordSender3f::
|
||||
issue_vertex() {
|
||||
const LVecBase3f &d = _reader->get_data3f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ", stage " << _stage_index
|
||||
<< ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(GL_TEXTURE0 + _stage_index, d[0], d[1], d[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(ImmediateModeSender)::TexcoordSender4f::issue_vertex
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ImmediateModeSender)::TexcoordSender4f::
|
||||
issue_vertex() {
|
||||
const LVecBase4f &d = _reader->get_data4f();
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< *_reader->get_column()->get_name() << ", stage " << _stage_index
|
||||
<< ": " << d << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
(*_func)(GL_TEXTURE0 + _stage_index, d[0], d[1], d[2], d[3]);
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
// Filename: glImmediateModeSender_src.h
|
||||
// Created by: drose (15Aug05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pandabase.h"
|
||||
#include "geomVertexReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GLImmediateModeSender
|
||||
// Description : This class collects together a handful of objects
|
||||
// that will issue immediate-mode commands like
|
||||
// glVertex, glTexCoord, etc., for the purposes of
|
||||
// sending an object's vertices using the immediate mode
|
||||
// functions.
|
||||
//
|
||||
// Normally, this isn't used, since it's almost always
|
||||
// better to use vertex arrays or vertex buffers
|
||||
// instead. But OpenGL is a complicated API, and some
|
||||
// drivers might have issues handling the vertex arrays;
|
||||
// this code is provided as a last-ditch fallback in
|
||||
// case you have such spectacularly buggy drivers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_GL CLP(ImmediateModeSender) {
|
||||
public:
|
||||
INLINE CLP(ImmediateModeSender)();
|
||||
~CLP(ImmediateModeSender)();
|
||||
|
||||
void clear();
|
||||
|
||||
void set_vertex(int vertex_index);
|
||||
void issue_vertex();
|
||||
|
||||
class ComponentSender;
|
||||
typedef void GLAPIENTRY (Func1f)(GLfloat a);
|
||||
typedef void GLAPIENTRY (Func2f)(GLfloat a, GLfloat b);
|
||||
typedef void GLAPIENTRY (Func3f)(GLfloat a, GLfloat b, GLfloat c);
|
||||
typedef void GLAPIENTRY (Func4f)(GLfloat a, GLfloat b, GLfloat c, GLfloat d);
|
||||
typedef void GLAPIENTRY (TexcoordFunc1f)(GLenum texture, GLfloat a);
|
||||
typedef void GLAPIENTRY (TexcoordFunc2f)(GLenum texture, GLfloat a, GLfloat b);
|
||||
typedef void GLAPIENTRY (TexcoordFunc3f)(GLenum texture, GLfloat a, GLfloat b, GLfloat c);
|
||||
typedef void GLAPIENTRY (TexcoordFunc4f)(GLenum texture, GLfloat a, GLfloat b, GLfloat c, GLfloat d);
|
||||
|
||||
bool add_column(const GeomVertexData *vertex_data, const InternalName *name,
|
||||
Func1f *func1f, Func2f *func2f, Func3f *func3f, Func4f *func4f);
|
||||
bool add_texcoord_column(const GeomVertexData *vertex_data,
|
||||
const InternalName *name, int stage_index,
|
||||
TexcoordFunc1f *func1f, TexcoordFunc2f *func2f,
|
||||
TexcoordFunc3f *func3f, TexcoordFunc4f *func4f);
|
||||
|
||||
void add_sender(ComponentSender *sender);
|
||||
|
||||
public:
|
||||
|
||||
class ComponentSender {
|
||||
public:
|
||||
INLINE ComponentSender(GeomVertexReader *reader);
|
||||
virtual ~ComponentSender();
|
||||
INLINE void set_vertex(int vertex_index);
|
||||
virtual void issue_vertex()=0;
|
||||
protected:
|
||||
GeomVertexReader *_reader;
|
||||
};
|
||||
|
||||
class ComponentSender1f : public ComponentSender {
|
||||
public:
|
||||
INLINE ComponentSender1f(GeomVertexReader *reader, Func1f *func);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
Func1f *_func;
|
||||
};
|
||||
|
||||
class ComponentSender2f : public ComponentSender {
|
||||
public:
|
||||
INLINE ComponentSender2f(GeomVertexReader *reader, Func2f *func);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
Func2f *_func;
|
||||
};
|
||||
|
||||
class ComponentSender3f : public ComponentSender {
|
||||
public:
|
||||
INLINE ComponentSender3f(GeomVertexReader *reader, Func3f *func);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
Func3f *_func;
|
||||
};
|
||||
|
||||
class ComponentSender4f : public ComponentSender {
|
||||
public:
|
||||
INLINE ComponentSender4f(GeomVertexReader *reader, Func4f *func);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
Func4f *_func;
|
||||
};
|
||||
|
||||
class TexcoordSender1f : public ComponentSender {
|
||||
public:
|
||||
INLINE TexcoordSender1f(GeomVertexReader *reader, TexcoordFunc1f *func,
|
||||
int stage_index);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
TexcoordFunc1f *_func;
|
||||
int _stage_index;
|
||||
};
|
||||
|
||||
class TexcoordSender2f : public ComponentSender {
|
||||
public:
|
||||
INLINE TexcoordSender2f(GeomVertexReader *reader, TexcoordFunc2f *func,
|
||||
int stage_index);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
TexcoordFunc2f *_func;
|
||||
int _stage_index;
|
||||
};
|
||||
|
||||
class TexcoordSender3f : public ComponentSender {
|
||||
public:
|
||||
INLINE TexcoordSender3f(GeomVertexReader *reader, TexcoordFunc3f *func,
|
||||
int stage_index);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
TexcoordFunc3f *_func;
|
||||
int _stage_index;
|
||||
};
|
||||
|
||||
class TexcoordSender4f : public ComponentSender {
|
||||
public:
|
||||
INLINE TexcoordSender4f(GeomVertexReader *reader, TexcoordFunc4f *func,
|
||||
int stage_index);
|
||||
virtual void issue_vertex();
|
||||
private:
|
||||
TexcoordFunc4f *_func;
|
||||
int _stage_index;
|
||||
};
|
||||
|
||||
private:
|
||||
typedef pvector<ComponentSender *> ComponentSenders;
|
||||
ComponentSenders _senders;
|
||||
};
|
||||
|
||||
#include "glImmediateModeSender_src.I"
|
||||
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "glGeomContext_src.cxx"
|
||||
#include "glGeomMunger_src.cxx"
|
||||
#include "glCgShaderContext_src.cxx"
|
||||
#include "glImmediateModeSender_src.cxx"
|
||||
#include "glGraphicsStateGuardian_src.cxx"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
// This file is not protected from multiple inclusion; it may need to
|
||||
// be included multiple times.
|
||||
|
||||
#include "glext.h"
|
||||
#include "panda_glext.h"
|
||||
|
||||
#include "glmisc_src.h"
|
||||
#include "glTextureContext_src.h"
|
||||
|
|
@ -46,6 +46,6 @@
|
|||
#include "glGeomContext_src.h"
|
||||
#include "glGeomMunger_src.h"
|
||||
#include "glCgShaderContext_src.h"
|
||||
#include "glImmediateModeSender_src.h"
|
||||
#include "glGraphicsStateGuardian_src.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,21 @@ ConfigVariableBool vertex_buffers
|
|||
"or offscreen buffers). On lower-end graphics cards this will "
|
||||
"make little or no difference."));
|
||||
|
||||
ConfigVariableBool vertex_arrays
|
||||
("vertex-arrays", true,
|
||||
PRC_DESC("Set this true to allow the use of vertex arrays for rendering "
|
||||
"OpenGL vertex data. This, or vertex buffers, is the normal "
|
||||
"way of issuing vertices ever since OpenGL 1.1, and you "
|
||||
"almost always want to have set to true. However, some very "
|
||||
"buggy graphics drivers may have problems handling vertex arrays "
|
||||
"correctly, so if you are experiencing problems you might try "
|
||||
"setting this to false. If this is false, Panda will fall back "
|
||||
"to using immediate-mode commands like glVertex3f(), etc., to "
|
||||
"issue the vertices, which is potentially much slower than "
|
||||
"vertex arrays. Setting this false causes vertex_buffers to be "
|
||||
"ignored (since vertex buffers are a special case of vertex "
|
||||
"arrays in OpenGL). This has no effect on DirectX rendering."));
|
||||
|
||||
ConfigVariableBool display_lists
|
||||
("display-lists", false,
|
||||
PRC_DESC("Set this true to allow the use of OpenGL display lists for "
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ EXPCL_PANDA istream &operator >> (istream &in, AutoTextureScale &ats);
|
|||
extern EXPCL_PANDA ConfigVariableInt max_texture_dimension;
|
||||
extern EXPCL_PANDA ConfigVariableBool keep_texture_ram;
|
||||
extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA ConfigVariableBool vertex_arrays;
|
||||
extern EXPCL_PANDA ConfigVariableBool display_lists;
|
||||
extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices;
|
||||
extern EXPCL_PANDA ConfigVariableBool hardware_point_sprites;
|
||||
|
|
|
|||
Loading…
Reference in New Issue