mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -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::
|
||||
ObjectData(CullableObject *object) :
|
||||
_object(object)
|
||||
_object(object),
|
||||
_format(object->_munged_data->get_format())
|
||||
{
|
||||
}
|
||||
|
||||
@ -45,16 +46,30 @@ ObjectData(CullableObject *object) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CullBinStateSorted::ObjectData::
|
||||
operator < (const ObjectData &other) const {
|
||||
// First group objects by transform, since transform changes are
|
||||
// supposed to be expensive.
|
||||
// Group by state changes, in approximate order from heaviest
|
||||
// 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) {
|
||||
return _object->_internal_transform < other._object->_internal_transform;
|
||||
}
|
||||
|
||||
// Then group by other state changes, in approximate order from
|
||||
// heaviest change to lightest change.
|
||||
const RenderState *sa = _object->_state;
|
||||
const RenderState *sb = other._object->_state;
|
||||
return sa->compare_sort(*sb) < 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ private:
|
||||
INLINE bool operator < (const ObjectData &other) const;
|
||||
|
||||
CullableObject *_object;
|
||||
const GeomVertexFormat *_format;
|
||||
};
|
||||
|
||||
typedef pvector<ObjectData> Objects;
|
||||
|
@ -1036,7 +1036,7 @@ disable_shader_texture_bindings() {
|
||||
if (p == 0) continue;
|
||||
|
||||
int texunit = cgGetParameterResourceIndex(p);
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
_glgsg->set_active_texture_stage(texunit);
|
||||
|
||||
glBindTexture(GL_TEXTURE_1D, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -1099,7 +1099,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
||||
if (tex.is_null()) {
|
||||
// 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.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->set_active_texture_stage(i);
|
||||
_glgsg->apply_white_texture();
|
||||
continue;
|
||||
}
|
||||
@ -1115,7 +1115,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
_glgsg->set_active_texture_stage(texunit);
|
||||
|
||||
TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg);
|
||||
if (tc == (TextureContext*)NULL) {
|
||||
|
@ -288,6 +288,23 @@ set_vertex_attrib_divisor(GLuint index, GLuint divisor) {
|
||||
|
||||
#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
|
||||
// Access: Protected
|
||||
|
@ -1086,9 +1086,7 @@ reset() {
|
||||
has_extension("GL_ARB_texture_non_power_of_two");
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
_glActiveTexture = glActiveTexture;
|
||||
#else
|
||||
#ifndef OPENGLES_2
|
||||
bool supports_multitexture = false;
|
||||
if (is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1)) {
|
||||
supports_multitexture = true;
|
||||
@ -1641,6 +1639,28 @@ reset() {
|
||||
_glVertexAttribLPointer = NULL;
|
||||
#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
|
||||
// something didn't happen to have a shader applied, or
|
||||
// if it failed to compile. This default shader just outputs
|
||||
@ -2344,6 +2364,7 @@ reset() {
|
||||
}
|
||||
}
|
||||
|
||||
_active_texture_stage = -1;
|
||||
_num_active_texture_stages = 0;
|
||||
|
||||
// Check availability of anisotropic texture filtering.
|
||||
@ -2407,18 +2428,22 @@ reset() {
|
||||
|
||||
// Check availability of multi-bind functions.
|
||||
_supports_multi_bind = false;
|
||||
#ifndef OPENGLES
|
||||
if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_multi_bind")) {
|
||||
_glBindTextures = (PFNGLBINDTEXTURESPROC)
|
||||
get_extension_func("glBindTextures");
|
||||
_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)
|
||||
get_extension_func("glBindImageTextures");
|
||||
|
||||
#ifndef OPENGLES
|
||||
if (_supports_sampler_objects) {
|
||||
_glBindSamplers = (PFNGLBINDSAMPLERSPROC)
|
||||
get_extension_func("glBindSamplers");
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
if (_use_vertex_attrib_binding) {
|
||||
_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)
|
||||
get_extension_func("glBindVertexBuffers");
|
||||
}
|
||||
|
||||
if (_glBindTextures != NULL && _glBindImageTextures != NULL) {
|
||||
_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";
|
||||
}
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_internalformat_query2")) {
|
||||
_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)
|
||||
@ -2616,6 +2642,12 @@ reset() {
|
||||
_point_size = 1.0f;
|
||||
_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();
|
||||
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
@ -3108,7 +3140,7 @@ clear_before_callback() {
|
||||
// Some callbacks may quite reasonably assume that the active
|
||||
// texture stage is still set to stage 0. CEGUI, in particular,
|
||||
// makes this assumption.
|
||||
_glActiveTexture(GL_TEXTURE0);
|
||||
set_active_texture_stage(0);
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
_glClientActiveTexture(GL_TEXTURE0);
|
||||
#endif
|
||||
@ -3375,6 +3407,9 @@ end_frame(Thread *current_thread) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Respecify the active texture next frame, for good measure.
|
||||
_active_texture_stage = -1;
|
||||
|
||||
// Calling glFlush() at the end of the frame is particularly
|
||||
// necessary if this is a single-buffered visual, so that the frame
|
||||
// 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;
|
||||
#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);
|
||||
#ifdef OPENGLES_1
|
||||
@ -3908,42 +3952,97 @@ unbind_buffers() {
|
||||
_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
|
||||
disable_standard_vertex_arrays();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
#ifndef OPENGLES
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::disable_standard_vertex_arrays
|
||||
// Function: GLGraphicsStateGuardian::update_shader_vertex_format
|
||||
// Access: Protected
|
||||
// Description: Used to disable all the standard vertex arrays that
|
||||
// are currently enabled. glShaderContexts are
|
||||
// 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.
|
||||
// Description: Updates the vertex format used by the shader. This
|
||||
// is still an experimental feature.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
disable_standard_vertex_arrays() {
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (_use_sender) return;
|
||||
#endif
|
||||
update_shader_vertex_format(const GeomVertexFormat *format) {
|
||||
size_t num_columns = format->get_num_columns();
|
||||
for (size_t ci = 0; ci < num_columns; ++ci) {
|
||||
GLuint binding = format->get_array_with(ci);
|
||||
const GeomVertexColumn *column = format->get_column(ci);
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
// Needs improvement, obviously.
|
||||
const InternalName *name = column->get_name();
|
||||
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++) {
|
||||
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (_vertex_attrib_columns[loc] != NULL &&
|
||||
_vertex_attrib_columns[loc]->compare_to(*column) == 0) {
|
||||
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);
|
||||
report_my_gl_errors();
|
||||
size_t num_arrays = format->get_num_arrays();
|
||||
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
|
||||
@ -5112,7 +5211,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
apply_vertex_buffer(gvbc, data->get_handle(), false);
|
||||
update_vertex_buffer(gvbc, data->get_handle(), false);
|
||||
return gvbc;
|
||||
}
|
||||
|
||||
@ -5120,31 +5219,22 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::apply_vertex_buffer
|
||||
// Function: GLGraphicsStateGuardian::update_vertex_buffer
|
||||
// Access: Public
|
||||
// Description: Makes the data the currently available data for
|
||||
// rendering.
|
||||
// Description: Makes sure that the data in the vertex buffer is
|
||||
// up-to-date. This may bind it to the GL_ARRAY_BUFFER
|
||||
// binding point if necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
apply_vertex_buffer(VertexBufferContext *vbc,
|
||||
const GeomVertexArrayDataHandle *reader, bool force) {
|
||||
update_vertex_buffer(CLP(VertexBufferContext) *gvbc,
|
||||
const GeomVertexArrayDataHandle *reader, bool force) {
|
||||
nassertr(_supports_buffers, false);
|
||||
if (reader->get_modified() == UpdateSeq::initial()) {
|
||||
// No need to re-apply.
|
||||
return true;
|
||||
}
|
||||
|
||||
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
|
||||
|
||||
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);
|
||||
}
|
||||
gvbc->set_active(true);
|
||||
|
||||
if (gvbc->was_modified(reader)) {
|
||||
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());
|
||||
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)) {
|
||||
_glBufferData(GL_ARRAY_BUFFER, num_bytes, client_pointer,
|
||||
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.
|
||||
VertexBufferContext *vbc = array_reader->prepare_now(get_prepared_objects(), this);
|
||||
nassertr(vbc != (VertexBufferContext *)NULL, false);
|
||||
if (!apply_vertex_buffer(vbc, array_reader, force)) {
|
||||
CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext),
|
||||
array_reader->prepare_now(get_prepared_objects(), this));
|
||||
|
||||
nassertr(gvbc != (CLP(VertexBufferContext) *)NULL, false);
|
||||
if (!update_vertex_buffer(gvbc, array_reader, force)) {
|
||||
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.
|
||||
client_pointer = NULL;
|
||||
return true;
|
||||
@ -9316,6 +9426,14 @@ void CLP(GraphicsStateGuardian)::
|
||||
reissue_transforms() {
|
||||
prepare_lens();
|
||||
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
|
||||
@ -9592,7 +9710,7 @@ set_state_and_transform(const RenderState *target,
|
||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||
}
|
||||
#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();
|
||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||
}
|
||||
@ -9945,7 +10063,7 @@ update_standard_texture_bindings() {
|
||||
nassertv(texture != (Texture *)NULL);
|
||||
|
||||
// Issue the texture on stage i.
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
|
||||
// First, turn off the previous texture mode.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
@ -10114,7 +10232,7 @@ update_standard_texture_bindings() {
|
||||
|
||||
// Disable the texture stages that are no longer used.
|
||||
for (i = num_stages; i < _num_active_texture_stages; i++) {
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (_supports_cube_map) {
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
@ -10217,7 +10335,7 @@ update_show_usage_texture_bindings(int show_stage_index) {
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
// Disable all texture stages.
|
||||
for (i = 0; i < _num_active_texture_stages; i++) {
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
#ifndef OPENGLES
|
||||
glDisable(GL_TEXTURE_1D);
|
||||
#endif // OPENGLES
|
||||
@ -10249,7 +10367,7 @@ update_show_usage_texture_bindings(int show_stage_index) {
|
||||
nassertv(texture != (Texture *)NULL);
|
||||
|
||||
// Choose the corresponding usage texture and apply it.
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
#endif
|
||||
@ -10366,7 +10484,7 @@ void CLP(GraphicsStateGuardian)::
|
||||
disable_standard_texture_bindings() {
|
||||
// Disable the texture stages that are no longer used.
|
||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
#ifndef OPENGLES
|
||||
glDisable(GL_TEXTURE_1D);
|
||||
#endif // OPENGLES
|
||||
@ -10399,7 +10517,7 @@ do_issue_tex_matrix() {
|
||||
|
||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
|
||||
@ -10452,7 +10570,7 @@ do_issue_tex_gen() {
|
||||
|
||||
for (int i = 0; i < _num_active_texture_stages; i++) {
|
||||
TextureStage *stage = _target_texture->get_on_ff_stage(i);
|
||||
_glActiveTexture(GL_TEXTURE0 + i);
|
||||
set_active_texture_stage(i);
|
||||
if (_supports_point_sprite) {
|
||||
#ifdef OPENGLES
|
||||
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
|
||||
// texture and change the texture parameters if they don't match.
|
||||
if (gtc->_active_sampler != sampler) {
|
||||
_glActiveTexture(GL_TEXTURE0 + unit);
|
||||
set_active_texture_stage(unit);
|
||||
apply_texture(gtc);
|
||||
specify_texture(gtc, sampler);
|
||||
}
|
||||
|
@ -306,9 +306,9 @@ public:
|
||||
void record_deleted_display_list(GLuint index);
|
||||
|
||||
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
|
||||
bool apply_vertex_buffer(VertexBufferContext *vbc,
|
||||
const GeomVertexArrayDataHandle *reader,
|
||||
bool force);
|
||||
bool update_vertex_buffer(CLP(VertexBufferContext) *gvbc,
|
||||
const GeomVertexArrayDataHandle *reader,
|
||||
bool force);
|
||||
virtual void release_vertex_buffer(VertexBufferContext *vbc);
|
||||
|
||||
bool setup_array_data(const unsigned char *&client_pointer,
|
||||
@ -457,6 +457,8 @@ protected:
|
||||
INLINE void set_vertex_attrib_divisor(GLuint index, GLuint divisor);
|
||||
#endif
|
||||
|
||||
INLINE void set_active_texture_stage(int i);
|
||||
|
||||
INLINE void enable_multisample_antialias(bool val);
|
||||
INLINE void enable_multisample_alpha_one(bool val);
|
||||
INLINE void enable_multisample_alpha_mask(bool val);
|
||||
@ -533,6 +535,9 @@ protected:
|
||||
void disable_standard_texture_bindings();
|
||||
void update_standard_texture_bindings();
|
||||
#endif
|
||||
#ifndef OPENGLES
|
||||
void update_shader_vertex_format(const GeomVertexFormat *format);
|
||||
#endif
|
||||
|
||||
void apply_white_texture();
|
||||
GLuint get_white_texture();
|
||||
@ -651,6 +656,15 @@ protected:
|
||||
GLuint _current_vbuffer_index;
|
||||
GLuint _current_ibuffer_index;
|
||||
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;
|
||||
PN_stdfloat _max_anisotropy;
|
||||
bool _supports_anisotropy;
|
||||
@ -735,7 +749,9 @@ public:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES_2
|
||||
PFNGLACTIVETEXTUREPROC _glActiveTexture;
|
||||
#endif
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
|
||||
#endif
|
||||
@ -897,6 +913,13 @@ public:
|
||||
PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
|
||||
#endif // !OPENGLES_1
|
||||
#ifndef OPENGLES
|
||||
PFNGLBINDVERTEXBUFFERPROC _glBindVertexBuffer;
|
||||
PFNGLBINDVERTEXBUFFERSPROC _glBindVertexBuffers;
|
||||
PFNGLVERTEXATTRIBFORMATPROC _glVertexAttribFormat;
|
||||
PFNGLVERTEXATTRIBIFORMATPROC _glVertexAttribIFormat;
|
||||
PFNGLVERTEXATTRIBLFORMATPROC _glVertexAttribLFormat;
|
||||
PFNGLVERTEXATTRIBBINDINGPROC _glVertexAttribBinding;
|
||||
PFNGLVERTEXBINDINGDIVISORPROC _glVertexBindingDivisor;
|
||||
PFNGLGETACTIVEUNIFORMSIVPROC _glGetActiveUniformsiv;
|
||||
PFNGLGETACTIVEUNIFORMBLOCKIVPROC _glGetActiveUniformBlockiv;
|
||||
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC _glGetActiveUniformBlockName;
|
||||
|
@ -262,6 +262,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
||||
_glgsg = glgsg;
|
||||
_glsl_program = 0;
|
||||
_uses_standard_vertex_arrays = false;
|
||||
_enabled_attribs.clear();
|
||||
_color_attrib_index = -1;
|
||||
_transform_table_index = -1;
|
||||
_slider_table_index = -1;
|
||||
@ -279,13 +280,31 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a buffer the size of the longest uniform name. Note
|
||||
// that Intel HD drivers report values that are too low.
|
||||
// Process the vertex attributes first.
|
||||
GLint param_count = 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);
|
||||
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
|
||||
// Get the used uniform blocks.
|
||||
if (_glgsg->_supports_uniform_buffers) {
|
||||
@ -316,7 +335,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
||||
_glgsg->_glUseProgram(_glsl_program);
|
||||
|
||||
// Analyze the uniforms.
|
||||
GLint param_count = 0;
|
||||
param_count = 0;
|
||||
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count);
|
||||
|
||||
_shader->_ptr_spec.clear();
|
||||
@ -326,17 +345,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
||||
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();
|
||||
|
||||
// Restore the active shader.
|
||||
@ -470,6 +478,37 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2045,91 +2084,152 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
||||
_state_rs->get_attrib_def(color_attrib);
|
||||
|
||||
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
|
||||
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 (_glgsg->_use_vertex_attrib_binding) {
|
||||
// Use experimental new separated format/binding state.
|
||||
const GeomVertexDataPipelineReader *data_reader = _glgsg->_data_reader;
|
||||
|
||||
if (divisor > 0) {
|
||||
_glgsg->set_vertex_attrib_divisor(p, divisor);
|
||||
}
|
||||
for (int ai = 0; ai < data_reader->get_num_arrays(); ++ai) {
|
||||
array_reader = data_reader->get_array_reader(ai);
|
||||
|
||||
++p;
|
||||
client_pointer += element_stride;
|
||||
// Make sure the vertex buffer is up-to-date.
|
||||
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) {
|
||||
_glgsg->disable_vertex_attrib_array(p + i);
|
||||
|
||||
GLintptr stride = array_reader->get_array_format()->get_stride();
|
||||
|
||||
// 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) {
|
||||
// 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
|
||||
if (_glgsg->_current_vertex_buffers[ai] != gvbc->_index) {
|
||||
_glgsg->_glBindVertexBuffer(ai, gvbc->_index, 0, stride);
|
||||
_glgsg->_current_vertex_buffers[ai] = gvbc->_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Figure out which attributes to enable or disable.
|
||||
BitMask32 enabled_attribs = _enabled_attribs;
|
||||
if (_color_attrib_index != -1 &&
|
||||
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) {
|
||||
@ -2180,7 +2280,7 @@ disable_shader_texture_bindings() {
|
||||
}
|
||||
#endif
|
||||
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->set_active_texture_stage(i);
|
||||
|
||||
switch (_shader->_tex_spec[i]._desired_type) {
|
||||
case Texture::TT_1d_texture:
|
||||
@ -2371,7 +2471,8 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
||||
static const bool multi_bind = false;
|
||||
#else
|
||||
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.
|
||||
multi_bind = true;
|
||||
textures = (GLuint *)alloca(sizeof(GLuint) * num_textures);
|
||||
@ -2394,7 +2495,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
||||
textures[i] = _glgsg->get_white_texture();
|
||||
samplers[i] = 0;
|
||||
} else {
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->set_active_texture_stage(i);
|
||||
_glgsg->apply_white_texture();
|
||||
}
|
||||
continue;
|
||||
@ -2487,7 +2588,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
||||
#endif // !OPENGLES
|
||||
{
|
||||
// Non-multibind case.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->set_active_texture_stage(i);
|
||||
if (!_glgsg->update_texture(gtc, false)) {
|
||||
continue;
|
||||
}
|
||||
@ -2765,6 +2866,15 @@ glsl_compile_and_link() {
|
||||
_glgsg->_glBindAttribLocation(_glsl_program, 2, "p3d_Normal");
|
||||
_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 !defined(NDEBUG) && !defined(OPENGLES)
|
||||
if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {
|
||||
|
@ -83,6 +83,7 @@ private:
|
||||
//typedef pvector<ParamContext> ParamContexts;
|
||||
//ParamContexts _params;
|
||||
|
||||
BitMask32 _enabled_attribs;
|
||||
GLint _color_attrib_index;
|
||||
GLint _transform_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 "
|
||||
"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
|
||||
("gl-support-primitive-restart-index", true,
|
||||
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_enable_memory_barriers;
|
||||
extern ConfigVariableBool gl_vertex_array_objects;
|
||||
extern ConfigVariableBool gl_fixed_vertex_attrib_locations;
|
||||
extern ConfigVariableBool gl_support_primitive_restart_index;
|
||||
extern ConfigVariableBool gl_support_sampler_objects;
|
||||
extern ConfigVariableBool gl_support_shadow_filter;
|
||||
|
@ -427,6 +427,13 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ generate() {
|
||||
(InternalName::get_vertex(), 3,
|
||||
GeomEnums::NT_stdfloat, GeomEnums::C_point,
|
||||
InternalName::get_normal(), 3,
|
||||
GeomEnums::NT_stdfloat, GeomEnums::C_vector,
|
||||
GeomEnums::NT_stdfloat, GeomEnums::C_normal,
|
||||
InternalName::get_texcoord(), 3,
|
||||
GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user