精靈移動時,超出父節點矩形範圍的部分自動裁剪隱藏,類似 clippingEnabled 或 CSS overflow: hidden。
Cocos2d-x 繪製流程中,visit() 是節點渲染入口。通過 OpenGL GL_SCISSOR_TEST 可實現矩形裁剪區域。
class ClippingNode : public cocos2d::Node {
protected:
// 重寫 visit 方法
void visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags) override {
// 1. 計算世界空間下的裁剪矩形 (父節點的包圍盒)
cocos2d::Rect clippingRect = getClippingRect(); // 需自行實現獲取父節點世界座標下的 rect
// 2. 啟用 Scissor Test
glEnable(GL_SCISSOR_TEST);
// glScissor 參數:左下角 x, y, 寬, 高 (像素,OpenGL 座標系,原點左下角)
// 需將 cocos2d::Rect 轉換為 OpenGL 視口座標
cocos2d::Point origin = this->convertToWorldSpace(clippingRect.origin);
cocos2d::Size size = clippingRect.size;
// 考慮縮放、旋轉等變換,實際項目中建議用 getBoundingBoxToWorld()
glScissor((GLint)origin.x, (GLint)origin.y, (GLsizei)size.width, (GLsizei)size.height);
// 3. 調用父類 visit 繪製子節點 (在裁剪區域內)
Node::visit(renderer, parentTransform, parentFlags);
// 4. 禁用 Scissor Test (恢復狀態)
glDisable(GL_SCISSOR_TEST);
}
// 獲取裁剪區域 (示例:使用自身 contentSize 作為裁剪區)
virtual cocos2d::Rect getClippingRect() {
return cocos2d::Rect(0, 0, this->getContentSize().width, this->getContentSize().height);
}
};
| 步驟 | 說明 |
|---|---|
glEnable(GL_SCISSOR_TEST) | 啟用 OpenGL 裁剪測試,後續繪製命令僅影響裁剪矩形內的像素 |
glScissor(x, y, w, h) | 設置裁剪矩形,**座標系為 OpenGL 視口座標 (左下角原點,像素單位)**,非 Cocos2d-x 節點座標 |
| 座標轉換 | 必須將節點座標系下的矩形轉換為視口座標:auto worldRect = node->getBoundingBoxToWorld();再配合 Director::getInstance()->getOpenGLView()->getFrameSize() 等計算 |
Node::visit(...) | 在裁剪狀態下繪製自身及所有子節點 |
glDisable(GL_SCISSOR_TEST) | **必須成對調用**,否則影響後續無關節點渲染 |
引擎已提供 cocos2d::ClippingNode (繼承自 Node),基於 Stencil Buffer 實現任意形狀裁剪,比 Scissor Test 更強大:
auto clippingNode = ClippingNode::create();
// 設置模板節點 (定義裁剪形狀,這裡用矩形)
auto stencil = DrawNode::create();
stencil->drawSolidRect(Vec2(0,0), Vec2(300,200), Color4F::WHITE);
clippingNode->setStencil(stencil);
// 反轉模板 (可選)
clippingNode->setInverted(false);
// 添加內容節點
clippingNode->addChild(sprite);
this->addChild(clippingNode);
優勢:支援非矩形裁剪 (圓形、多邊形、不規則形狀)、抗鋸齒、嵌套裁剪。
visit 中使用最新的變換矩陣計算世界座標下的裁剪矩形。**推薦使用內建 ClippingNode` + `DrawNode` 模板** 實現,代碼簡潔、功能強大、官方維護。僅在極度追求性能且裁剪區域為固定軸對齊矩形時,考慮手工 visit() + GL_SCISSOR_TEST。