void Bitmap::radialBlur(int angle, int divisions) { GUARD_DISPOSED; GUARD_MEGA; angle = clamp<int>(angle, 0, 359); divisions = clamp<int>(divisions, 2, 100); const int _width = width(); const int _height = height(); float angleStep = (float) angle / (divisions-1); float opacity = 1.0f / divisions; float baseAngle = -((float) angle / 2); ColorQuadArray qArray; qArray.resize(5); std::vector<Vertex> &vert = qArray.vertices; int i = 0; /* Center */ FloatRect texRect(0, 0, _width, _height); FloatRect posRect(0, 0, _width, _height); i += Quad::setTexPosRect(&vert[i*4], texRect, posRect); /* Upper */ posRect = FloatRect(0, 0, _width, -_height); i += Quad::setTexPosRect(&vert[i*4], texRect, posRect); /* Lower */ posRect = FloatRect(0, _height*2, _width, -_height); i += Quad::setTexPosRect(&vert[i*4], texRect, posRect); /* Left */ posRect = FloatRect(0, 0, -_width, _height); i += Quad::setTexPosRect(&vert[i*4], texRect, posRect); /* Right */ posRect = FloatRect(_width*2, 0, -_width, _height); i += Quad::setTexPosRect(&vert[i*4], texRect, posRect); for (int i = 0; i < 4*5; ++i) vert[i].color = Vec4(1, 1, 1, opacity); qArray.commit(); TEXFBO newTex = shState->texPool().request(_width, _height); FBO::bind(newTex.fbo, FBO::Draw); glState.clearColor.pushSet(Vec4()); FBO::clear(); Transform trans; trans.setOrigin(Vec2(_width / 2.0f, _height / 2.0f)); trans.setPosition(Vec2(_width / 2.0f, _height / 2.0f)); glState.blendMode.pushSet(BlendAddition); SimpleMatrixShader &shader = shState->shaders().simpleMatrix; shader.bind(); p->bindTexture(shader); TEX::setSmooth(true); p->pushSetViewport(shader); for (int i = 0; i < divisions; ++i) { trans.setRotation(baseAngle + i*angleStep); shader.setMatrix(trans.getMatrix()); qArray.draw(); } p->popViewport(); TEX::setSmooth(false); glState.blendMode.pop(); glState.clearColor.pop(); shState->texPool().release(p->gl); p->gl = newTex; modified(); }
void draw() { if (base.tex.tex == TEX::ID(0)) return; bool windowskinValid = !nullOrDisposed(windowskin); bool contentsValid = !nullOrDisposed(contents); Vec2i trans = geo.pos() + sceneOffset; SimpleAlphaShader &shader = shState->shaders().simpleAlpha; shader.bind(); shader.applyViewportProj(); if (windowskinValid) { shader.setTranslation(trans); shader.setTexSize(Vec2i(base.tex.width, base.tex.height)); TEX::bind(base.tex.tex); base.quad.draw(); if (openness < 255) return; windowskin->bindTex(shader); TEX::setSmooth(true); ctrlVert.draw(0, ctrlQuads); TEX::setSmooth(false); } if (openness < 255) return; bool drawCursor = cursorVert.count() > 0 && windowskinValid; if (drawCursor || contentsValid) { /* Translate cliprect from local into screen space */ IntRect clip = clipRect; clip.setPos(clip.pos() + trans); glState.scissorBox.push(); glState.scissorTest.pushSet(true); if (rgssVer >= 3) glState.scissorBox.setIntersect(clip); else glState.scissorBox.setIntersect(IntRect(trans, geo.size())); IntRect pad = padRect; pad.setPos(pad.pos() + trans); if (drawCursor) { Vec2i contTrans = pad.pos(); contTrans.x += cursorRect->x; contTrans.y += cursorRect->y; if (rgssVer >= 3) contTrans -= contentsOff; shader.setTranslation(contTrans); TEX::setSmooth(true); cursorVert.draw(); TEX::setSmooth(false); } if (contentsValid) { if (rgssVer <= 2) glState.scissorBox.setIntersect(clip); Vec2i contTrans = pad.pos(); contTrans -= contentsOff; shader.setTranslation(contTrans); TEX::setSmooth(false); // XXX contents->bindTex(shader); contentsQuad.draw(); } glState.scissorBox.pop(); glState.scissorTest.pop(); } TEX::setSmooth(false); // XXX FIND out a way to eliminate }