Add hardware instancing support
This commit is contained in:
parent
f2a937c79f
commit
c136904fa9
|
|
@ -651,6 +651,19 @@ get_supports_two_sided_stencil() const {
|
|||
return _supports_two_sided_stencil;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_supports_geometry_instancing
|
||||
// Access: Published
|
||||
// Description: Returns true if this particular GSG supports
|
||||
// hardware geometry instancing: the ability to render
|
||||
// multiple copies of a model. In OpenGL, this is
|
||||
// done using the EXT_draw_instanced extension.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
get_supports_geometry_instancing() const {
|
||||
return _supports_geometry_instancing;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_maximum_simultaneous_render_targets
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
|
|||
_supports_stencil = false;
|
||||
_supports_stencil_wrap = false;
|
||||
_supports_two_sided_stencil = false;
|
||||
_supports_geometry_instancing = false;
|
||||
|
||||
_maximum_simultaneous_render_targets = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ PUBLISHED:
|
|||
INLINE bool get_supports_glsl() const;
|
||||
INLINE bool get_supports_stencil() const;
|
||||
INLINE bool get_supports_two_sided_stencil() const;
|
||||
INLINE bool get_supports_geometry_instancing() const;
|
||||
|
||||
INLINE int get_maximum_simultaneous_render_targets() const;
|
||||
|
||||
|
|
@ -467,6 +468,7 @@ protected:
|
|||
bool _supports_stencil;
|
||||
bool _supports_stencil_wrap;
|
||||
bool _supports_two_sided_stencil;
|
||||
bool _supports_geometry_instancing;
|
||||
|
||||
int _maximum_simultaneous_render_targets;
|
||||
|
||||
|
|
|
|||
|
|
@ -1454,6 +1454,26 @@ reset() {
|
|||
_glActiveStencilFaceEXT = 0;
|
||||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
// Some drivers expose one, some expose the other. ARB seems to be the newer one.
|
||||
if (has_extension("GL_ARB_draw_instanced")) {
|
||||
_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawArraysInstancedARB");
|
||||
_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawElementsInstancedARB");
|
||||
_supports_geometry_instancing = true;
|
||||
} else if (has_extension("GL_EXT_draw_instanced")) {
|
||||
_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawArraysInstancedEXT");
|
||||
_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawElementsInstancedEXT");
|
||||
_supports_geometry_instancing = true;
|
||||
} else {
|
||||
_glDrawElementsInstanced = 0;
|
||||
_glDrawArraysInstanced = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
_auto_rescale_normal = false;
|
||||
|
||||
// Ensure the initial state is what we say it should be (in some
|
||||
|
|
@ -2728,16 +2748,34 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
return false;
|
||||
}
|
||||
|
||||
_glDrawRangeElements(GL_TRIANGLES,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLES, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_TRIANGLES,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_TRIANGLES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2780,16 +2818,34 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLE_STRIP, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLE_STRIP,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -2812,11 +2868,21 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
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(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLE_STRIP, ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride,
|
||||
_instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP,
|
||||
mins.get_data1i(), maxs.get_data1i(),
|
||||
ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
}
|
||||
start = ends[i] + 2;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2824,8 +2890,16 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
int first_vertex = reader->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);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLE_STRIP, first_vertex + start,
|
||||
ends[i] - start, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start,
|
||||
ends[i] - start);
|
||||
}
|
||||
start = ends[i] + 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -2875,10 +2949,20 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
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(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLE_FAN, ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride,
|
||||
_instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_TRIANGLE_FAN,
|
||||
mins.get_data1i(), maxs.get_data1i(), ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
}
|
||||
start = ends[i];
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2886,8 +2970,16 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
int first_vertex = reader->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);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLE_FAN, first_vertex + start,
|
||||
ends[i] - start, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_TRIANGLE_FAN, first_vertex + start,
|
||||
ends[i] - start);
|
||||
}
|
||||
start = ends[i];
|
||||
}
|
||||
}
|
||||
|
|
@ -2926,16 +3018,34 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
_glDrawRangeElements(GL_LINES,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_LINES, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_LINES,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_LINES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_LINES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_LINES,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2982,16 +3092,34 @@ draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
_glDrawRangeElements(GL_POINTS,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_POINTS, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_glDrawRangeElements(GL_POINTS,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
GLP(DrawArrays)(GL_POINTS,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_POINTS,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLP(DrawArrays)(GL_POINTS,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6795,6 +6923,9 @@ set_state_and_transform(const RenderState *target,
|
|||
_target_rs = target;
|
||||
|
||||
_target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
|
||||
#ifndef OPENGLES
|
||||
_instance_count = _target_shader->get_instance_count();
|
||||
#endif
|
||||
#ifndef OPENGLES_1
|
||||
if (_target_shader->auto_shader()) {
|
||||
// If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
|
|||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
|
||||
#endif // OPENGLES_1
|
||||
#ifndef OPENGLES
|
||||
typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
|
||||
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
|
||||
#endif // OPENGLES
|
||||
#endif // __EDG__
|
||||
|
||||
|
|
@ -625,6 +626,8 @@ public:
|
|||
#endif // OPENGLES_1
|
||||
#ifndef OPENGLES
|
||||
PFNGLPROGRAMPARAMETERIEXTPROC _glProgramParameteri;
|
||||
PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced;
|
||||
PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
|
||||
#endif // OPENGLES
|
||||
|
||||
GLenum _edge_clamp;
|
||||
|
|
@ -633,6 +636,9 @@ public:
|
|||
GLenum _mirror_clamp;
|
||||
GLenum _mirror_edge_clamp;
|
||||
GLenum _mirror_border_clamp;
|
||||
#ifndef OPENGLES
|
||||
GLsizei _instance_count;
|
||||
#endif
|
||||
|
||||
LightMutex _lock;
|
||||
typedef pvector<GLuint> DeletedDisplayLists;
|
||||
|
|
|
|||
|
|
@ -3709,6 +3709,24 @@ get_shader_input(InternalName *id) const {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::get_instance_count
|
||||
// Access: Published
|
||||
// Description: Returns the geometry instance count, or 0 if
|
||||
// disabled. See set_instance_count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const int NodePath::
|
||||
get_instance_count() const {
|
||||
nassertr_always(!is_empty(), NULL);
|
||||
const RenderAttrib *attrib =
|
||||
node()->get_attrib(ShaderAttrib::get_class_slot());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
|
||||
return sa->get_instance_count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::clear_shader_input
|
||||
// Access: Published
|
||||
|
|
@ -3826,6 +3844,30 @@ clear_shader_input(const string &id) {
|
|||
clear_shader_input(InternalName::make(id));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_instance_count
|
||||
// Access: Published
|
||||
// Description: Sets the geometry instance count, or 0 if
|
||||
// geometry instancing should be disabled. Do not
|
||||
// confuse with instanceTo which only applies to
|
||||
// animation instancing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_instance_count(int instance_count) {
|
||||
nassertv_always(!is_empty());
|
||||
|
||||
const RenderAttrib *attrib =
|
||||
node()->get_attrib(ShaderAttrib::get_class_slot());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
|
||||
node()->set_attrib(sa->set_instance_count(instance_count));
|
||||
} else {
|
||||
// Create a new ShaderAttrib for this node.
|
||||
CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
|
||||
node()->set_attrib(sa->set_instance_count(instance_count));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_tex_transform
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -606,10 +606,12 @@ PUBLISHED:
|
|||
void set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, double n4=1, int priority=0);
|
||||
void clear_shader_input(InternalName *id);
|
||||
void clear_shader_input(const string &id);
|
||||
void set_instance_count(int instance_count);
|
||||
|
||||
const Shader *get_shader() const;
|
||||
const ShaderInput *get_shader_input(InternalName *id) const;
|
||||
const ShaderInput *get_shader_input(const string &id) const;
|
||||
const int get_instance_count() const;
|
||||
|
||||
void set_tex_transform(TextureStage *stage, const TransformState *transform);
|
||||
void clear_tex_transform();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ ShaderAttrib() :
|
|||
_auto_shader(false),
|
||||
_has_shader(false),
|
||||
_flags(0),
|
||||
_has_flags(0)
|
||||
_has_flags(0),
|
||||
_instance_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ ShaderAttrib(const ShaderAttrib ©) :
|
|||
_has_shader(copy._has_shader),
|
||||
_flags(copy._flags),
|
||||
_has_flags(copy._has_flags),
|
||||
_instance_count(copy._instance_count),
|
||||
_inputs(copy._inputs)
|
||||
{
|
||||
}
|
||||
|
|
@ -79,6 +81,17 @@ get_shader_priority() const {
|
|||
return _shader_priority;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderAttrib::get_instance_count
|
||||
// Access: Published
|
||||
// Description: Returns the number of geometry instances. A value
|
||||
// of 0 means not to use instancing at all.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ShaderAttrib::
|
||||
get_instance_count() const {
|
||||
return _instance_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderAttrib::get_flag
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ int ShaderAttrib::_attrib_slot;
|
|||
// the use of shaders (it does not clear out all shader
|
||||
// data, however.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPT(RenderAttrib) ShaderAttrib::
|
||||
make_off() {
|
||||
static CPT(RenderAttrib) _off_attrib;
|
||||
|
|
@ -259,6 +258,21 @@ set_shader_input(const string &id, double n1, double n2, double n3, double n4, i
|
|||
return set_shader_input(new ShaderInput(InternalName::make(id), LVector4f(n1,n2,n3,n4), priority));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderAttrib::set_instance_count
|
||||
// Access: Published
|
||||
// Description: Sets the geometry instance count. Do not confuse
|
||||
// this with instanceTo, which is used for animation
|
||||
// instancing, and has nothing to do with this.
|
||||
// A value of 0 means not to use instancing at all.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ShaderAttrib::
|
||||
set_instance_count(int instance_count) const {
|
||||
ShaderAttrib *result = new ShaderAttrib(*this);
|
||||
result->_instance_count = instance_count;
|
||||
return return_new(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderAttrib::clear_shader_input
|
||||
// Access: Published
|
||||
|
|
@ -456,6 +470,9 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||
if (this->_has_flags != that->_has_flags) {
|
||||
return (this->_has_flags < that->_has_flags) ? -1 : 1;
|
||||
}
|
||||
if (this->_instance_count != that->_instance_count) {
|
||||
return (this->_instance_count < that->_instance_count) ? -1 : 1;
|
||||
}
|
||||
|
||||
Inputs::const_iterator i1 = this->_inputs.begin();
|
||||
Inputs::const_iterator i2 = that->_inputs.begin();
|
||||
|
|
@ -511,6 +528,8 @@ compose_impl(const RenderAttrib *other) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Just copy the instance count.
|
||||
attr->_instance_count = over->_instance_count;
|
||||
// Update the flags.
|
||||
attr->_flags &= ~(over->_has_flags);
|
||||
attr->_flags |= over->_flags;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ PUBLISHED:
|
|||
INLINE bool has_shader() const;
|
||||
INLINE bool auto_shader() const;
|
||||
INLINE int get_shader_priority() const;
|
||||
INLINE int get_instance_count() const;
|
||||
|
||||
CPT(RenderAttrib) set_shader(const Shader *s, int priority=0) const;
|
||||
CPT(RenderAttrib) set_shader_off(int priority=0) const;
|
||||
|
|
@ -62,6 +63,8 @@ PUBLISHED:
|
|||
CPT(RenderAttrib) set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, double n4=1,
|
||||
int priority=0) const;
|
||||
|
||||
CPT(RenderAttrib) set_instance_count(int instance_count) const;
|
||||
|
||||
CPT(RenderAttrib) set_flag(int flag, bool value) const;
|
||||
CPT(RenderAttrib) clear_flag(int flag) const;
|
||||
|
||||
|
|
@ -96,6 +99,7 @@ private:
|
|||
bool _has_shader;
|
||||
int _flags;
|
||||
int _has_flags;
|
||||
int _instance_count;
|
||||
typedef pmap < CPT(InternalName), CPT(ShaderInput) > Inputs;
|
||||
Inputs _inputs;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue