// enable clipping to rectangle static void setClipArea(struct SaslGraphicsCallbacks *canvas, double x, double y, double width, double height) { OglCanvas *c = (OglCanvas*)canvas; assert(canvas); dumpBuffers(c); int oldLevel = c->clipAreas.size(); if (! oldLevel) { glClear(GL_STENCIL_BUFFER_BIT); glEnable(GL_STENCIL_TEST); } Rect r = { x, y, width, height }; c->clipAreas.push_back(r); glEnable(GL_STENCIL_TEST); glStencilMask(255); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); glStencilFunc(GL_EQUAL, oldLevel, 0xFFFFffff); drawStencilRect(c, r); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, oldLevel+1, 0xFFFFffff); }
CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType) : m_meshType(meshType) , m_points(columns + 1, rows + 1) , m_tiles(columns, rows) , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height()) , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height()) , m_meshBox(meshBox) { // Build the two buffers needed to draw triangles: // * m_vertices has a number of float attributes that will be passed to the vertex shader // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType. // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside // the m_vertices buffer. m_vertices.reserveCapacity(verticesCount() * floatsPerVertex()); m_indices.reserveCapacity(indicesCount()); // Based on the meshType there can be two types of meshes. // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory // when there's no need to explode the tiles. // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3 // attribute is passed, so that each vertex can be uniquely identified. if (m_meshType == MeshTypeAttached) generateAttachedMesh(); else generateDetachedMesh(); #ifndef NDEBUG if (s_dumpCustomFilterMeshBuffers) dumpBuffers(); #endif }
// disable clipping. static void resetClipArea(struct SaslGraphicsCallbacks *canvas) { OglCanvas *c = (OglCanvas*)canvas; assert(canvas); // TODO: implement it. see notes in setClipArea dumpBuffers(c); int curLevel = c->clipAreas.size(); if (! curLevel) return; Rect &r = c->clipAreas.back(); glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); glStencilFunc(GL_EQUAL, curLevel, 0xFFFFffff); drawStencilRect(c, r); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, curLevel-1, 0xFFFFffff); c->clipAreas.pop_back(); if (c->clipAreas.empty()) glDisable(GL_STENCIL_TEST); }
// switch primitives to draw static void setMode(OglCanvas *c, int mode) { if (c->currentMode != mode) { if (c->numVertices) c->batchLines++; dumpBuffers(c); c->currentMode = mode; } }
// stop texturing static void disableTexture(OglCanvas *c) { if (c->currentTexture) { if (c->numVertices) c->batchNoTex++; dumpBuffers(c); glDisable(GL_TEXTURE_2D); c->currentTexture = 0; } }
// draw rectangle in stencil buffer only static void drawStencilRect(OglCanvas *c, Rect &r) { glColorMask(false, false, false, false); drawTriangle((SaslGraphicsCallbacks*)c, r.x, r.y + r.height, 0, 0, 0, 0, r.x + r.width, r.y + r.height, 0, 0, 0, 0, r.x + r.width, r.y, 0, 0, 0, 0); drawTriangle((SaslGraphicsCallbacks*)c, r.x, r.y + r.height, 0, 0, 0, 0, r.x + r.width, r.y, 0, 0, 0, 0, r.x, r.y, 0, 0, 0, 0); glColorMask(true, true, true, true); dumpBuffers(c); }
// start texturing static void setTexture(OglCanvas *c, int texId) { if (c->currentTexture != texId) { if (c->numVertices) c->batchTex++; dumpBuffers(c); if (! c->currentTexture) glEnable(GL_TEXTURE_2D); if (c->binderCallback) c->binderCallback(texId); else glBindTexture(GL_TEXTURE_2D, texId); c->currentTexture = texId; } }
/// flush drawed graphics to screen static void drawEnd(struct SaslGraphicsCallbacks *canvas) { OglCanvas *c = (OglCanvas*)canvas; assert(canvas); dumpBuffers(c); #ifndef USE_GLES1 glPopAttrib(); glPopClientAttrib(); #endif /* printf("textures: %i (%i Kb) triangles: %i lines: %i batches: %i\n", c->textures, c->texturesSize / 1024, c->triangles, c->lines, c->batches); printf("batches reasons: textures: %i translation: %i notex: %i " "lines: %i\n", c->batchTex, c->batchTrans, c->batchNoTex, c->batchLines);*/ }
// start rendering to texture // pass -1 as texture ID to restore default render target static int setRenderTarget(struct SaslGraphicsCallbacks *canvas, int textureId) { OglCanvas *c = (OglCanvas*)canvas; assert(canvas); dumpBuffers(c); if (! c->fboAvailable) { printf("fbo not available\n"); return -1; } if (-1 != textureId) { // save state glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glPushAttrib(GL_ALL_ATTRIB_BITS); glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); GLint w, h; glBindTexture(GL_TEXTURE_2D, textureId); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); // enable fbo c->defaultFbo = getCurrentFbo(); GLuint fbo = getFbo(c, textureId); if ((GLuint)-1 == fbo) { printf("can't create fbo\n"); return -1; } c->currentFboTex = textureId; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); prepareFbo(c, textureId, w, h); } else { // restore default fbo glBindFramebuffer(GL_DRAW_FRAMEBUFFER, c->defaultFbo); glBindTexture(GL_TEXTURE_2D, c->currentFboTex); glGenerateMipmap(GL_TEXTURE); glBindTexture(GL_TEXTURE_2D, 0); // restore x-plane state glPopClientAttrib(); glPopAttrib(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); if (c->currentTexture) glBindTexture(GL_TEXTURE_2D, c->currentTexture); c->transform.pop_back(); } return 0; }