// Used only for VSM shader with geometry instancing support. void GPU_shader_bind_instancing_attrib(GPUShader *shader, void *matrixoffset, void *positionoffset, unsigned int stride) { int posloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_POSITION_ATTRIB)); int matloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_MATRIX_ATTRIB)); // Matrix if (matloc != -1) { glEnableVertexAttribArrayARB(matloc); glEnableVertexAttribArrayARB(matloc + 1); glEnableVertexAttribArrayARB(matloc + 2); glVertexAttribPointerARB(matloc, 3, GL_FLOAT, GL_FALSE, stride, matrixoffset); glVertexAttribPointerARB(matloc + 1, 3, GL_FLOAT, GL_FALSE, stride, ((char *)matrixoffset) + 3 * sizeof(float)); glVertexAttribPointerARB(matloc + 2, 3, GL_FLOAT, GL_FALSE, stride, ((char *)matrixoffset) + 6 * sizeof(float)); glVertexAttribDivisorARB(matloc, 1); glVertexAttribDivisorARB(matloc + 1, 1); glVertexAttribDivisorARB(matloc + 2, 1); } // Position if (posloc != -1) { glEnableVertexAttribArrayARB(posloc); glVertexAttribPointerARB(posloc, 3, GL_FLOAT, GL_FALSE, stride, positionoffset); glVertexAttribDivisorARB(posloc, 1); } }
static GLboolean test_instancing(GLuint divisor) { static const GLfloat verts[4][2] = { {-1, -1}, {1, -1}, {1, 1}, {-1, 1} }; glVertexPointer(2, GL_FLOAT, 0, verts); glEnableClientState(GL_VERTEX_ARRAY); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, Positions); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, Colors); glEnableVertexAttribArray(PosAttrib); glEnableVertexAttribArray(ColorAttrib); glVertexAttribDivisorARB(PosAttrib, 1); /* advance color once every 'n' instances */ glVertexAttribDivisorARB(ColorAttrib, divisor); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(Program); glDrawArraysInstancedARB(GL_POLYGON, 0, 4, PRIMS); glUseProgram(0); { GLint i; GLint pos[4]; for (i = 0; i < PRIMS; i++) { GLuint elem = i / divisor; /* use glRasterPos to determine where to read a sample pixel */ glRasterPos2fv(Positions[i]); glGetIntegerv(GL_CURRENT_RASTER_POSITION, pos); if (!piglit_probe_pixel_rgba(pos[0], pos[1], Colors[elem])) { fprintf(stderr, "%s: instance %d failed to draw correctly\n", TestName, i); fprintf(stderr, "%s: color instance divisor = %u\n", TestName, divisor); glutSwapBuffers(); return GL_FALSE; } } } glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(PosAttrib); glDisableVertexAttribArray(ColorAttrib); glutSwapBuffers(); return GL_TRUE; }
void VAOInstanceUtil<InstanceDataDualTex>::SetVertexAttrib() { SetVertexAttrib_impl(); glEnableVertexAttribArray(10); glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceDataDualTex), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisorARB(10, 1); glEnableVertexAttribArray(11); glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataDualTex), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); glVertexAttribDivisorARB(11, 1); }
static void SetVertexAttrib_impl() { glEnableVertexAttribArray(7); glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(T), 0); glVertexAttribDivisorARB(7, 1); glEnableVertexAttribArray(8); glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(T), (GLvoid*)(3 * sizeof(float))); glVertexAttribDivisorARB(8, 1); glEnableVertexAttribArray(9); glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(T), (GLvoid*)(6 * sizeof(float))); glVertexAttribDivisorARB(9, 1); }
void VAOInstanceUtil<GlowInstanceData>::SetVertexAttrib() { SetVertexAttrib_impl(); glEnableVertexAttribArray(15); glVertexAttribPointer(15, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisorARB(15, 1); }
void VAOInstanceUtil<InstanceDataThreeTex>::SetVertexAttrib() { SetVertexAttrib_impl(); glEnableVertexAttribArray(10); glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceDataThreeTex), (GLvoid*)(9 * sizeof(float))); glVertexAttribDivisorARB(10, 1); glEnableVertexAttribArray(11); glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataThreeTex), (GLvoid*)(13 * sizeof(float))); glVertexAttribDivisorARB(11, 1); glEnableVertexAttribArray(12); glVertexAttribIPointer(12, 2, GL_UNSIGNED_INT, sizeof(InstanceDataThreeTex), (GLvoid*)(13 * sizeof(float) + 2 * sizeof(unsigned))); glVertexAttribDivisorARB(12, 1); glEnableVertexAttribArray(13); glVertexAttribIPointer(13, 2, GL_UNSIGNED_INT, sizeof(InstanceDataThreeTex), (GLvoid*)(13 * sizeof(float) + 4 * sizeof(unsigned))); glVertexAttribDivisorARB(13, 1); }
EXTERN_C_ENTER JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBInstancedArrays_glVertexAttribDivisorARB(JNIEnv *__env, jclass clazz, jint index, jint divisor) { glVertexAttribDivisorARBPROC glVertexAttribDivisorARB = (glVertexAttribDivisorARBPROC)tlsGetFunction(1203); UNUSED_PARAM(clazz) glVertexAttribDivisorARB(index, divisor); }
void VaoImplCore::vertexAttribDivisorImpl( GLuint index, GLuint divisor ) { mLayout.vertexAttribDivisor( index, divisor ); #if defined( CINDER_GL_ES ) #if defined( CINDER_GL_ANGLE ) glVertexAttribDivisorANGLE( index, divisor ); #else if( gl::env()->supportsInstancedArrays() ) { glVertexAttribDivisor( index, divisor ); } #endif #else if( glVertexAttribDivisor ) { // not always available glVertexAttribDivisor( index, divisor ); } else if( glVertexAttribDivisorARB ) { glVertexAttribDivisorARB( index, divisor ); } #endif /* #if defined( CINDER_GL_ANGLE ) glVertexAttribDivisorANGLE( index, divisor ); #elif defined( CINDER_GL_ES_3 ) glVertexAttribDivisor( index, divisor ); #else if( glVertexAttribDivisor ) // not always available glVertexAttribDivisor( index, divisor ); else if( glVertexAttribDivisorARB ) glVertexAttribDivisorARB( index, divisor ); #endif */ }
/*! \brief Sets the divisor of a vertex attribute. The divisor is used in instancing to set the rate at which vertex attributes are incremented. */ inline void setAttributeDivisor(GLuint idx, GLuint divisor) { if (idx >= _vertexAttributeState.size()) M_throw() << "Attribute index out of range"; if (divisor == _vertexAttributeState[idx].divisor) return; _vertexAttributeState[idx].divisor = divisor; glVertexAttribDivisorARB(idx, divisor); detail::errorCheck(); }
void GPU_shader_unbind_instancing_attrib(GPUShader *shader) { int posloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_POSITION_ATTRIB)); int matloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_MATRIX_ATTRIB)); // Matrix if (matloc != -1) { glDisableVertexAttribArrayARB(matloc); glDisableVertexAttribArrayARB(matloc + 1); glDisableVertexAttribArrayARB(matloc + 2); glVertexAttribDivisorARB(matloc, 0); glVertexAttribDivisorARB(matloc + 1, 0); glVertexAttribDivisorARB(matloc + 2, 0); } // Position if (posloc != -1) { glDisableVertexAttribArrayARB(posloc); glVertexAttribDivisorARB(posloc, 0); } }
void VertexArrayNoVao::enableOpenGLVertexAttribArrays() { #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL array buffer // -> Using "GL_EXT_direct_state_access" this would not help in here because "glVertexAttribPointerARB" is not specified there :/ GLint openGLArrayBufferBackup = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &openGLArrayBufferBackup); #endif // Loop through all attributes // -> We're using "glBindAttribLocationARB()" when linking the program so we have known attribute locations (the vertex array can't know about the program) GLuint attributeLocation = 0; const Renderer::VertexAttribute *attributeEnd = mAttributes + mNumberOfAttributes; for (const Renderer::VertexAttribute *attribute = mAttributes; attribute < attributeEnd; ++attribute, ++attributeLocation) { // Set the OpenGL vertex attribute pointer // TODO(co) Add security check: Is the given resource one of the currently used renderer? const Renderer::VertexArrayVertexBuffer& vertexArrayVertexBuffer = mVertexBuffers[attribute->inputSlot]; glBindBufferARB(GL_ARRAY_BUFFER_ARB, static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer()); glVertexAttribPointerARB(attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes), reinterpret_cast<GLvoid*>(attribute->alignedByteOffset)); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && mIsGL_ARB_instanced_arrays) { glVertexAttribDivisorARB(attributeLocation, attribute->instancesPerElement); } // Enable OpenGL vertex attribute array glEnableVertexAttribArrayARB(attributeLocation); } #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL array buffer glBindBufferARB(GL_ARRAY_BUFFER_ARB, static_cast<GLuint>(openGLArrayBufferBackup)); #endif // Get the used index buffer // -> In case of no index buffer we don't bind buffer 0, there's not really a point in it const IndexBuffer *indexBuffer = getIndexBuffer(); if (nullptr != indexBuffer) { // Bind OpenGL element array buffer glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer->getOpenGLElementArrayBuffer()); } }
void VertexArrayNoVao::disableOpenGLVertexAttribArrays() { // No previous bound OpenGL element array buffer restore, there's not really a point in it // Loop through all attributes // -> We're using "glBindAttribLocationARB()" when linking the program so we have known attribute locations (the vertex array can't know about the program) GLuint attributeLocation = 0; const Renderer::VertexAttribute *attributeEnd = mAttributes + mNumberOfAttributes; for (const Renderer::VertexAttribute *attribute = mAttributes; attribute < attributeEnd; ++attribute, ++attributeLocation) { // Disable OpenGL vertex attribute array glDisableVertexAttribArrayARB(attributeLocation); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && mIsGL_ARB_instanced_arrays) { glVertexAttribDivisorARB(attributeLocation, 0); } } }
void GLInstancingRenderer::RenderScene(void) { B3_PROFILE("GLInstancingRenderer::RenderScene"); { B3_PROFILE("init"); init(); } GLint err = glGetError(); assert(err==GL_NO_ERROR); { B3_PROFILE("updateCamera"); updateCamera(); } err = glGetError(); assert(err==GL_NO_ERROR); //render coordinate system #if 0 glBegin(GL_LINES); err = glGetError(); assert(err==GL_NO_ERROR); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(1,0,0); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,1,0); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(0,0,1); glEnd(); #endif //do a finish, to make sure timings are clean // glFinish(); // glBindBuffer(GL_ARRAY_BUFFER, 0); { B3_PROFILE("glFlush2"); glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo); glFlush(); } err = glGetError(); assert(err==GL_NO_ERROR); //updatePos(); // simulationLoop(); //useCPU = true; int totalNumInstances = 0; for (int i=0;i<m_graphicsInstances.size();i++) { totalNumInstances+=m_graphicsInstances[i]->m_numGraphicsInstances; } int curOffset = 0; GLuint lastBindTexture = 0; for (int i=0;i<m_graphicsInstances.size();i++) { b3GraphicsInstance* gfxObj = m_graphicsInstances[i]; if (gfxObj->m_numGraphicsInstances) { GLuint curBindTexture = 0; if (gfxObj->m_texturehandle) curBindTexture = gfxObj->m_texturehandle; else curBindTexture = m_data->m_defaultTexturehandle; if (lastBindTexture != curBindTexture) { glBindTexture(GL_TEXTURE_2D,curBindTexture); } lastBindTexture = curBindTexture; err = glGetError(); assert(err==GL_NO_ERROR); // int myOffset = gfxObj->m_instanceOffset*4*sizeof(float); int POSITION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); int ORIENTATION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); int COLOR_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); // int SCALE_BUFFER_SIZE = (totalNumInstances*sizeof(float)*3); glBindVertexArray(gfxObj->m_cube_vao); int vertexStride = 9*sizeof(float); int vertexBase = gfxObj->m_vertexArrayOffset*vertexStride; glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid*)vertexBase); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes)); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE)); int uvoffset = 7*sizeof(float)+vertexBase; int normaloffset = 4*sizeof(float)+vertexBase; glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE)); glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*3*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); glVertexAttribDivisorARB(0, 0); glVertexAttribDivisorARB(1, 1); glVertexAttribDivisorARB(2, 1); glVertexAttribDivisorARB(3, 0); glVertexAttribDivisorARB(4, 0); glVertexAttribDivisorARB(5, 1); glVertexAttribDivisorARB(6, 1); { B3_PROFILE("glFlush"); glFlush(); } int indexCount = gfxObj->m_numIndices; int indexOffset = 0; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo); { B3_PROFILE("glDrawElementsInstanced"); if (gfxObj->m_primitiveType==B3_GL_POINTS) { glUseProgram(instancingShaderPointSprite); glUniformMatrix4fv(ProjectionMatrixPointSprite, 1, false, &projectionMatrix[0]); glUniformMatrix4fv(ModelViewMatrixPointSprite, 1, false, &modelviewMatrix[0]); glUniform1f(screenWidthPointSprite,m_screenWidth); //glUniform1i(uniform_texture_diffusePointSprite, 0); err = glGetError(); assert(err==GL_NO_ERROR); glPointSize(20); #ifndef __APPLE__ glEnable(GL_POINT_SPRITE_ARB); glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); #endif glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glDrawElementsInstanced(GL_POINTS, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); } else { glUseProgram(instancingShader); glUniform1f(angle_loc, 0); glUniformMatrix4fv(ProjectionMatrix, 1, false, &projectionMatrix[0]); glUniformMatrix4fv(ModelViewMatrix, 1, false, &modelviewMatrix[0]); glUniform1i(uniform_texture_diffuse, 0); glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); } //glDrawElementsInstanced(GL_LINE_LOOP, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); } } curOffset+= gfxObj->m_numGraphicsInstances; } err = glGetError(); assert(err==GL_NO_ERROR); { B3_PROFILE("glUseProgram(0);"); glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindVertexArray(0); } err = glGetError(); assert(err==GL_NO_ERROR); }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] VertexArrayVaoDsa::VertexArrayVaoDsa(OpenGLRenderer &openGLRenderer, const Renderer::VertexAttributes& vertexAttributes, uint32_t numberOfVertexBuffers, const Renderer::VertexArrayVertexBuffer *vertexBuffers, IndexBuffer *indexBuffer) : VertexArrayVao(openGLRenderer, numberOfVertexBuffers, vertexBuffers, indexBuffer) { // Vertex buffer reference handling is done within the base class "VertexArrayVao" const bool isARB_DSA = openGLRenderer.getExtensions().isGL_ARB_direct_state_access(); if (isARB_DSA) { // Create the OpenGL vertex array glCreateVertexArrays(1, &mOpenGLVertexArray); } else { // Create the OpenGL vertex array glGenVertexArrays(1, &mOpenGLVertexArray); } // Loop through all attributes // -> We're using "glBindAttribLocationARB()" when linking the program so we have known attribute locations (the vertex array can't know about the program) GLuint attributeLocation = 0; const Renderer::VertexAttribute *attributeEnd = vertexAttributes.attributes + vertexAttributes.numberOfAttributes; for (const Renderer::VertexAttribute *attribute = vertexAttributes.attributes; attribute < attributeEnd; ++attribute, ++attributeLocation) { // Set the OpenGL vertex attribute pointer // TODO(co) Add security check: Is the given resource one of the currently used renderer? const Renderer::VertexArrayVertexBuffer& vertexArrayVertexBuffer = vertexBuffers[attribute->inputSlot]; if (isARB_DSA) { // Enable attribute glEnableVertexArrayAttrib(mOpenGLVertexArray, attributeLocation); // Set up the format for my attribute glVertexArrayAttribFormat(mOpenGLVertexArray, attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLuint>(attribute->alignedByteOffset)); // Bind vertex buffer to buffer point glVertexArrayVertexBuffer(mOpenGLVertexArray, attributeLocation, static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(), 0, // No offset to the first element of the buffer static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes)); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays()) { glVertexArrayBindingDivisor(mOpenGLVertexArray, attributeLocation, attribute->instancesPerElement); } } else { glVertexArrayVertexAttribOffsetEXT(mOpenGLVertexArray, static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(), attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes), static_cast<GLintptr>(attribute->alignedByteOffset)); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays()) { // Sadly, DSA has no support for "GL_ARB_instanced_arrays", so, we have to use the bind way // -> Keep the bind-horror as local as possible #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL vertex array GLint openGLVertexArrayBackup = 0; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup); #endif // Bind this OpenGL vertex array glBindVertexArray(mOpenGLVertexArray); // Set divisor glVertexAttribDivisorARB(attributeLocation, attribute->instancesPerElement); #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL vertex array glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup)); #endif } // Enable OpenGL vertex attribute array glEnableVertexArrayAttribEXT(mOpenGLVertexArray, attributeLocation); } } // Check the used index buffer // -> In case of no index buffer we don't bind buffer 0, there's not really a point in it if (nullptr != indexBuffer) { if (isARB_DSA) { // Bind the index buffer glVertexArrayElementBuffer(mOpenGLVertexArray, indexBuffer->getOpenGLElementArrayBuffer()); } else { // Sadly, EXT DSA has no support for element array buffer, so, we have to use the bind way // -> Keep the bind-horror as local as possible #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL vertex array GLint openGLVertexArrayBackup = 0; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup); // Backup the currently bound OpenGL element array buffer GLint openGLElementArrayBufferBackup = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &openGLElementArrayBufferBackup); #endif // Bind this OpenGL vertex array glBindVertexArray(mOpenGLVertexArray); // Bind OpenGL element array buffer glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer->getOpenGLElementArrayBuffer()); #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL vertex array glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup)); // Be polite and restore the previous bound OpenGL element array buffer glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, static_cast<GLuint>(openGLElementArrayBufferBackup)); #endif } } }
void piglit_init(int argc, char **argv) { GLuint vertices_bo; GLuint instance_bo; GLuint indices_bo; GLuint indirect_bo; piglit_require_extension("GL_ARB_draw_indirect"); piglit_require_extension("GL_ARB_base_instance"); piglit_require_extension("GL_ARB_instanced_arrays"); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &vertices_bo); glBindBuffer(GL_ARRAY_BUFFER, vertices_bo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glGenBuffers(1, &instance_bo); glBindBuffer(GL_ARRAY_BUFFER, instance_bo); glBufferData(GL_ARRAY_BUFFER, sizeof(instance_data), instance_data, GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribIPointer(1, 1, GL_INT, 0, 0); glVertexAttribDivisorARB(1, 1); glGenBuffers(1, &indices_bo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_bo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_data), indices_data, GL_STATIC_DRAW); glGenBuffers(1, &indirect_bo); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_bo); glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirect_data), indirect_data, GL_STATIC_DRAW); prog = piglit_build_simple_program( "#version 130\n" "#extension GL_ARB_explicit_attrib_location: require\n" "#extension GL_ARB_draw_instanced: require\n" "\n" "layout(location=0) in vec2 pos;\n" "layout(location=1) in int instance_in;\n" "\n" "flat out int instance;\n" "\n" "void main() {\n" " gl_Position = vec4(pos, 0, 1);\n" " instance = instance_in;\n" "}\n", "#version 130\n" "\n" "flat in int instance;\n" "\n" "void main() {\n" " if (instance == 42) {\n" " gl_FragColor = vec4(0,1,0,1);\n" " } else {\n" " gl_FragColor = vec4(1,0,0,1);\n" " }\n" "}\n"); glBindVertexArray(0); }
void GLInstancingRenderer::renderSceneInternal(int renderMode) { // glEnable(GL_DEPTH_TEST); GLint dims[4]; glGetIntegerv(GL_VIEWPORT, dims); //we need to get the viewport dims, because on Apple Retina the viewport dimension is different from screenWidth //printf("dims=%d,%d,%d,%d\n",dims[0],dims[1],dims[2],dims[3]); // Accept fragment if it closer to the camera than the former one //glDepthFunc(GL_LESS); // Cull triangles which normal is not towards the camera //glEnable(GL_CULL_FACE); B3_PROFILE("GLInstancingRenderer::RenderScene"); { B3_PROFILE("init"); init(); } GLint err = glGetError(); b3Assert(err==GL_NO_ERROR); float depthProjectionMatrix[4][4]; GLfloat depthModelViewMatrix[4][4]; //GLfloat depthModelViewMatrix2[4][4]; // Compute the MVP matrix from the light's point of view if (renderMode==B3_CREATE_SHADOWMAP_RENDERMODE) { if (!m_data->m_shadowMap) { glActiveTexture(GL_TEXTURE0); glGenTextures(1,&m_data->m_shadowTexture); glBindTexture(GL_TEXTURE_2D,m_data->m_shadowTexture); //glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT16,m_screenWidth,m_screenHeight,0,GL_DEPTH_COMPONENT,GL_FLOAT,0); //glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT32,m_screenWidth,m_screenHeight,0,GL_DEPTH_COMPONENT,GL_FLOAT,0); glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, shadowMapWidth, shadowMapHeight, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); float l_ClampColor[] = {1.0, 1.0, 1.0, 1.0}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, l_ClampColor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); m_data->m_shadowMap=new GLRenderToTexture(); m_data->m_shadowMap->init(shadowMapWidth, shadowMapHeight,m_data->m_shadowTexture,RENDERTEXTURE_DEPTH); } m_data->m_shadowMap->enable(); glViewport(0,0,shadowMapWidth,shadowMapHeight); //glClearColor(1,1,1,1); glClear(GL_DEPTH_BUFFER_BIT); //glClearColor(0.3,0.3,0.3,1); // m_data->m_shadowMap->disable(); // return; // glEnable(GL_CULL_FACE); // glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles GLint err = glGetError(); b3Assert(err==GL_NO_ERROR); } static b3Vector3 lightPos = b3MakeVector3(-5.f,200,-40);//20,15,10);//-13,6,2);// = b3Vector3(0.5f,2,2); // lightPos.y+=0.1f; b3CreateOrtho(-shadowMapWorldSize,shadowMapWorldSize,-shadowMapWorldSize,shadowMapWorldSize,1,300,depthProjectionMatrix);//-14,14,-14,14,1,200, depthProjectionMatrix); float depthViewMatrix[4][4]; b3Vector3 center = b3MakeVector3(0,0,0); b3Vector3 up =b3MakeVector3(0,1,0); b3CreateLookAt(lightPos,center,up,&depthViewMatrix[0][0]); //b3CreateLookAt(lightPos,m_data->m_cameraTargetPosition,b3Vector3(0,1,0),(float*)depthModelViewMatrix2); GLfloat depthModelMatrix[4][4]; b3CreateDiagonalMatrix(1.f,depthModelMatrix); b3Matrix4x4Mul(depthViewMatrix, depthModelMatrix, depthModelViewMatrix); GLfloat depthMVP[4][4]; b3Matrix4x4Mul(depthProjectionMatrix,depthModelViewMatrix,depthMVP); GLfloat biasMatrix[4][4]={ 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0 }; GLfloat depthBiasMVP[4][4]; b3Matrix4x4Mul(biasMatrix,depthMVP,depthBiasMVP); //float m_frustumZNear=0.1; //float m_frustumZFar=100.f; //b3CreateFrustum(-m_frustumZNear, m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar,(float*)depthProjectionMatrix); //b3CreateLookAt(lightPos,m_data->m_cameraTargetPosition,b3Vector3(0,0,1),(float*)depthModelViewMatrix); { B3_PROFILE("updateCamera"); updateCamera(); } err = glGetError(); b3Assert(err==GL_NO_ERROR); // glBindBuffer(GL_ARRAY_BUFFER, 0); { B3_PROFILE("glFlush2"); glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo); glFlush(); } err = glGetError(); b3Assert(err==GL_NO_ERROR); int totalNumInstances = 0; for (int i=0;i<m_graphicsInstances.size();i++) { totalNumInstances+=m_graphicsInstances[i]->m_numGraphicsInstances; } int curOffset = 0; GLuint lastBindTexture = 0; for (int i=0;i<m_graphicsInstances.size();i++) { b3GraphicsInstance* gfxObj = m_graphicsInstances[i]; if (gfxObj->m_numGraphicsInstances) { glActiveTexture(GL_TEXTURE0); GLuint curBindTexture = 0; if (gfxObj->m_texturehandle) curBindTexture = gfxObj->m_texturehandle; else curBindTexture = m_data->m_defaultTexturehandle; //if (lastBindTexture != curBindTexture) { glBindTexture(GL_TEXTURE_2D,curBindTexture); } lastBindTexture = curBindTexture; err = glGetError(); b3Assert(err==GL_NO_ERROR); // int myOffset = gfxObj->m_instanceOffset*4*sizeof(float); int POSITION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); int ORIENTATION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); int COLOR_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); // int SCALE_BUFFER_SIZE = (totalNumInstances*sizeof(float)*3); glBindVertexArray(gfxObj->m_cube_vao); int vertexStride = 9*sizeof(float); int vertexBase = gfxObj->m_vertexArrayOffset*vertexStride; glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid*)vertexBase); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes)); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE)); int uvoffset = 7*sizeof(float)+vertexBase; int normaloffset = 4*sizeof(float)+vertexBase; glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE)); glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*3*sizeof(float)+m_maxShapeCapacityInBytes+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); glVertexAttribDivisorARB(0, 0); glVertexAttribDivisorARB(1, 1); glVertexAttribDivisorARB(2, 1); glVertexAttribDivisorARB(3, 0); glVertexAttribDivisorARB(4, 0); glVertexAttribDivisorARB(5, 1); glVertexAttribDivisorARB(6, 1); int indexCount = gfxObj->m_numIndices; int indexOffset = 0; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo); { B3_PROFILE("glDrawElementsInstanced"); if (gfxObj->m_primitiveType==B3_GL_POINTS) { glUseProgram(instancingShaderPointSprite); glUniformMatrix4fv(ProjectionMatrixPointSprite, 1, false, &projectionMatrix[0]); glUniformMatrix4fv(ModelViewMatrixPointSprite, 1, false, &modelviewMatrix[0]); glUniform1f(screenWidthPointSprite,m_screenWidth); //glUniform1i(uniform_texture_diffusePointSprite, 0); err = glGetError(); b3Assert(err==GL_NO_ERROR); glPointSize(20); #ifndef __APPLE__ glEnable(GL_POINT_SPRITE_ARB); // glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); #endif glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glDrawElementsInstanced(GL_POINTS, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); } else { switch (renderMode) { case B3_DEFAULT_RENDERMODE: { glUseProgram(instancingShader); glUniformMatrix4fv(ProjectionMatrix, 1, false, &projectionMatrix[0]); glUniformMatrix4fv(ModelViewMatrix, 1, false, &modelviewMatrix[0]); glUniform1i(uniform_texture_diffuse, 0); glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); break; } case B3_CREATE_SHADOWMAP_RENDERMODE: { glUseProgram(createShadowMapInstancingShader); glUniformMatrix4fv(createShadow_depthMVP, 1, false, &depthMVP[0][0]); glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); break; } case B3_USE_SHADOWMAP_RENDERMODE: { glUseProgram(useShadowMapInstancingShader); glUniformMatrix4fv(useShadow_ProjectionMatrix, 1, false, &projectionMatrix[0]); glUniformMatrix4fv(useShadow_ModelViewMatrix, 1, false, &modelviewMatrix[0]); float MVP[16]; b3Matrix4x4Mul16(projectionMatrix,modelviewMatrix,MVP); glUniformMatrix4fv(useShadow_MVP, 1, false, &MVP[0]); glUniformMatrix4fv(useShadow_DepthBiasModelViewMatrix, 1, false, &depthBiasMVP[0][0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, m_data->m_shadowTexture); glUniform1i(useShadow_shadowMap,1); glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); break; } default: { // b3Assert(0); } }; } //glDrawElementsInstanced(GL_LINE_LOOP, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); } } curOffset+= gfxObj->m_numGraphicsInstances; } { B3_PROFILE("glFlush"); glFlush(); } if (renderMode==B3_CREATE_SHADOWMAP_RENDERMODE) { // writeTextureToPng(shadowMapWidth,shadowMapHeight,"shadowmap.png",4); m_data->m_shadowMap->disable(); glViewport(dims[0],dims[1],dims[2],dims[3]); } err = glGetError(); b3Assert(err==GL_NO_ERROR); { B3_PROFILE("glUseProgram(0);"); glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindVertexArray(0); } err = glGetError(); b3Assert(err==GL_NO_ERROR); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBInstancedArrays_nglVertexAttribDivisorARB(JNIEnv *env, jclass clazz, jint index, jint divisor, jlong function_pointer) { glVertexAttribDivisorARBPROC glVertexAttribDivisorARB = (glVertexAttribDivisorARBPROC)((intptr_t)function_pointer); glVertexAttribDivisorARB(index, divisor); }
/* * bindShaders - bind buffer data and pass shader variables. * code based on example in http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/particles-instancing/ */ void ParticleSystem::bindShaders() { /* Update the buffers that OpenGL uses for rendering */ glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLfloat) * 4, position_size_data); glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLubyte) * 4, color_data); glBindBuffer(GL_ARRAY_BUFFER, particles_age_buffer); glBufferData(GL_ARRAY_BUFFER, max_particles * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details. glBufferSubData(GL_ARRAY_BUFFER, 0, active_particles * sizeof(GLfloat), age_data); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Use our shader glUseProgram(programID); // Bind our texture in Texture Unit 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i(texture_ID, 0); glUniform3f(CameraRight_worldspace_ID, model_view[0][0], model_view[1][0], model_view[2][0]); glUniform3f(CameraUp_worldspace_ID, model_view[0][1], model_view[1][1], model_view[2][1]); glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &model_projection[0][0]); /* billboard vertices */ glEnableVertexAttribArray(squareVerticesID); glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer); glVertexAttribPointer(squareVerticesID, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); /* bind particle attributes */ /* positions of particles' centers */ glEnableVertexAttribArray(xyzsID); glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer); glVertexAttribPointer(xyzsID, 4, GL_FLOAT, GL_FALSE, 0, (void *)0); /* particles' colors */ glEnableVertexAttribArray(colorID); glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer); glVertexAttribPointer(colorID, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void *)0); /* particles' age */ glEnableVertexAttribArray(ageID); glBindBuffer(GL_ARRAY_BUFFER, particles_age_buffer); glVertexAttribPointer(ageID, 1, GL_FLOAT, GL_TRUE, 0, (void *)0); glVertexAttribDivisorARB(squareVerticesID, 0); // particles vertices : always reuse the same 4 vertices -> 0 glVertexAttribDivisorARB(xyzsID, 1); // positions: one per quad (its center) -> 1 glVertexAttribDivisorARB(colorID, 1); // color: one per quad -> 1 glVertexAttribDivisorARB(ageID, 1); /* age: one per quad */ /* draw each instance */ glDrawArraysInstancedARB(GL_TRIANGLE_STRIP, 0, 4, active_particles); glDisableVertexAttribArray(squareVerticesID); glDisableVertexAttribArray(xyzsID); glDisableVertexAttribArray(colorID); glDisableVertexAttribArray(ageID); }
void InstancingApp::Initialize(void) { GLenum err = glewInit(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); } instancingProg = gltLoadShaderPair("instancing.vs", "instancing.fs"); glBindAttribLocation(instancingProg, 0, "position"); glBindAttribLocation(instancingProg, 1, "instance_color"); glBindAttribLocation(instancingProg, 2, "instance_position"); glLinkProgram(instancingProg); glUseProgram(instancingProg); static const GLfloat square_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }; static const GLfloat instance_colors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; static const GLfloat instance_positions[] = { -2.0f, -2.0f, 0.0f, 0.0f, 2.0f, -2.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.0f, 0.0f, -2.0f, 2.0f, 0.0f, 0.0f }; GLuint offset = 0; glGenVertexArrays(1, &square_vao); glGenBuffers(1, &square_vbo); glBindVertexArray(square_vao); glBindBuffer(GL_ARRAY_BUFFER, square_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(square_vertices) + sizeof(instance_colors) + sizeof(instance_positions), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(square_vertices), square_vertices); offset += sizeof(square_vertices); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(instance_colors), instance_colors); offset += sizeof(instance_colors); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(instance_positions), instance_positions); offset += sizeof(instance_positions); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)sizeof(square_vertices)); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(square_vertices) + sizeof(instance_colors))); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glVertexAttribDivisorARB(1, 1); glVertexAttribDivisorARB(2, 1); }
static GLboolean test_instancing(GLuint divisor) { static const GLfloat verts[4][2] = { {-1, -1}, {1, -1}, {1, 1}, {-1, 1} }; GLuint vbo; uintptr_t offset = 0; if (use_vbo) { glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(Positions) + sizeof(Colors), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(verts), verts); glVertexPointer(2, GL_FLOAT, 0, (void*) offset); offset += sizeof(verts); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(Positions), Positions); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*) offset); offset += sizeof(Positions); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(Colors), Colors); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, (void*) offset); offset += sizeof(Colors); glBindBuffer(GL_ARRAY_BUFFER, 0); } else { glVertexPointer(2, GL_FLOAT, 0, verts); glVertexAttribPointer(PosAttrib, 2, GL_FLOAT, GL_FALSE, 0, Positions); glVertexAttribPointer(ColorAttrib, 4, GL_FLOAT, GL_FALSE, 0, Colors); } glEnableClientState(GL_VERTEX_ARRAY); glEnableVertexAttribArray(PosAttrib); glEnableVertexAttribArray(ColorAttrib); glVertexAttribDivisorARB(PosAttrib, 1); /* advance color once every 'n' instances */ glVertexAttribDivisorARB(ColorAttrib, divisor); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(Program); glDrawArraysInstancedARB(GL_POLYGON, 0, 4, PRIMS); glUseProgram(0); if (use_vbo) { glDeleteBuffers(1, &vbo); } { GLint i; GLint pos[4]; for (i = 0; i < PRIMS; i++) { GLuint elem = i / divisor; /* use glRasterPos to determine where to read a sample pixel */ glRasterPos2fv(Positions[i]); glGetIntegerv(GL_CURRENT_RASTER_POSITION, pos); if (!piglit_probe_pixel_rgba(pos[0], pos[1], Colors[elem])) { fprintf(stderr, "%s: instance %d failed to draw correctly\n", TestName, i); fprintf(stderr, "%s: color instance divisor = %u\n", TestName, divisor); piglit_present_results(); return GL_FALSE; } } } glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(PosAttrib); glDisableVertexAttribArray(ColorAttrib); piglit_present_results(); return GL_TRUE; }