inline void gl_set_vertex_attribute_divisor(GLuint index, GLuint divisor) { #if defined(__OSX__) #if defined(__OPENGL_20__) glVertexAttribDivisorEXT(index, divisor); #else glVertexAttribDivisor(index, divisor); #endif #elif defined(__IOS__) #if defined(__OPENGL_20__) glVertexAttribDivisorEXT(index, divisor); #else glVertexAttribDivisor(index, divisor); #endif #endif #if defined(DEBUG) gl_get_error(); #endif }
void OGLESRenderLayout::UnbindVertexStreams(ShaderObjectPtr const & so) const { OGLESShaderObjectPtr const & ogl_so = checked_pointer_cast<OGLESShaderObject>(so); for (uint32_t i = 0; i < this->NumVertexStreams(); ++ i) { vertex_elements_type const & vertex_stream_fmt = this->VertexStreamFormat(i); for (auto const & vs_elem : vertex_stream_fmt) { GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index); if (attr != -1) { glDisableVertexAttribArray(attr); } } } if (this->InstanceStream() && (glloader_GLES_VERSION_3_0() || glloader_GLES_EXT_instanced_arrays())) { size_t const inst_format_size = this->InstanceStreamFormat().size(); for (size_t i = 0; i < inst_format_size; ++ i) { vertex_element const & vs_elem = this->InstanceStreamFormat()[i]; GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index); if (attr != -1) { glDisableVertexAttribArray(attr); if (glloader_GLES_VERSION_3_0()) { glVertexAttribDivisor(attr, 0); } else { glVertexAttribDivisorEXT(attr, 0); } } } } }
void OGLESRenderLayout::BindVertexStreams(ShaderObjectPtr const & so) const { OGLESShaderObjectPtr const & ogl_so = checked_pointer_cast<OGLESShaderObject>(so); RenderEngine& re = Context::Instance().RenderFactoryInstance().RenderEngineInstance(); uint32_t max_vertex_streams = re.DeviceCaps().max_vertex_streams; std::vector<char> used_streams(max_vertex_streams, 0); for (uint32_t i = 0; i < this->NumVertexStreams(); ++ i) { OGLESGraphicsBuffer& stream(*checked_pointer_cast<OGLESGraphicsBuffer>(this->GetVertexStream(i))); uint32_t const size = this->VertexSize(i); vertex_elements_type const & vertex_stream_fmt = this->VertexStreamFormat(i); uint8_t* elem_offset = nullptr; for (auto const & vs_elem : vertex_stream_fmt) { GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index); if (attr != -1) { GLvoid* offset = static_cast<GLvoid*>(elem_offset + this->StartVertexLocation() * size); GLint const num_components = static_cast<GLint>(NumComponents(vs_elem.format)); GLenum type; GLboolean normalized; OGLESMapping::MappingVertexFormat(type, normalized, vs_elem.format); normalized = (((VEU_Diffuse == vs_elem.usage) || (VEU_Specular == vs_elem.usage)) && !IsFloatFormat(vs_elem.format)) ? GL_TRUE : normalized; BOOST_ASSERT(GL_ARRAY_BUFFER == stream.GLType()); stream.Active(use_vao_); glVertexAttribPointer(attr, num_components, type, normalized, size, offset); glEnableVertexAttribArray(attr); used_streams[attr] = 1; } elem_offset += vs_elem.element_size(); } } if (this->InstanceStream() && (glloader_GLES_VERSION_3_0() || glloader_GLES_EXT_instanced_arrays())) { OGLESGraphicsBuffer& stream(*checked_pointer_cast<OGLESGraphicsBuffer>(this->InstanceStream())); uint32_t const instance_size = this->InstanceSize(); BOOST_ASSERT(this->NumInstances() * instance_size <= stream.Size()); size_t const inst_format_size = this->InstanceStreamFormat().size(); uint8_t* elem_offset = nullptr; for (size_t i = 0; i < inst_format_size; ++ i) { vertex_element const & vs_elem = this->InstanceStreamFormat()[i]; GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index); if (attr != -1) { GLint const num_components = static_cast<GLint>(NumComponents(vs_elem.format)); GLenum type; GLboolean normalized; OGLESMapping::MappingVertexFormat(type, normalized, vs_elem.format); normalized = (((VEU_Diffuse == vs_elem.usage) || (VEU_Specular == vs_elem.usage)) && !IsFloatFormat(vs_elem.format)) ? GL_TRUE : normalized; GLvoid* offset = static_cast<GLvoid*>(elem_offset + this->StartInstanceLocation() * instance_size); BOOST_ASSERT(GL_ARRAY_BUFFER == stream.GLType()); stream.Active(use_vao_); glVertexAttribPointer(attr, num_components, type, normalized, instance_size, offset); glEnableVertexAttribArray(attr); if (glloader_GLES_VERSION_3_0()) { glVertexAttribDivisor(attr, 1); } else { glVertexAttribDivisorEXT(attr, 1); } used_streams[attr] = 1; } elem_offset += vs_elem.element_size(); } } for (GLuint i = 0; i < max_vertex_streams; ++ i) { if (!used_streams[i]) { glDisableVertexAttribArray(i); } } OGLESRenderEngine& ogl_re = *checked_cast<OGLESRenderEngine*>(&re); if (!(ogl_re.HackForMali() || ogl_re.HackForAdreno()) && this->UseIndices()) { OGLESGraphicsBuffer& stream(*checked_pointer_cast<OGLESGraphicsBuffer>(this->GetIndexStream())); BOOST_ASSERT(GL_ELEMENT_ARRAY_BUFFER == stream.GLType()); stream.Active(use_vao_); } }
void VaoImplEs::vertexAttribDivisorImpl( GLuint index, GLuint divisor ) { mLayout.vertexAttribDivisor( index, divisor ); glVertexAttribDivisorEXT( index, divisor ); }