void onDraw(Graphics& g){ g.pointSize(renderMode+0.5); g.color(RGB(1)); mesh.colors().reset(); switch (renderMode) { case 0: // do it on the CPU: for (int k=0; k<N; k++) { for (int j=0; j<N; j++) { for (int i=0; i<N; i++) { Color color; data.read_interp(color.components, i,j,k); mesh.color(color); }}} g.draw(mesh); break; case 1: // use 3D texcoords: tex.bind(); g.draw(mesh); tex.unbind(); break; case 2: // use shader: shader.begin(); tex.bind(); g.draw(mesh); tex.unbind(); shader.end(); break; default:; } }
inline void OmniStereoGraphicsRenderer::onDrawOmni(OmniStereo& omni) { graphics().error("start onDraw"); mShader.begin(); mOmni.uniforms(mShader); graphics().pushMatrix(graphics().MODELVIEW); onDraw(graphics()); graphics().popMatrix(graphics().MODELVIEW); mShader.end(); }
inline bool OmniStereoGraphicsRenderer::onCreate() { mOmni.onCreate(); Shader vert, frag; vert.source(OmniStereo::glsl() + vertexCode(), Shader::VERTEX).compile(); vert.printLog(); frag.source(fragmentCode(), Shader::FRAGMENT).compile(); frag.printLog(); mShader.attach(vert).attach(frag).link(); mShader.printLog(); mShader.begin(); mShader.uniform("lighting", 0.0); mShader.uniform("texture", 0.0); mShader.end(); return true; }
void run() { if(!initialize()) shutdown("Failed to initialize"); if(!loadContent()) shutdown("Failed to load resources"); Mesh cubeMesh = Mesh::genUnitColoredCube(); MeshBuffer cubeBuffer(cubeMesh); Model cube(cubeBuffer); Mesh waterMesh = Mesh::genUnitColoredPlane(Color(0.57f, 0.63f, 0.98f)); MeshBuffer waterBuffer(waterMesh); Model water(waterBuffer); BufferObject quadVbo; float quadVertices[] = { -1.0f, -1.0f, 0.0f, 0.0f, +1.0f, -1.0f, 1.0f, 0.0f, +1.0f, +1.0f, 1.0f, 1.0f, +1.0f, +1.0f, 1.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f }; quadVbo.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, sizeof(quadVertices), quadVertices); Mesh gridMesh; for(int i = 0; i <= 8; ++i) { float f = (i / 8.0) * 2.0f - 1.0f; int j = gridMesh.getPositionCount(); gridMesh.addPosition(f * 3.0f, 0.0f, -3.0f); gridMesh.addPosition(f * 3.0f, 0.0f, +3.0f); gridMesh.addPosition(-3.0f, 0.0f, f * 3.0f); gridMesh.addPosition(+3.0f, 0.0f, f * 3.0f); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addIndex(j + 0); gridMesh.addIndex(j + 1); gridMesh.addIndex(j + 2); gridMesh.addIndex(j + 3); } MeshBuffer gridBuffer(gridMesh); Model grid(gridBuffer); VertexArray vao; vao.create(); vao.bind(); mat4 perspectiveMatrix = glm::perspective(45.0f, windowWidth / float(windowHeight), 0.05f, 50.0f); // The geometry to be refracted and reflected are stored in these // In addition to RGB values, the world-space height is stored in the alpha-channel // of the refraction texture. // Fresnel equations is used to blend between the two textures RenderTexture refractionRT(windowWidth, windowHeight); RenderTexture reflectionRT(windowWidth, windowHeight); renderer.setClearColor(0.55f, 0.45f, 0.45f, 1.0f); renderer.setClearDepth(1.0); Timer timer; timer.start(); double renderTime = 0.0; while(context.isOpen()) { timer.step(); double time = timer.getElapsedTime(); update(time, timer.getDelta()); double renderStart = timer.getElapsedTime(); MatrixStack viewMatrix; viewMatrix.push(); viewMatrix.translate(0.0f, 0.0f, -3.0f); viewMatrix.rotateX(xAxisRotation); viewMatrix.rotateY(yAxisRotation); renderer.setCullState(CullStates::CullNone); renderer.setDepthTestState(DepthTestStates::LessThanOrEqual); colorShader.begin(); colorShader.setUniform("projection", perspectiveMatrix); cube.pushTransform(); cube.translate(0.0f, 0.0f, 0.0f); cube.scale(0.5f); // Render the geometry to be refracted, store result in rt refractionRT.begin(); renderer.clearColorAndDepth(); colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); grid.draw(GL_LINES); refractionRT.end(); // Render the geometry to be reflected, store result in rt reflectionRT.begin(); renderer.clearColorAndDepth(); viewMatrix.push(); viewMatrix.scale(1.0f, -1.0f, 1.0f); // Reflect about xz-plane colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); viewMatrix.pop(); reflectionRT.end(); colorShader.end(); cube.popTransform(); // Render the water with the previous reflection/refraction texture waterShader.begin(); waterShader.setUniform("time", time); glActiveTexture(GL_TEXTURE0 + 0); refractionRT.bindTexture(); glActiveTexture(GL_TEXTURE0 + 1); reflectionRT.bindTexture(); glActiveTexture(GL_TEXTURE0 + 2); waterNormals.bind(); //waterShader.setUniform("view", viewMatrix.top()); waterShader.setUniform("refraction_tex", 0); waterShader.setUniform("reflection_tex", 1); waterShader.setUniform("water_normals_tex", 2); //waterShader.setUniform("light0_pos", vec3(0.0f, 1.0f, 0.0f)); //waterShader.setUniform("light0_col", vec3(1.0f, 0.8f, 0.5f)); //waterShader.setUniform("ambient", vec3(67.0f/255.0f, 66.0f/255.0f, 63.0f/255.0f)); quadVbo.bind(); waterShader.setAttributefv("position", 2, 4, 0); waterShader.setAttributefv("texel", 2, 4, 2); glDrawArrays(GL_TRIANGLES, 0, 6); quadVbo.unbind(); reflectionRT.unbindTexture(); refractionRT.unbindTexture(); waterNormals.unbind(); waterShader.end(); glActiveTexture(GL_TEXTURE0 + 0); // Render unmirrored scene //colorShader.begin(); //renderer.clearColorAndDepth(); //renderer.setCullState(CullStates::CullNone); //renderer.setBlendState(BlendStates::AlphaBlend); //renderer.setDepthTestState(DepthTestStates::LessThanOrEqual); //colorShader.setUniform("projection", perspectiveMatrix); //colorShader.setUniform("view", viewMatrix.top()); //cube.pushTransform(); //cube.translate(0.0f, 0.4f, 0.0f); //cube.scale(0.5f); //cube.draw(GL_TRIANGLES); /*grid.pushTransform(); grid.translate(0.0f, -0.5f, 0.0f); grid.draw(GL_LINES); grid.popTransform();*/ // Draw mirrored scene to a rendertarget /*rt.begin(); renderer.clearColorAndDepth(); viewMatrix.push(); viewMatrix.scale(1.0f, -1.0f, 1.0f); colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); cube.popTransform(); viewMatrix.pop(); rt.end();*/ // Enable stencil testing and mask out a section containing the water mesh //glEnable(GL_STENCIL_TEST); //glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1 //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); //glStencilMask(0xFF); // Write to stencil buffer //glDepthMask(GL_FALSE); // Don't write to depth buffer //glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default) //// Draw water mesh //water.pushTransform(); //water.scale(3.0f); //water.draw(GL_TRIANGLES); //water.popTransform(); //colorShader.end(); //// Draw previous rendertarget as a quad masked into the water plane //glStencilFunc(GL_EQUAL, 1, 0xFF); // Pass test if stencil value is 1 //glStencilMask(0x00); // Don't write anything to stencil buffer //glDepthMask(GL_TRUE); //glDisable(GL_STENCIL_TEST); viewMatrix.pop(); context.display(); renderTime = timer.getElapsedTime() - renderStart; if(renderTime < 0.013) context.sleep(0.013 - renderTime); if(checkGLErrors(std::cerr)) { std::cin.get(); context.close(); } } waterNormals.dispose(); colorShader.dispose(); waterShader.dispose(); vao.dispose(); context.dispose(); }
int main(int argc, char** argv) { SDL_Window* window; SDL_GLContext ctx; GLuint vao; if(!initSDL(&window, &ctx) || !initGLEW()) { return false; } // Create camera Camera camera(glm::radians(60.0f), static_cast<float>(width)/static_cast<float>(height), 0.000001f, 1000.0f); camera.getTransform()->setPosition(0.0f,0.0f,5.0f); VertexShader vs; FragmentShader fs; ShaderProgram shaderProg; WavefrontMeshFactory factory; Mesh* mesh = factory.load("../../wreck/assets/uvcube.obj"); if(!vs.load("../../wreck/assets/lambert.vs")) std::cout << "Vertex Shader error." << std::endl; if(!fs.load("../../wreck/assets/lambert.fs")) std::cout << "Fragment shader error." << std::endl; Texture texture; texture.load("../../wreck/assets/uvpattern.dds"); Light light(glm::vec3(5.0f, 5.0f, 5.0f), glm::vec3(1.0f, 1.0f, 1.0f)); light.setIntensity(1.0f); std::cout << "Linking..." << std::endl; shaderProg.setVertexShader(&vs); shaderProg.setFragmentShader(&fs); shaderProg.link(); //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Uint32 ticks = SDL_GetTicks(); bool running = true; while(running) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SDL_Event event; while(SDL_PollEvent(&event)) { Uint32 elapsed = SDL_GetTicks()-ticks; ticks = SDL_GetTicks(); switch (event.type) { case SDL_KEYDOWN: keyboardCameraControl(event, camera, elapsed); break; case SDL_KEYUP: // if escape is pressed, quit if (event.key.keysym.sym == SDLK_ESCAPE) running = false; // set status to 1 to exit main loop break; case SDL_MOUSEMOTION: mouseCameraControl(event, window, camera, elapsed); break; case SDL_QUIT: running = false; break; } } glm::vec3 lightPos = light.getTransform()->getPosition(); glm::vec3 lightColor = light.getColor() * light.getIntensity(); glm::vec4 diffuse = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); glm::mat4 m = glm::mat4(1.0f); glm::mat4 v = camera.getViewMatrix(); glm::mat4 p = camera.getProjectionMatrix(); glm::mat4 mvp = p*v*m; // Begin drawing shaderProg.begin(); mesh->use(); texture.use(); shaderProg.setUniformValue(0, mvp); shaderProg.setUniformValue(1, m); shaderProg.setUniformValue(2, v); shaderProg.setUniformValue(3, lightPos); shaderProg.setUniformValue(4, lightColor); //shaderProg.setUniformValue(1, diffuse); glDrawElements(GL_TRIANGLES, mesh->indices.size(), GL_UNSIGNED_INT, 0); shaderProg.end(); SDL_GL_SwapWindow(window); } SDL_GL_DeleteContext(ctx); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
bool onFrame(){ gl.clearColor(0.1, 0.1, 0.1, 1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.viewport(0,0, width(), height()); gl.matrixMode(gl.PROJECTION); gl.loadMatrix(Matrix4d::perspective(45, aspect(), 0.1, 100)); gl.matrixMode(gl.MODELVIEW); gl.loadMatrix(Matrix4d::lookAt(Vec3d(0,0,4), Vec3d(0,0,0), Vec3d(0,1,0))); gl.disable(gl.LIGHTING); // shaderprogram.begin(); // shaderprogram.uniform("tex0", 0); // GraphicsGL::gl_error("shader"); // tex.bind(0); // gl.begin(gl.QUADS); // gl.color(1, 1, 1); // gl.texCoord(0, 0); // gl.vertex(0, 0, 0); // gl.texCoord(0, 1); // gl.vertex(0, 1, 0); // gl.texCoord(1, 1); // gl.vertex(1, 1, 0); // gl.texCoord(1, 0); // gl.vertex(1, 0, 0); // gl.end(); // tex.unbind(0); // shaderprogram.end(); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // Uses default lighting parameters glEnable(GL_DEPTH_TEST); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glEnable(GL_NORMALIZE); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); const GLfloat pos[]={ 1.f, 1.f, 2.f, 0.f }; glLightfv(GL_LIGHT0, GL_POSITION, pos); // gl.enable(gl.DEPTH_TEST); //// gl.enable(gl.NORMALIZE); // light.twoSided(true); // light.dir(1.f, 1.f, 2.f); // // light(); // material(); // glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); gl.pushMatrix(); // rotate it around the y axis gl.rotate(a, 0.f,1.f,0.f); a += 0.5; // scale the whole asset to fit into our view frustum float tmp = scene_max[0]-scene_min[0]; tmp = al::max(scene_max[1] - scene_min[1],tmp); tmp = al::max(scene_max[2] - scene_min[2],tmp); tmp = 2.f / tmp; gl.scale(tmp); // center the model gl.translate( -scene_center ); shaderprogram.begin(); shaderprogram.uniform("tex0", 1); Graphics::error("tex0"); tex.bind(1); scene_list.draw(); tex.unbind(1); shaderprogram.end(); gl.popMatrix(); return true; }
void ModelRendererGl::renderMesh(const Mesh *mesh, float fade, int frame, int id, ShaderProgram *customShaders) { //assertions assertGl(); const RenderMode &mode = m_renderMode; if (mode == RenderMode::SELECTION && mesh->isNoSelect()) { return; } bool renderTextures = (mode == RenderMode::UNITS || mode == RenderMode::OBJECTS || mode == RenderMode::SHADOWS); bool sendNormals = (mode == RenderMode::UNITS || mode == RenderMode::OBJECTS); // set cull face if (mesh->isTwoSided()) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } // mesh colour (units only, tileset objects use colour set by engine based on FoW tex) if (m_renderMode == RenderMode::UNITS) { Vec4f color(mesh->getDiffuseColor(), std::min(mesh->getOpacity(), fade)); glColor4fv(color.ptr()); } const Texture2DGl *texture = 0, *textureNormal = 0, *textureCustom = 0; // diffuse texture glActiveTexture(diffuseTextureUnit); texture = static_cast<const Texture2DGl*>(mesh->getTexture(MeshTexture::DIFFUSE)); if (texture != NULL && renderTextures) { if (m_lastTexture != texture->getHandle()) { assert(glIsTexture(texture->getHandle())); glBindTexture(GL_TEXTURE_2D, texture->getHandle()); m_lastTexture = texture->getHandle(); } } else { glBindTexture(GL_TEXTURE_2D, 0); m_lastTexture = 0; } // bump map textureNormal = static_cast<const Texture2DGl*>(mesh->getTexture(MeshTexture::NORMAL)); glActiveTexture(normalTextureUnit); if (textureNormal != NULL && sendNormals) { assert(glIsTexture(textureNormal->getHandle())); glBindTexture(GL_TEXTURE_2D, textureNormal->getHandle()); } else { glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } // custom map if (customShaders && renderTextures) { textureCustom = static_cast<const Texture2DGl*>(mesh->getTexture(MeshTexture::CUSTOM)); glActiveTexture(customTextureUnit); if (textureCustom) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureCustom->getHandle()); } else { glDisable(GL_TEXTURE_2D); } } glActiveTexture(diffuseTextureUnit); //misc vars uint32 vertexCount = mesh->getVertexCount(); uint32 indexCount = mesh->getIndexCount(); //assertions assertGl(); if (!vertexCount) { return; } ShaderProgram *shaderProgram; if (m_shaderIndex == -1 || mode == RenderMode::SELECTION || mode == RenderMode::SHADOWS) { shaderProgram = m_fixedFunctionProgram; if (m_meshCallback) { m_meshCallback->execute(mesh); } } else { if (customShaders) { shaderProgram = customShaders; } else { shaderProgram = m_shaders[m_shaderIndex]; } } if (shaderProgram != m_lastShaderProgram) { if (m_lastShaderProgram) { m_lastShaderProgram->end(); } shaderProgram->begin(); shaderProgram->setUniform("gae_IsUsingFog", GLuint(m_useFog)); m_lastShaderProgram = shaderProgram; } ///@todo would be better to do this once only per faction, set from the game somewhere/somehow shaderProgram->setUniform("gae_TeamColour", getTeamColour()); int teamColourFlag = (mesh->usesTeamTexture() && mode == RenderMode::UNITS) ? 1 : 0; shaderProgram->setUniform("gae_UsesTeamColour", teamColourFlag); shaderProgram->setUniform("gae_AlphaThreshold", m_alphaThreshold); shaderProgram->setUniform("gae_LightCount", m_currentLightCount); if (customShaders) { shaderProgram->setUniform("gae_FrameNumber", frame); shaderProgram->setUniform("gae_EntityId", id); } // vertices const MeshVertexBlock *mainBlock = 0; const MeshVertexBlock &staticBlock = mesh->getStaticVertData(); if (staticBlock.count != 0) { mainBlock = &staticBlock; } else { mainBlock = &mesh->getInterpolationData()->getVertexBlock(); } const int stride = mainBlock->getStride(); int tanAttribLoc = -1; if (mainBlock->vbo_handle) { # define VBO_OFFSET(x) ((void*)(x * sizeof(float))) glBindBuffer(GL_ARRAY_BUFFER, mainBlock->vbo_handle); glVertexPointer(3, GL_FLOAT, stride, VBO_OFFSET(0)); if (sendNormals) { glNormalPointer(GL_FLOAT, stride, VBO_OFFSET(3)); } if (sendNormals && textureNormal && (mainBlock->type == MeshVertexBlock::POS_NORM_TAN || mainBlock->type == MeshVertexBlock::POS_NORM_TAN_UV)) { shaderProgram->setUniform("gae_HasNormalMap", 1u); tanAttribLoc = shaderProgram->getAttribLoc("gae_Tangent"); if (tanAttribLoc != -1) { glEnableVertexAttribArray(tanAttribLoc); glVertexAttribPointer(tanAttribLoc, 3, GL_FLOAT, GL_TRUE, stride, VBO_OFFSET(6)); } } else { shaderProgram->setUniform("gae_HasNormalMap", 0u); } if (renderTextures && mesh->getTexture(MeshTexture::DIFFUSE)) { int uvOffset = mainBlock->getUvOffset(); if (uvOffset != -1) { if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, stride, VBO_OFFSET(uvOffset)); } glActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, stride, VBO_OFFSET(uvOffset)); } else { const MeshVertexBlock &uvBlock = mesh->getTecCoordBlock(); assert(uvBlock.count != 0); glBindBuffer(GL_ARRAY_BUFFER, uvBlock.vbo_handle); if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, VBO_OFFSET(0)); } glActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, VBO_OFFSET(0)); } } else { if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } glActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } assertGl(); // draw model glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndices().vbo_handle); int indexType = mesh->getIndices().type == MeshIndexBlock::UNSIGNED_16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, indexType, VBO_OFFSET(0)); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (tanAttribLoc != -1) { glDisableVertexAttribArray(tanAttribLoc); } assertGl(); } else { // Non static mesh or VBOs disabled glVertexPointer(3, GL_FLOAT, stride, mainBlock->m_arrayPtr); if (sendNormals) { glNormalPointer(GL_FLOAT, stride, &mainBlock->m_posNorm[0].norm); } if (sendNormals && textureNormal && (mainBlock->type == MeshVertexBlock::POS_NORM_TAN || mainBlock->type == MeshVertexBlock::POS_NORM_TAN_UV)) { shaderProgram->setUniform("gae_HasNormalMap", 1u); tanAttribLoc = shaderProgram->getAttribLoc("gae_Tangent"); if (tanAttribLoc != -1) { glEnableVertexAttribArray(tanAttribLoc); glVertexAttribPointer(tanAttribLoc, 3, GL_FLOAT, GL_TRUE, stride, &mainBlock->m_posNormTan[0].tan); } } else { shaderProgram->setUniform("gae_HasNormalMap", 0u); } if (renderTextures && mesh->getTexture(MeshTexture::DIFFUSE)) { int uvOffset = mainBlock->getUvOffset(); if (uvOffset != -1) { if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, stride, &((float*)mainBlock->m_arrayPtr)[uvOffset]); } glActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, stride, &((float*)mainBlock->m_arrayPtr)[uvOffset]); } else { const MeshVertexBlock &uvBlock = mesh->getTecCoordBlock(); assert(uvBlock.count != 0); if (uvBlock.vbo_handle) { glBindBuffer(GL_ARRAY_BUFFER, uvBlock.vbo_handle); } if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (uvBlock.vbo_handle) { glTexCoordPointer(2, GL_FLOAT, 0, VBO_OFFSET(0)); } else { glTexCoordPointer(2, GL_FLOAT, 0, uvBlock.m_arrayPtr); } } glActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (uvBlock.vbo_handle) { glTexCoordPointer(2, GL_FLOAT, 0, VBO_OFFSET(0)); } else { glTexCoordPointer(2, GL_FLOAT, 0, uvBlock.m_arrayPtr); } } } else { if (m_duplicateTexCoords) { glActiveTexture(GL_TEXTURE0 + m_secondaryTexCoordUnit); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } glActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } int indexType = mesh->getIndices().type == MeshIndexBlock::UNSIGNED_16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; if (use_vbos) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndices().vbo_handle); glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, indexType, VBO_OFFSET(0)); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else { glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, indexType, mesh->getIndices().m_indices); } if (tanAttribLoc != -1) { glDisableVertexAttribArray(tanAttribLoc); } } assertGl(); }