mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
Reduce redundant state changes, add gl-fixed-vertex-attrib-locations
This commit is contained in:
parent
927a5bd48b
commit
08c29313b2
@ -33,7 +33,8 @@ CullBinStateSorted(const string &name, GraphicsStateGuardianBase *gsg,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE CullBinStateSorted::ObjectData::
|
INLINE CullBinStateSorted::ObjectData::
|
||||||
ObjectData(CullableObject *object) :
|
ObjectData(CullableObject *object) :
|
||||||
_object(object)
|
_object(object),
|
||||||
|
_format(object->_munged_data->get_format())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,16 +46,30 @@ ObjectData(CullableObject *object) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool CullBinStateSorted::ObjectData::
|
INLINE bool CullBinStateSorted::ObjectData::
|
||||||
operator < (const ObjectData &other) const {
|
operator < (const ObjectData &other) const {
|
||||||
// First group objects by transform, since transform changes are
|
// Group by state changes, in approximate order from heaviest
|
||||||
// supposed to be expensive.
|
// change to lightest change.
|
||||||
|
const RenderState *sa = _object->_state;
|
||||||
|
const RenderState *sb = other._object->_state;
|
||||||
|
int compare = sa->compare_sort(*sb);
|
||||||
|
if (compare != 0) {
|
||||||
|
return compare < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex format changes are also fairly slow.
|
||||||
|
if (_format != other._format) {
|
||||||
|
return _format < other._format;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent unnecessary vertex buffer rebinds.
|
||||||
|
if (_object->_munged_data != other._object->_munged_data) {
|
||||||
|
return _object->_munged_data < other._object->_munged_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uniform updates are actually pretty fast.
|
||||||
if (_object->_internal_transform != other._object->_internal_transform) {
|
if (_object->_internal_transform != other._object->_internal_transform) {
|
||||||
return _object->_internal_transform < other._object->_internal_transform;
|
return _object->_internal_transform < other._object->_internal_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then group by other state changes, in approximate order from
|
return 0;
|
||||||
// heaviest change to lightest change.
|
|
||||||
const RenderState *sa = _object->_state;
|
|
||||||
const RenderState *sb = other._object->_state;
|
|
||||||
return sa->compare_sort(*sb) < 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ private:
|
|||||||
INLINE bool operator < (const ObjectData &other) const;
|
INLINE bool operator < (const ObjectData &other) const;
|
||||||
|
|
||||||
CullableObject *_object;
|
CullableObject *_object;
|
||||||
|
const GeomVertexFormat *_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pvector<ObjectData> Objects;
|
typedef pvector<ObjectData> Objects;
|
||||||
|
@ -1036,7 +1036,7 @@ disable_shader_texture_bindings() {
|
|||||||
if (p == 0) continue;
|
if (p == 0) continue;
|
||||||
|
|
||||||
int texunit = cgGetParameterResourceIndex(p);
|
int texunit = cgGetParameterResourceIndex(p);
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
_glgsg->set_active_texture_stage(texunit);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_1D, 0);
|
glBindTexture(GL_TEXTURE_1D, 0);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
@ -1099,7 +1099,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
if (tex.is_null()) {
|
if (tex.is_null()) {
|
||||||
// Apply a white texture in order to make it easier to use a shader
|
// Apply a white texture in order to make it easier to use a shader
|
||||||
// that takes a texture on a model that doesn't have a texture applied.
|
// that takes a texture on a model that doesn't have a texture applied.
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
_glgsg->set_active_texture_stage(i);
|
||||||
_glgsg->apply_white_texture();
|
_glgsg->apply_white_texture();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1115,7 +1115,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
_glgsg->set_active_texture_stage(texunit);
|
||||||
|
|
||||||
TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg);
|
TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg);
|
||||||
if (tc == (TextureContext*)NULL) {
|
if (tc == (TextureContext*)NULL) {
|
||||||
|
@ -288,6 +288,23 @@ set_vertex_attrib_divisor(GLuint index, GLuint divisor) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GLGraphicsStateGuardian::set_active_texture_stage
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Calls glActiveTexture.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void CLP(GraphicsStateGuardian)::
|
||||||
|
set_active_texture_stage(int i) {
|
||||||
|
if (i != _active_texture_stage) {
|
||||||
|
#ifdef OPENGLES_2
|
||||||
|
glActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
#else
|
||||||
|
_glActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
#endif
|
||||||
|
_active_texture_stage = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GLGraphicsStateGuardian::enable_multisample_antialias
|
// Function: GLGraphicsStateGuardian::enable_multisample_antialias
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
|
@ -1086,9 +1086,7 @@ reset() {
|
|||||||
has_extension("GL_ARB_texture_non_power_of_two");
|
has_extension("GL_ARB_texture_non_power_of_two");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OPENGLES_2
|
#ifndef OPENGLES_2
|
||||||
_glActiveTexture = glActiveTexture;
|
|
||||||
#else
|
|
||||||
bool supports_multitexture = false;
|
bool supports_multitexture = false;
|
||||||
if (is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1)) {
|
if (is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1)) {
|
||||||
supports_multitexture = true;
|
supports_multitexture = true;
|
||||||
@ -1641,6 +1639,28 @@ reset() {
|
|||||||
_glVertexAttribLPointer = NULL;
|
_glVertexAttribLPointer = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
_use_vertex_attrib_binding = false;
|
||||||
|
if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_vertex_attrib_binding")) {
|
||||||
|
_glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)
|
||||||
|
get_extension_func("glBindVertexBuffer");
|
||||||
|
_glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)
|
||||||
|
get_extension_func("glVertexAttribFormat");
|
||||||
|
_glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)
|
||||||
|
get_extension_func("glVertexAttribIFormat");
|
||||||
|
_glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)
|
||||||
|
get_extension_func("glVertexAttribLFormat");
|
||||||
|
_glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)
|
||||||
|
get_extension_func("glVertexAttribBinding");
|
||||||
|
_glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)
|
||||||
|
get_extension_func("glVertexBindingDivisor");
|
||||||
|
|
||||||
|
if (gl_fixed_vertex_attrib_locations) {
|
||||||
|
_use_vertex_attrib_binding = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We need to have a default shader to apply in case
|
// We need to have a default shader to apply in case
|
||||||
// something didn't happen to have a shader applied, or
|
// something didn't happen to have a shader applied, or
|
||||||
// if it failed to compile. This default shader just outputs
|
// if it failed to compile. This default shader just outputs
|
||||||
@ -2344,6 +2364,7 @@ reset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_active_texture_stage = -1;
|
||||||
_num_active_texture_stages = 0;
|
_num_active_texture_stages = 0;
|
||||||
|
|
||||||
// Check availability of anisotropic texture filtering.
|
// Check availability of anisotropic texture filtering.
|
||||||
@ -2407,18 +2428,22 @@ reset() {
|
|||||||
|
|
||||||
// Check availability of multi-bind functions.
|
// Check availability of multi-bind functions.
|
||||||
_supports_multi_bind = false;
|
_supports_multi_bind = false;
|
||||||
|
#ifndef OPENGLES
|
||||||
if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_multi_bind")) {
|
if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_multi_bind")) {
|
||||||
_glBindTextures = (PFNGLBINDTEXTURESPROC)
|
_glBindTextures = (PFNGLBINDTEXTURESPROC)
|
||||||
get_extension_func("glBindTextures");
|
get_extension_func("glBindTextures");
|
||||||
_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)
|
_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)
|
||||||
get_extension_func("glBindImageTextures");
|
get_extension_func("glBindImageTextures");
|
||||||
|
|
||||||
#ifndef OPENGLES
|
|
||||||
if (_supports_sampler_objects) {
|
if (_supports_sampler_objects) {
|
||||||
_glBindSamplers = (PFNGLBINDSAMPLERSPROC)
|
_glBindSamplers = (PFNGLBINDSAMPLERSPROC)
|
||||||
get_extension_func("glBindSamplers");
|
get_extension_func("glBindSamplers");
|
||||||
}
|
}
|
||||||
#endif // OPENGLES
|
|
||||||
|
if (_use_vertex_attrib_binding) {
|
||||||
|
_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)
|
||||||
|
get_extension_func("glBindVertexBuffers");
|
||||||
|
}
|
||||||
|
|
||||||
if (_glBindTextures != NULL && _glBindImageTextures != NULL) {
|
if (_glBindTextures != NULL && _glBindImageTextures != NULL) {
|
||||||
_supports_multi_bind = true;
|
_supports_multi_bind = true;
|
||||||
@ -2427,6 +2452,7 @@ reset() {
|
|||||||
<< "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n";
|
<< "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // OPENGLES
|
||||||
|
|
||||||
if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_internalformat_query2")) {
|
if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_internalformat_query2")) {
|
||||||
_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)
|
_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)
|
||||||
@ -2616,6 +2642,12 @@ reset() {
|
|||||||
_point_size = 1.0f;
|
_point_size = 1.0f;
|
||||||
_point_perspective = false;
|
_point_perspective = false;
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
_current_vertex_buffers.clear();
|
||||||
|
_current_vertex_format.clear();
|
||||||
|
memset(_vertex_attrib_columns, 0, sizeof(const GeomVertexColumn *) * 32);
|
||||||
|
#endif
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
|
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
@ -3108,7 +3140,7 @@ clear_before_callback() {
|
|||||||
// Some callbacks may quite reasonably assume that the active
|
// Some callbacks may quite reasonably assume that the active
|
||||||
// texture stage is still set to stage 0. CEGUI, in particular,
|
// texture stage is still set to stage 0. CEGUI, in particular,
|
||||||
// makes this assumption.
|
// makes this assumption.
|
||||||
_glActiveTexture(GL_TEXTURE0);
|
set_active_texture_stage(0);
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
_glClientActiveTexture(GL_TEXTURE0);
|
_glClientActiveTexture(GL_TEXTURE0);
|
||||||
#endif
|
#endif
|
||||||
@ -3375,6 +3407,9 @@ end_frame(Thread *current_thread) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Respecify the active texture next frame, for good measure.
|
||||||
|
_active_texture_stage = -1;
|
||||||
|
|
||||||
// Calling glFlush() at the end of the frame is particularly
|
// Calling glFlush() at the end of the frame is particularly
|
||||||
// necessary if this is a single-buffered visual, so that the frame
|
// necessary if this is a single-buffered visual, so that the frame
|
||||||
// will be finished drawing before we return to the application.
|
// will be finished drawing before we return to the application.
|
||||||
@ -3636,6 +3671,15 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
|
|||||||
_use_sender = !vertex_arrays;
|
_use_sender = !vertex_arrays;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
if (_use_vertex_attrib_binding) {
|
||||||
|
const GeomVertexFormat *format = data_reader->get_format();
|
||||||
|
if (format != _current_vertex_format) {
|
||||||
|
update_shader_vertex_format(format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
//PStatGPUTimer timer(this, _vertex_array_update_pcollector);
|
//PStatGPUTimer timer(this, _vertex_array_update_pcollector);
|
||||||
#ifdef OPENGLES_1
|
#ifdef OPENGLES_1
|
||||||
@ -3908,42 +3952,97 @@ unbind_buffers() {
|
|||||||
_current_ibuffer_index = 0;
|
_current_ibuffer_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
if (_current_vertex_buffers.size() > 1 && _supports_multi_bind) {
|
||||||
|
_glBindVertexBuffers(0, _current_vertex_buffers.size(), NULL, NULL, NULL);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < _current_vertex_buffers.size(); ++i) {
|
||||||
|
if (_current_vertex_buffers[i] != 0) {
|
||||||
|
_glBindVertexBuffer(i, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_current_vertex_buffers.clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
disable_standard_vertex_arrays();
|
disable_standard_vertex_arrays();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifndef OPENGLES
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GLGraphicsStateGuardian::disable_standard_vertex_arrays
|
// Function: GLGraphicsStateGuardian::update_shader_vertex_format
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
// Description: Used to disable all the standard vertex arrays that
|
// Description: Updates the vertex format used by the shader. This
|
||||||
// are currently enabled. glShaderContexts are
|
// is still an experimental feature.
|
||||||
// responsible for setting up their own vertex arrays,
|
|
||||||
// but before they can do so, the standard vertex
|
|
||||||
// arrays need to be disabled to get them "out of the
|
|
||||||
// way." Called only from begin_draw_primitives.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void CLP(GraphicsStateGuardian)::
|
void CLP(GraphicsStateGuardian)::
|
||||||
disable_standard_vertex_arrays() {
|
update_shader_vertex_format(const GeomVertexFormat *format) {
|
||||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
size_t num_columns = format->get_num_columns();
|
||||||
if (_use_sender) return;
|
for (size_t ci = 0; ci < num_columns; ++ci) {
|
||||||
#endif
|
GLuint binding = format->get_array_with(ci);
|
||||||
|
const GeomVertexColumn *column = format->get_column(ci);
|
||||||
|
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
// Needs improvement, obviously.
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
const InternalName *name = column->get_name();
|
||||||
GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f);
|
GLuint loc;
|
||||||
|
if (name == InternalName::get_vertex()) {
|
||||||
|
loc = 0;
|
||||||
|
} else if (name == InternalName::get_transform_weight()) {
|
||||||
|
loc = 1;
|
||||||
|
} else if (name == InternalName::get_normal()) {
|
||||||
|
loc = 2;
|
||||||
|
} else if (name == InternalName::get_color()) {
|
||||||
|
loc = 3;
|
||||||
|
} else if (name == InternalName::get_transform_index()) {
|
||||||
|
loc = 7;
|
||||||
|
} else if (name == InternalName::get_texcoord()) {
|
||||||
|
loc = 8;
|
||||||
|
} else {
|
||||||
|
// Not yet supported, ignore for now. This system will be improved.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int stage_index=0; stage_index < _last_max_stage_index; stage_index++) {
|
if (_vertex_attrib_columns[loc] != NULL &&
|
||||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
_vertex_attrib_columns[loc]->compare_to(*column) == 0) {
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
continue;
|
||||||
|
}
|
||||||
|
_vertex_attrib_columns[loc] = column;
|
||||||
|
|
||||||
|
GLuint offset = column->get_start();
|
||||||
|
GLenum type = get_numeric_type(column->get_numeric_type());
|
||||||
|
GLboolean normalized = (column->get_contents() == GeomEnums::C_color);
|
||||||
|
GLint size = column->get_num_values();
|
||||||
|
|
||||||
|
if (column->get_numeric_type() == GeomEnums::NT_packed_dabc) {
|
||||||
|
// GL_BGRA is a special accepted value available since OpenGL 3.2.
|
||||||
|
// It requires us to pass GL_TRUE for normalized.
|
||||||
|
size = GL_BGRA;
|
||||||
|
normalized = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < column->get_num_elements(); ++i) {
|
||||||
|
if (loc == 7) { // Temp hack
|
||||||
|
_glVertexAttribIFormat(loc, size, type, offset);
|
||||||
|
} else {
|
||||||
|
_glVertexAttribFormat(loc, size, type, normalized, offset);
|
||||||
|
}
|
||||||
|
_glVertexAttribBinding(loc, binding);
|
||||||
|
|
||||||
|
offset += column->get_element_stride();
|
||||||
|
++loc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_last_max_stage_index = 0;
|
|
||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
size_t num_arrays = format->get_num_arrays();
|
||||||
report_my_gl_errors();
|
for (size_t ai = 0; ai < num_arrays; ++ai) {
|
||||||
|
_glVertexBindingDivisor(ai, format->get_array(ai)->get_divisor());
|
||||||
|
}
|
||||||
|
|
||||||
|
_current_vertex_format = format;
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_FIXED_FUNCTION
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GLGraphicsStateGuardian::draw_triangles
|
// Function: GLGraphicsStateGuardian::draw_triangles
|
||||||
@ -5112,7 +5211,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
apply_vertex_buffer(gvbc, data->get_handle(), false);
|
update_vertex_buffer(gvbc, data->get_handle(), false);
|
||||||
return gvbc;
|
return gvbc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5120,31 +5219,22 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GLGraphicsStateGuardian::apply_vertex_buffer
|
// Function: GLGraphicsStateGuardian::update_vertex_buffer
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Makes the data the currently available data for
|
// Description: Makes sure that the data in the vertex buffer is
|
||||||
// rendering.
|
// up-to-date. This may bind it to the GL_ARRAY_BUFFER
|
||||||
|
// binding point if necessary.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool CLP(GraphicsStateGuardian)::
|
bool CLP(GraphicsStateGuardian)::
|
||||||
apply_vertex_buffer(VertexBufferContext *vbc,
|
update_vertex_buffer(CLP(VertexBufferContext) *gvbc,
|
||||||
const GeomVertexArrayDataHandle *reader, bool force) {
|
const GeomVertexArrayDataHandle *reader, bool force) {
|
||||||
nassertr(_supports_buffers, false);
|
nassertr(_supports_buffers, false);
|
||||||
if (reader->get_modified() == UpdateSeq::initial()) {
|
if (reader->get_modified() == UpdateSeq::initial()) {
|
||||||
// No need to re-apply.
|
// No need to re-apply.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
|
gvbc->set_active(true);
|
||||||
|
|
||||||
if (_current_vbuffer_index != gvbc->_index) {
|
|
||||||
if (GLCAT.is_spam() && gl_debug_buffers) {
|
|
||||||
GLCAT.spam()
|
|
||||||
<< "binding vertex buffer " << (int)gvbc->_index << "\n";
|
|
||||||
}
|
|
||||||
_glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
|
|
||||||
_current_vbuffer_index = gvbc->_index;
|
|
||||||
gvbc->set_active(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gvbc->was_modified(reader)) {
|
if (gvbc->was_modified(reader)) {
|
||||||
int num_bytes = reader->get_data_size_bytes();
|
int num_bytes = reader->get_data_size_bytes();
|
||||||
@ -5160,6 +5250,15 @@ apply_vertex_buffer(VertexBufferContext *vbc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
PStatGPUTimer timer(this, _load_vertex_buffer_pcollector, reader->get_current_thread());
|
PStatGPUTimer timer(this, _load_vertex_buffer_pcollector, reader->get_current_thread());
|
||||||
|
if (_current_vbuffer_index != gvbc->_index) {
|
||||||
|
if (GLCAT.is_spam() && gl_debug_buffers) {
|
||||||
|
GLCAT.spam()
|
||||||
|
<< "binding vertex buffer " << (int)gvbc->_index << "\n";
|
||||||
|
}
|
||||||
|
_glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
|
||||||
|
_current_vbuffer_index = gvbc->_index;
|
||||||
|
}
|
||||||
|
|
||||||
if (gvbc->changed_size(reader) || gvbc->changed_usage_hint(reader)) {
|
if (gvbc->changed_size(reader) || gvbc->changed_usage_hint(reader)) {
|
||||||
_glBufferData(GL_ARRAY_BUFFER, num_bytes, client_pointer,
|
_glBufferData(GL_ARRAY_BUFFER, num_bytes, client_pointer,
|
||||||
get_usage(reader->get_usage_hint()));
|
get_usage(reader->get_usage_hint()));
|
||||||
@ -5263,12 +5362,23 @@ setup_array_data(const unsigned char *&client_pointer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the buffer object and bind it.
|
// Prepare the buffer object and bind it.
|
||||||
VertexBufferContext *vbc = array_reader->prepare_now(get_prepared_objects(), this);
|
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext),
|
||||||
nassertr(vbc != (VertexBufferContext *)NULL, false);
|
array_reader->prepare_now(get_prepared_objects(), this));
|
||||||
if (!apply_vertex_buffer(vbc, array_reader, force)) {
|
|
||||||
|
nassertr(gvbc != (CLP(VertexBufferContext) *)NULL, false);
|
||||||
|
if (!update_vertex_buffer(gvbc, array_reader, force)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_current_vbuffer_index != gvbc->_index) {
|
||||||
|
if (GLCAT.is_spam() && gl_debug_buffers) {
|
||||||
|
GLCAT.spam()
|
||||||
|
<< "binding vertex buffer " << (int)gvbc->_index << "\n";
|
||||||
|
}
|
||||||
|
_glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
|
||||||
|
_current_vbuffer_index = gvbc->_index;
|
||||||
|
}
|
||||||
|
|
||||||
// NULL is the OpenGL convention for the first byte of the buffer object.
|
// NULL is the OpenGL convention for the first byte of the buffer object.
|
||||||
client_pointer = NULL;
|
client_pointer = NULL;
|
||||||
return true;
|
return true;
|
||||||
@ -9316,6 +9426,14 @@ void CLP(GraphicsStateGuardian)::
|
|||||||
reissue_transforms() {
|
reissue_transforms() {
|
||||||
prepare_lens();
|
prepare_lens();
|
||||||
do_issue_transform();
|
do_issue_transform();
|
||||||
|
|
||||||
|
_active_texture_stage = -1;
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
// Might also want to reissue the vertex format, for good measure.
|
||||||
|
_current_vertex_format.clear();
|
||||||
|
memset(_vertex_attrib_columns, 0, sizeof(const GeomVertexColumn *) * 32);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
@ -9592,7 +9710,7 @@ set_state_and_transform(const RenderState *target,
|
|||||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||||
}
|
}
|
||||||
#ifndef SUPPORT_FIXED_FUNCTION
|
#ifndef SUPPORT_FIXED_FUNCTION
|
||||||
else { // In the case of OpenGL ES 2.x, we need to glUseShader before we draw anything.
|
else if (_current_shader == NULL) { // In the case of OpenGL ES 2.x, we need to glUseShader before we draw anything.
|
||||||
do_issue_shader();
|
do_issue_shader();
|
||||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||||
}
|
}
|
||||||
@ -9945,7 +10063,7 @@ update_standard_texture_bindings() {
|
|||||||
nassertv(texture != (Texture *)NULL);
|
nassertv(texture != (Texture *)NULL);
|
||||||
|
|
||||||
// Issue the texture on stage i.
|
// Issue the texture on stage i.
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
|
|
||||||
// First, turn off the previous texture mode.
|
// First, turn off the previous texture mode.
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
@ -10114,7 +10232,7 @@ update_standard_texture_bindings() {
|
|||||||
|
|
||||||
// Disable the texture stages that are no longer used.
|
// Disable the texture stages that are no longer used.
|
||||||
for (i = num_stages; i < _num_active_texture_stages; i++) {
|
for (i = num_stages; i < _num_active_texture_stages; i++) {
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
if (_supports_cube_map) {
|
if (_supports_cube_map) {
|
||||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||||
@ -10217,7 +10335,7 @@ update_show_usage_texture_bindings(int show_stage_index) {
|
|||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
// Disable all texture stages.
|
// Disable all texture stages.
|
||||||
for (i = 0; i < _num_active_texture_stages; i++) {
|
for (i = 0; i < _num_active_texture_stages; i++) {
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
glDisable(GL_TEXTURE_1D);
|
glDisable(GL_TEXTURE_1D);
|
||||||
#endif // OPENGLES
|
#endif // OPENGLES
|
||||||
@ -10249,7 +10367,7 @@ update_show_usage_texture_bindings(int show_stage_index) {
|
|||||||
nassertv(texture != (Texture *)NULL);
|
nassertv(texture != (Texture *)NULL);
|
||||||
|
|
||||||
// Choose the corresponding usage texture and apply it.
|
// Choose the corresponding usage texture and apply it.
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
#endif
|
#endif
|
||||||
@ -10366,7 +10484,7 @@ void CLP(GraphicsStateGuardian)::
|
|||||||
disable_standard_texture_bindings() {
|
disable_standard_texture_bindings() {
|
||||||
// Disable the texture stages that are no longer used.
|
// Disable the texture stages that are no longer used.
|
||||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
glDisable(GL_TEXTURE_1D);
|
glDisable(GL_TEXTURE_1D);
|
||||||
#endif // OPENGLES
|
#endif // OPENGLES
|
||||||
@ -10399,7 +10517,7 @@ do_issue_tex_matrix() {
|
|||||||
|
|
||||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||||
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
glMatrixMode(GL_TEXTURE);
|
||||||
|
|
||||||
@ -10452,7 +10570,7 @@ do_issue_tex_gen() {
|
|||||||
|
|
||||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||||
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
||||||
_glActiveTexture(GL_TEXTURE0 + i);
|
set_active_texture_stage(i);
|
||||||
if (_supports_point_sprite) {
|
if (_supports_point_sprite) {
|
||||||
#ifdef OPENGLES
|
#ifdef OPENGLES
|
||||||
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE);
|
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE);
|
||||||
@ -10909,7 +11027,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc
|
|||||||
// We don't support sampler objects. We'll have to bind the
|
// We don't support sampler objects. We'll have to bind the
|
||||||
// texture and change the texture parameters if they don't match.
|
// texture and change the texture parameters if they don't match.
|
||||||
if (gtc->_active_sampler != sampler) {
|
if (gtc->_active_sampler != sampler) {
|
||||||
_glActiveTexture(GL_TEXTURE0 + unit);
|
set_active_texture_stage(unit);
|
||||||
apply_texture(gtc);
|
apply_texture(gtc);
|
||||||
specify_texture(gtc, sampler);
|
specify_texture(gtc, sampler);
|
||||||
}
|
}
|
||||||
|
@ -306,9 +306,9 @@ public:
|
|||||||
void record_deleted_display_list(GLuint index);
|
void record_deleted_display_list(GLuint index);
|
||||||
|
|
||||||
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
|
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
|
||||||
bool apply_vertex_buffer(VertexBufferContext *vbc,
|
bool update_vertex_buffer(CLP(VertexBufferContext) *gvbc,
|
||||||
const GeomVertexArrayDataHandle *reader,
|
const GeomVertexArrayDataHandle *reader,
|
||||||
bool force);
|
bool force);
|
||||||
virtual void release_vertex_buffer(VertexBufferContext *vbc);
|
virtual void release_vertex_buffer(VertexBufferContext *vbc);
|
||||||
|
|
||||||
bool setup_array_data(const unsigned char *&client_pointer,
|
bool setup_array_data(const unsigned char *&client_pointer,
|
||||||
@ -457,6 +457,8 @@ protected:
|
|||||||
INLINE void set_vertex_attrib_divisor(GLuint index, GLuint divisor);
|
INLINE void set_vertex_attrib_divisor(GLuint index, GLuint divisor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
INLINE void set_active_texture_stage(int i);
|
||||||
|
|
||||||
INLINE void enable_multisample_antialias(bool val);
|
INLINE void enable_multisample_antialias(bool val);
|
||||||
INLINE void enable_multisample_alpha_one(bool val);
|
INLINE void enable_multisample_alpha_one(bool val);
|
||||||
INLINE void enable_multisample_alpha_mask(bool val);
|
INLINE void enable_multisample_alpha_mask(bool val);
|
||||||
@ -533,6 +535,9 @@ protected:
|
|||||||
void disable_standard_texture_bindings();
|
void disable_standard_texture_bindings();
|
||||||
void update_standard_texture_bindings();
|
void update_standard_texture_bindings();
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef OPENGLES
|
||||||
|
void update_shader_vertex_format(const GeomVertexFormat *format);
|
||||||
|
#endif
|
||||||
|
|
||||||
void apply_white_texture();
|
void apply_white_texture();
|
||||||
GLuint get_white_texture();
|
GLuint get_white_texture();
|
||||||
@ -651,6 +656,15 @@ protected:
|
|||||||
GLuint _current_vbuffer_index;
|
GLuint _current_vbuffer_index;
|
||||||
GLuint _current_ibuffer_index;
|
GLuint _current_ibuffer_index;
|
||||||
GLuint _current_fbo;
|
GLuint _current_fbo;
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
pvector<GLuint> _current_vertex_buffers;
|
||||||
|
bool _use_vertex_attrib_binding;
|
||||||
|
CPT(GeomVertexFormat) _current_vertex_format;
|
||||||
|
const GeomVertexColumn *_vertex_attrib_columns[32];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int _active_texture_stage;
|
||||||
int _num_active_texture_stages;
|
int _num_active_texture_stages;
|
||||||
PN_stdfloat _max_anisotropy;
|
PN_stdfloat _max_anisotropy;
|
||||||
bool _supports_anisotropy;
|
bool _supports_anisotropy;
|
||||||
@ -735,7 +749,9 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENGLES_2
|
||||||
PFNGLACTIVETEXTUREPROC _glActiveTexture;
|
PFNGLACTIVETEXTUREPROC _glActiveTexture;
|
||||||
|
#endif
|
||||||
#ifdef SUPPORT_FIXED_FUNCTION
|
#ifdef SUPPORT_FIXED_FUNCTION
|
||||||
PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
|
PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
|
||||||
#endif
|
#endif
|
||||||
@ -897,6 +913,13 @@ public:
|
|||||||
PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
|
PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
|
||||||
#endif // !OPENGLES_1
|
#endif // !OPENGLES_1
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
|
PFNGLBINDVERTEXBUFFERPROC _glBindVertexBuffer;
|
||||||
|
PFNGLBINDVERTEXBUFFERSPROC _glBindVertexBuffers;
|
||||||
|
PFNGLVERTEXATTRIBFORMATPROC _glVertexAttribFormat;
|
||||||
|
PFNGLVERTEXATTRIBIFORMATPROC _glVertexAttribIFormat;
|
||||||
|
PFNGLVERTEXATTRIBLFORMATPROC _glVertexAttribLFormat;
|
||||||
|
PFNGLVERTEXATTRIBBINDINGPROC _glVertexAttribBinding;
|
||||||
|
PFNGLVERTEXBINDINGDIVISORPROC _glVertexBindingDivisor;
|
||||||
PFNGLGETACTIVEUNIFORMSIVPROC _glGetActiveUniformsiv;
|
PFNGLGETACTIVEUNIFORMSIVPROC _glGetActiveUniformsiv;
|
||||||
PFNGLGETACTIVEUNIFORMBLOCKIVPROC _glGetActiveUniformBlockiv;
|
PFNGLGETACTIVEUNIFORMBLOCKIVPROC _glGetActiveUniformBlockiv;
|
||||||
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC _glGetActiveUniformBlockName;
|
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC _glGetActiveUniformBlockName;
|
||||||
|
@ -262,6 +262,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
|||||||
_glgsg = glgsg;
|
_glgsg = glgsg;
|
||||||
_glsl_program = 0;
|
_glsl_program = 0;
|
||||||
_uses_standard_vertex_arrays = false;
|
_uses_standard_vertex_arrays = false;
|
||||||
|
_enabled_attribs.clear();
|
||||||
_color_attrib_index = -1;
|
_color_attrib_index = -1;
|
||||||
_transform_table_index = -1;
|
_transform_table_index = -1;
|
||||||
_slider_table_index = -1;
|
_slider_table_index = -1;
|
||||||
@ -279,13 +280,31 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a buffer the size of the longest uniform name. Note
|
// Process the vertex attributes first.
|
||||||
// that Intel HD drivers report values that are too low.
|
GLint param_count = 0;
|
||||||
GLint name_buflen = 0;
|
GLint name_buflen = 0;
|
||||||
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &name_buflen);
|
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count);
|
||||||
|
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_buflen);
|
||||||
name_buflen = max(64, name_buflen);
|
name_buflen = max(64, name_buflen);
|
||||||
char *name_buffer = (char *)alloca(name_buflen);
|
char *name_buffer = (char *)alloca(name_buflen);
|
||||||
|
|
||||||
|
_shader->_var_spec.clear();
|
||||||
|
for (int i = 0; i < param_count; ++i) {
|
||||||
|
reflect_attribute(i, name_buffer, name_buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (gl_fixed_vertex_attrib_locations) {
|
||||||
|
// Relink the shader for glBindAttribLocation to take effect.
|
||||||
|
_glgsg->_glLinkProgram(_glsl_program);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Create a buffer the size of the longest uniform name. Note
|
||||||
|
// that Intel HD drivers report values that are too low.
|
||||||
|
name_buflen = 0;
|
||||||
|
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &name_buflen);
|
||||||
|
name_buflen = max(64, name_buflen);
|
||||||
|
name_buffer = (char *)alloca(name_buflen);
|
||||||
|
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
// Get the used uniform blocks.
|
// Get the used uniform blocks.
|
||||||
if (_glgsg->_supports_uniform_buffers) {
|
if (_glgsg->_supports_uniform_buffers) {
|
||||||
@ -316,7 +335,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
|||||||
_glgsg->_glUseProgram(_glsl_program);
|
_glgsg->_glUseProgram(_glsl_program);
|
||||||
|
|
||||||
// Analyze the uniforms.
|
// Analyze the uniforms.
|
||||||
GLint param_count = 0;
|
param_count = 0;
|
||||||
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count);
|
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count);
|
||||||
|
|
||||||
_shader->_ptr_spec.clear();
|
_shader->_ptr_spec.clear();
|
||||||
@ -326,17 +345,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
|||||||
reflect_uniform(i, name_buffer, name_buflen);
|
reflect_uniform(i, name_buffer, name_buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we've processed the uniforms, we'll process the attribs.
|
|
||||||
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count);
|
|
||||||
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_buflen);
|
|
||||||
name_buflen = max(64, name_buflen);
|
|
||||||
name_buffer = (char *)alloca(name_buflen);
|
|
||||||
|
|
||||||
_shader->_var_spec.clear();
|
|
||||||
for (int i = 0; i < param_count; ++i) {
|
|
||||||
reflect_attribute(i, name_buffer, name_buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glgsg->report_my_gl_errors();
|
_glgsg->report_my_gl_errors();
|
||||||
|
|
||||||
// Restore the active shader.
|
// Restore the active shader.
|
||||||
@ -470,6 +478,37 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Experimental feature.
|
||||||
|
if (gl_fixed_vertex_attrib_locations) {
|
||||||
|
GLint loc;
|
||||||
|
if (bind._name == InternalName::get_vertex()) {
|
||||||
|
loc = 0;
|
||||||
|
} else if (bind._name == InternalName::get_transform_weight()) {
|
||||||
|
loc = 1;
|
||||||
|
} else if (bind._name == InternalName::get_normal()) {
|
||||||
|
loc = 2;
|
||||||
|
} else if (bind._name == InternalName::get_color()) {
|
||||||
|
loc = 3;
|
||||||
|
} else if (bind._name == InternalName::get_transform_index()) {
|
||||||
|
loc = 7;
|
||||||
|
} else if (bind._name == InternalName::get_texcoord() &&
|
||||||
|
bind._append_uv >= 0 && bind._append_uv < 8) {
|
||||||
|
loc = 8 + bind._append_uv;
|
||||||
|
} else {
|
||||||
|
GLCAT.error()
|
||||||
|
<< "Vertex attrib '" << name_buffer << "' not yet supported with "
|
||||||
|
"gl-fixed-vertex-attrib-locations!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (loc != p) {
|
||||||
|
GLCAT.error()
|
||||||
|
<< "Vertex attrib '" << name_buffer << "' was bound to the wrong slot!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//_glgsg->_glBindAttribLocation(_glsl_program, loc, name_buffer);
|
||||||
|
_enabled_attribs.set_range(loc, bind._elements);
|
||||||
|
}
|
||||||
|
|
||||||
_shader->_var_spec.push_back(bind);
|
_shader->_var_spec.push_back(bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2045,91 +2084,152 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
|||||||
_state_rs->get_attrib_def(color_attrib);
|
_state_rs->get_attrib_def(color_attrib);
|
||||||
|
|
||||||
const GeomVertexArrayDataHandle *array_reader;
|
const GeomVertexArrayDataHandle *array_reader;
|
||||||
Geom::NumericType numeric_type;
|
|
||||||
int start, stride, num_values;
|
|
||||||
size_t nvarying = _shader->_var_spec.size();
|
|
||||||
|
|
||||||
GLuint max_p = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nvarying; ++i) {
|
|
||||||
const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
|
|
||||||
InternalName *name = bind._name;
|
|
||||||
int texslot = bind._append_uv;
|
|
||||||
|
|
||||||
if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) {
|
|
||||||
TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot);
|
|
||||||
InternalName *texname = stage->get_texcoord_name();
|
|
||||||
|
|
||||||
if (name == InternalName::get_texcoord()) {
|
|
||||||
name = texname;
|
|
||||||
} else if (texname != InternalName::get_texcoord()) {
|
|
||||||
name = name->append(texname->get_basename());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint p = bind._id._seqno;
|
|
||||||
max_p = max(max_p, p + 1);
|
|
||||||
|
|
||||||
// Don't apply vertex colors if they are disabled with a ColorAttrib.
|
|
||||||
int num_elements, element_stride, divisor;
|
|
||||||
bool normalized;
|
|
||||||
if ((p != _color_attrib_index || color_attrib->get_type() == ColorAttrib::T_vertex) &&
|
|
||||||
_glgsg->_data_reader->get_array_info(name, array_reader,
|
|
||||||
num_values, numeric_type,
|
|
||||||
normalized, start, stride, divisor,
|
|
||||||
num_elements, element_stride)) {
|
|
||||||
const unsigned char *client_pointer;
|
|
||||||
if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
client_pointer += start;
|
|
||||||
|
|
||||||
for (int i = 0; i < num_elements; ++i) {
|
|
||||||
_glgsg->enable_vertex_attrib_array(p);
|
|
||||||
|
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
if (bind._integer) {
|
if (_glgsg->_use_vertex_attrib_binding) {
|
||||||
_glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
|
// Use experimental new separated format/binding state.
|
||||||
stride, client_pointer);
|
const GeomVertexDataPipelineReader *data_reader = _glgsg->_data_reader;
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (numeric_type == GeomEnums::NT_packed_dabc) {
|
|
||||||
// GL_BGRA is a special accepted value available since OpenGL 3.2.
|
|
||||||
// It requires us to pass GL_TRUE for normalized.
|
|
||||||
_glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
|
|
||||||
GL_TRUE, stride, client_pointer);
|
|
||||||
} else {
|
|
||||||
_glgsg->_glVertexAttribPointer(p, num_values,
|
|
||||||
_glgsg->get_numeric_type(numeric_type),
|
|
||||||
normalized, stride, client_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (divisor > 0) {
|
for (int ai = 0; ai < data_reader->get_num_arrays(); ++ai) {
|
||||||
_glgsg->set_vertex_attrib_divisor(p, divisor);
|
array_reader = data_reader->get_array_reader(ai);
|
||||||
}
|
|
||||||
|
|
||||||
++p;
|
// Make sure the vertex buffer is up-to-date.
|
||||||
client_pointer += element_stride;
|
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext),
|
||||||
|
array_reader->prepare_now(_glgsg->get_prepared_objects(), _glgsg));
|
||||||
|
nassertr(gvbc != (CLP(VertexBufferContext) *)NULL, false);
|
||||||
|
|
||||||
|
if (!_glgsg->update_vertex_buffer(gvbc, array_reader, force)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (int i = 0; i < bind._elements; ++i) {
|
GLintptr stride = array_reader->get_array_format()->get_stride();
|
||||||
_glgsg->disable_vertex_attrib_array(p + i);
|
|
||||||
|
// Bind the vertex buffer to the binding index.
|
||||||
|
if (ai >= _glgsg->_current_vertex_buffers.size()) {
|
||||||
|
_glgsg->_current_vertex_buffers.resize(ai + 1, 0);
|
||||||
}
|
}
|
||||||
if (p == _color_attrib_index) {
|
if (_glgsg->_current_vertex_buffers[ai] != gvbc->_index) {
|
||||||
// Vertex colors are disabled or not present. Apply flat color.
|
_glgsg->_glBindVertexBuffer(ai, gvbc->_index, 0, stride);
|
||||||
#ifdef STDFLOAT_DOUBLE
|
_glgsg->_current_vertex_buffers[ai] = gvbc->_index;
|
||||||
_glgsg->_glVertexAttrib4dv(p, color_attrib->get_color().get_data());
|
|
||||||
#else
|
|
||||||
_glgsg->_glVertexAttrib4fv(p, color_attrib->get_color().get_data());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Disable attribute arrays we don't use.
|
// Figure out which attributes to enable or disable.
|
||||||
GLint highest_p = _glgsg->_enabled_vertex_attrib_arrays.get_highest_on_bit() + 1;
|
BitMask32 enabled_attribs = _enabled_attribs;
|
||||||
for (GLint p = max_p; p < highest_p; ++p) {
|
if (_color_attrib_index != -1 &&
|
||||||
_glgsg->disable_vertex_attrib_array(p);
|
color_attrib->get_type() != ColorAttrib::T_vertex) {
|
||||||
|
// Vertex colours are disabled.
|
||||||
|
enabled_attribs.clear_bit(_color_attrib_index);
|
||||||
|
|
||||||
|
#ifdef STDFLOAT_DOUBLE
|
||||||
|
_glgsg->_glVertexAttrib4dv(_color_attrib_index, color_attrib->get_color().get_data());
|
||||||
|
#else
|
||||||
|
_glgsg->_glVertexAttrib4fv(_color_attrib_index, color_attrib->get_color().get_data());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BitMask32 changed_attribs = enabled_attribs ^ _glgsg->_enabled_vertex_attrib_arrays;
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; ++i) {
|
||||||
|
if (changed_attribs.get_bit(i)) {
|
||||||
|
if (enabled_attribs.get_bit(i)) {
|
||||||
|
_glgsg->_glEnableVertexAttribArray(i);
|
||||||
|
} else {
|
||||||
|
_glgsg->_glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_glgsg->_enabled_vertex_attrib_arrays = enabled_attribs;
|
||||||
|
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Geom::NumericType numeric_type;
|
||||||
|
int start, stride, num_values;
|
||||||
|
size_t nvarying = _shader->_var_spec.size();
|
||||||
|
|
||||||
|
GLuint max_p = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nvarying; ++i) {
|
||||||
|
const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
|
||||||
|
InternalName *name = bind._name;
|
||||||
|
int texslot = bind._append_uv;
|
||||||
|
|
||||||
|
if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) {
|
||||||
|
TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot);
|
||||||
|
InternalName *texname = stage->get_texcoord_name();
|
||||||
|
|
||||||
|
if (name == InternalName::get_texcoord()) {
|
||||||
|
name = texname;
|
||||||
|
} else if (texname != InternalName::get_texcoord()) {
|
||||||
|
name = name->append(texname->get_basename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint p = bind._id._seqno;
|
||||||
|
max_p = max(max_p, p + 1);
|
||||||
|
|
||||||
|
// Don't apply vertex colors if they are disabled with a ColorAttrib.
|
||||||
|
int num_elements, element_stride, divisor;
|
||||||
|
bool normalized;
|
||||||
|
if ((p != _color_attrib_index || color_attrib->get_type() == ColorAttrib::T_vertex) &&
|
||||||
|
_glgsg->_data_reader->get_array_info(name, array_reader,
|
||||||
|
num_values, numeric_type,
|
||||||
|
normalized, start, stride, divisor,
|
||||||
|
num_elements, element_stride)) {
|
||||||
|
const unsigned char *client_pointer;
|
||||||
|
if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
client_pointer += start;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_elements; ++i) {
|
||||||
|
_glgsg->enable_vertex_attrib_array(p);
|
||||||
|
|
||||||
|
#ifndef OPENGLES
|
||||||
|
if (bind._integer) {
|
||||||
|
_glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
|
||||||
|
stride, client_pointer);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (numeric_type == GeomEnums::NT_packed_dabc) {
|
||||||
|
// GL_BGRA is a special accepted value available since OpenGL 3.2.
|
||||||
|
// It requires us to pass GL_TRUE for normalized.
|
||||||
|
_glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
|
||||||
|
GL_TRUE, stride, client_pointer);
|
||||||
|
} else {
|
||||||
|
_glgsg->_glVertexAttribPointer(p, num_values,
|
||||||
|
_glgsg->get_numeric_type(numeric_type),
|
||||||
|
normalized, stride, client_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (divisor > 0) {
|
||||||
|
_glgsg->set_vertex_attrib_divisor(p, divisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
++p;
|
||||||
|
client_pointer += element_stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < bind._elements; ++i) {
|
||||||
|
_glgsg->disable_vertex_attrib_array(p + i);
|
||||||
|
}
|
||||||
|
if (p == _color_attrib_index) {
|
||||||
|
// Vertex colors are disabled or not present. Apply flat color.
|
||||||
|
#ifdef STDFLOAT_DOUBLE
|
||||||
|
_glgsg->_glVertexAttrib4dv(p, color_attrib->get_color().get_data());
|
||||||
|
#else
|
||||||
|
_glgsg->_glVertexAttrib4fv(p, color_attrib->get_color().get_data());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable attribute arrays we don't use.
|
||||||
|
GLint highest_p = _glgsg->_enabled_vertex_attrib_arrays.get_highest_on_bit() + 1;
|
||||||
|
for (GLint p = max_p; p < highest_p; ++p) {
|
||||||
|
_glgsg->disable_vertex_attrib_array(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_transform_table_index >= 0) {
|
if (_transform_table_index >= 0) {
|
||||||
@ -2180,7 +2280,7 @@ disable_shader_texture_bindings() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
_glgsg->set_active_texture_stage(i);
|
||||||
|
|
||||||
switch (_shader->_tex_spec[i]._desired_type) {
|
switch (_shader->_tex_spec[i]._desired_type) {
|
||||||
case Texture::TT_1d_texture:
|
case Texture::TT_1d_texture:
|
||||||
@ -2371,7 +2471,8 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
static const bool multi_bind = false;
|
static const bool multi_bind = false;
|
||||||
#else
|
#else
|
||||||
bool multi_bind = false;
|
bool multi_bind = false;
|
||||||
if (_glgsg->_supports_multi_bind && _glgsg->_supports_sampler_objects) {
|
if (num_textures > 1 &&
|
||||||
|
_glgsg->_supports_multi_bind && _glgsg->_supports_sampler_objects) {
|
||||||
// Prepare to multi-bind the textures and samplers.
|
// Prepare to multi-bind the textures and samplers.
|
||||||
multi_bind = true;
|
multi_bind = true;
|
||||||
textures = (GLuint *)alloca(sizeof(GLuint) * num_textures);
|
textures = (GLuint *)alloca(sizeof(GLuint) * num_textures);
|
||||||
@ -2394,7 +2495,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
textures[i] = _glgsg->get_white_texture();
|
textures[i] = _glgsg->get_white_texture();
|
||||||
samplers[i] = 0;
|
samplers[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
_glgsg->set_active_texture_stage(i);
|
||||||
_glgsg->apply_white_texture();
|
_glgsg->apply_white_texture();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -2487,7 +2588,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
#endif // !OPENGLES
|
#endif // !OPENGLES
|
||||||
{
|
{
|
||||||
// Non-multibind case.
|
// Non-multibind case.
|
||||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
_glgsg->set_active_texture_stage(i);
|
||||||
if (!_glgsg->update_texture(gtc, false)) {
|
if (!_glgsg->update_texture(gtc, false)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2765,6 +2866,15 @@ glsl_compile_and_link() {
|
|||||||
_glgsg->_glBindAttribLocation(_glsl_program, 2, "p3d_Normal");
|
_glgsg->_glBindAttribLocation(_glsl_program, 2, "p3d_Normal");
|
||||||
_glgsg->_glBindAttribLocation(_glsl_program, 3, "p3d_Color");
|
_glgsg->_glBindAttribLocation(_glsl_program, 3, "p3d_Color");
|
||||||
|
|
||||||
|
if (gl_fixed_vertex_attrib_locations) {
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 1, "transform_weight");
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 2, "normal");
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 3, "color");
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 7, "transform_index");
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 8, "p3d_MultiTexCoord0");
|
||||||
|
_glgsg->_glBindAttribLocation(_glsl_program, 8, "texcoord");
|
||||||
|
}
|
||||||
|
|
||||||
// If we requested to retrieve the shader, we should indicate that before linking.
|
// If we requested to retrieve the shader, we should indicate that before linking.
|
||||||
#if !defined(NDEBUG) && !defined(OPENGLES)
|
#if !defined(NDEBUG) && !defined(OPENGLES)
|
||||||
if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {
|
if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {
|
||||||
|
@ -83,6 +83,7 @@ private:
|
|||||||
//typedef pvector<ParamContext> ParamContexts;
|
//typedef pvector<ParamContext> ParamContexts;
|
||||||
//ParamContexts _params;
|
//ParamContexts _params;
|
||||||
|
|
||||||
|
BitMask32 _enabled_attribs;
|
||||||
GLint _color_attrib_index;
|
GLint _color_attrib_index;
|
||||||
GLint _transform_table_index;
|
GLint _transform_table_index;
|
||||||
GLint _slider_table_index;
|
GLint _slider_table_index;
|
||||||
|
@ -276,6 +276,10 @@ ConfigVariableBool gl_vertex_array_objects
|
|||||||
"and vertex-buffers are both set. This should usually be "
|
"and vertex-buffers are both set. This should usually be "
|
||||||
"true unless you suspect a bug in the implementation. "));
|
"true unless you suspect a bug in the implementation. "));
|
||||||
|
|
||||||
|
ConfigVariableBool gl_fixed_vertex_attrib_locations
|
||||||
|
("gl-fixed-vertex-attrib-locations", false,
|
||||||
|
PRC_DESC("Experimental feature."));
|
||||||
|
|
||||||
ConfigVariableBool gl_support_primitive_restart_index
|
ConfigVariableBool gl_support_primitive_restart_index
|
||||||
("gl-support-primitive-restart-index", true,
|
("gl-support-primitive-restart-index", true,
|
||||||
PRC_DESC("Setting this causes Panda to make use of primitive "
|
PRC_DESC("Setting this causes Panda to make use of primitive "
|
||||||
|
@ -77,6 +77,7 @@ extern ConfigVariableBool gl_immutable_texture_storage;
|
|||||||
extern ConfigVariableBool gl_use_bindless_texture;
|
extern ConfigVariableBool gl_use_bindless_texture;
|
||||||
extern ConfigVariableBool gl_enable_memory_barriers;
|
extern ConfigVariableBool gl_enable_memory_barriers;
|
||||||
extern ConfigVariableBool gl_vertex_array_objects;
|
extern ConfigVariableBool gl_vertex_array_objects;
|
||||||
|
extern ConfigVariableBool gl_fixed_vertex_attrib_locations;
|
||||||
extern ConfigVariableBool gl_support_primitive_restart_index;
|
extern ConfigVariableBool gl_support_primitive_restart_index;
|
||||||
extern ConfigVariableBool gl_support_sampler_objects;
|
extern ConfigVariableBool gl_support_sampler_objects;
|
||||||
extern ConfigVariableBool gl_support_shadow_filter;
|
extern ConfigVariableBool gl_support_shadow_filter;
|
||||||
|
@ -427,6 +427,13 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|||||||
|
|
||||||
_name = DCAST(InternalName, p_list[pi++]);
|
_name = DCAST(InternalName, p_list[pi++]);
|
||||||
|
|
||||||
|
// Make sure that old .bam files are corrected to have C_normal
|
||||||
|
// normal columns rather than C_vector.
|
||||||
|
if (manager->get_file_minor_ver() < 38 &&
|
||||||
|
_name == InternalName::get_normal() && _contents == C_vector) {
|
||||||
|
_contents = C_normal;
|
||||||
|
}
|
||||||
|
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ generate() {
|
|||||||
(InternalName::get_vertex(), 3,
|
(InternalName::get_vertex(), 3,
|
||||||
GeomEnums::NT_stdfloat, GeomEnums::C_point,
|
GeomEnums::NT_stdfloat, GeomEnums::C_point,
|
||||||
InternalName::get_normal(), 3,
|
InternalName::get_normal(), 3,
|
||||||
GeomEnums::NT_stdfloat, GeomEnums::C_vector,
|
GeomEnums::NT_stdfloat, GeomEnums::C_normal,
|
||||||
InternalName::get_texcoord(), 3,
|
InternalName::get_texcoord(), 3,
|
||||||
GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
|
GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user