/*! \brief Draw all the elements in the current buffer multiple * times using instancing. */ inline void drawInstancedElements(element_type::Enum type, size_t instances) { initTest(); bind(buffer_targets::ELEMENT_ARRAY); if (GLEW_EXT_draw_instanced) glDrawElementsInstancedEXT(type, size(), detail::c_type_to_gl_enum<T>::val, 0, instances); else if (GLEW_ARB_draw_instanced) glDrawElementsInstancedEXT(type, size(), detail::c_type_to_gl_enum<T>::val, 0, instances); else M_throw() << "Cannot perform instanced drawing, GL_ARB_draw_instanced/GL_EXT_draw_instanced extensions are missing."; }
inline void VL_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) { if (glDrawElementsInstanced) glDrawElementsInstanced(mode, count, type, indices, primcount); else if (glDrawElementsInstancedARB) glDrawElementsInstancedARB(mode, count, type, indices, primcount); else if (glDrawElementsInstancedEXT) glDrawElementsInstancedEXT(mode, count, type, indices, primcount); else VL_UNSUPPORTED_FUNC(); }
inline void gl_draw_elements_instanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount) { #if defined(__OSX__) glDrawElementsInstanced(mode, count, type, indices, instancecount); #elif defined(__IOS__) #if defined(__OPENGL_20__) glDrawElementsInstancedEXT(mode, count, type, indices, instancecount); #else glDrawElementsInstanced(mode, count, type, indices, instancecount); #endif #endif #if defined(DEBUG) gl_get_error(); #endif }
void display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); if(displayError) { orthographicView(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); txtInstructions.render((screenWidth - txtInstructions.getTextureWidth()) / 2.0f, (screenHeight - txtInstructions.getTextureHeight()) / 2.0f); glFlush(); return; } glPushMatrix(); // Setup the navigation glTranslated(0, 0, -zoom); glRotatef(camRotateX, 1, 0, 0); glRotatef(camRotateY, 0, 1, 0); glTranslated(0, ROOM_SIZE, 0); // Setup drawing for the scene. perspectiveView(); #if _USE_MT // If the render thread needs to wait for new spheres to be added. while(pauseSimulation) { boost::this_thread::yield(); } threadStarted(); #endif renderFrame++; renderFrameCounter++; glEnable(GL_DEPTH_TEST); glColor3f(1.0f, 1.0f, 1.0f); glUseProgram(g_program); glUniform3fv(g_programCameraPositionLocation, 1, g_cameraPosition); glUniform3fv(g_programLightDirectionLocation, 1, g_lightDirection); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sphereMesh.indexBufferId); // We are using instanced rendering, however we cannot draw all the spheres at once. // So we have a maximum number of objects that can be rendered at once and we'll just // render that many at a time until we have less spheres than MAX_OBJECTS_PER_RENDER // left to render. for(int objectIndex = 0; objectIndex < numSpheres; objectIndex += MAX_OBJECTS_PER_RENDER) { int numObjects = MAX_OBJECTS_PER_RENDER; // Are we going to be rendering more spheres than we should? if (numObjects + objectIndex > numSpheres) { numObjects = numSpheres - objectIndex; } Vector3 *positionIndex = spherePositions + objectIndex; glUniform4fv(g_programObjectPositionLocation, numObjects, (float *)positionIndex); // Tell the shader the size of the user sphere. // Due to the way the shader renders multiple instances, it only knows the id // of the current instance it is rendering, which does not reflect the sphere's actual // id. // So we will set that the size of the userSphere only on the first instanced render // and all later renders it will be zero. glUniform1f(g_programUserSphereLocation, (objectIndex == 0) * userSphereSize); glDrawElementsInstancedEXT(GL_TRIANGLES, sphereMesh.numIndicies, GL_UNSIGNED_INT, 0, numObjects); } glUseProgram(0); #if _USE_MT threadStopped(); #endif glPopMatrix(); // Setup drawing for the interface. orthographicView(); char buff[64]; sprintf(buff, "FPS: %d", framesPerSecond); txtRenderFrames.setText(buff); sprintf(buff, "PPS: %.1f", physicsPerSecond); txtPhysicsFrames.setText(buff); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float yPos = -2.0f; txtInstructions.render(10, yPos += 12.0f); txtInstructions2.render(10, yPos += 12.0f); txtNumThreads.render(10, yPos += 12.0f); txtNumSpheres.render(10, yPos += 12.0f); txtRenderFrames.render(10, yPos += 12.0f); txtPhysicsFrames.render(10, yPos += 12.0f); glDisable(GL_BLEND); glFlush(); }
bool drawCallback(CPUTModel* pModel, CPUTRenderParameters &renderParams, CPUTMesh* pMesh, CPUTMaterialEffect* pMaterial, CPUTMaterialEffect* , void* ) { UINT mVertexCount = 0; UINT mIndexCount = 0; int index = 0; float rows = 0.0; float columns = 0.0; float instances = 0.0; float angle_value = 0.0; // Uniform locations GLint vpMatrixBufferLoc = -1; GLint worldMatrixBufferLoc = -1; float4x4 viewProj; float4x4 parents_world; rows = (float) currentRowCount; columns = (float) currentColCount; angle_value = 360.0 / columns; const int numInstances = (int)columns * (int) rows; pMaterial->SetRenderStates(renderParams); parents_world = pModel->GetParentsWorldMatrix(); CPUTCamera *pCamera = renderParams.mpCamera; // Set Uniform Data if(pCamera) { viewProj = *pCamera->GetViewMatrix() * *pCamera->GetProjectionMatrix(); } // Drawing mVertexCount = ((CPUTMeshOGL*)pMesh)->GetVertexCount(); mIndexCount = ((CPUTMeshOGL*)pMesh)->GetIndexCount(); CPUTBufferOGL * mpIndexBuffer = ((CPUTMeshOGL*)pMesh)->GetIndexBuffer(); if(mVertexCount == 0 && mIndexCount == 0) return false; ((CPUTMeshOGL*)pMesh)->EnableVertexArray(); CPUTMaterialEffectOGL *pMatEffect = (CPUTMaterialEffectOGL*) pMaterial; GLuint shaderProgID = pMatEffect->GetShaderID(); vpMatrixBufferLoc = glGetUniformLocation( shaderProgID, "viewProjMatrix" ); worldMatrixBufferLoc = glGetUniformLocation( shaderProgID, "worldMatrix" ); if( isInstanced ) { glUniformMatrix4fv( vpMatrixBufferLoc, 1, GL_FALSE, (const GLfloat *) &viewProj ); glUniformMatrix4fv( worldMatrixBufferLoc, numInstances, GL_FALSE, (const GLfloat *) &world[0] ); if(mpIndexBuffer != NULL) GL_CHECK(glDrawElementsInstancedEXT( GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, NULL, numInstances )); else GL_CHECK(glDrawArraysInstanced(GL_TRIANGLES, 0, numInstances, mVertexCount)); } else { index = 0; glUniformMatrix4fv( vpMatrixBufferLoc, 1, GL_FALSE, (const GLfloat *) &viewProj ); for (int i = 0; i < rows; ++i) { for (int j = 0; j < columns; ++j) { glUniformMatrix4fv( worldMatrixBufferLoc, 1, GL_FALSE, (const GLfloat *) &world[index] ); if(mpIndexBuffer != NULL) GL_CHECK(glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, NULL)); else GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, mVertexCount)); ++index; } } } ((CPUTMeshOGL*)pMesh)->DisableVertexArray(); glUseProgram(0); return true; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_EXTDrawInstanced_nglDrawElementsInstancedEXTBO(JNIEnv *env, jclass clazz, jint mode, jint count, jint type, jlong indices_buffer_offset, jint primcount, jlong function_pointer) { const GLvoid *indices_address = (const GLvoid *)(intptr_t)offsetToPointer(indices_buffer_offset); glDrawElementsInstancedEXTPROC glDrawElementsInstancedEXT = (glDrawElementsInstancedEXTPROC)((intptr_t)function_pointer); glDrawElementsInstancedEXT(mode, count, type, indices_address, primcount); }