![](/img/trans.png)
[英]openGL ES 2 - Is there a way to attach a stencil buffer with a different resolution than the target texture?
[英]Nested Stencil - OpenGL ES
我有一个2D节点场景图,正在尝试“嵌套”模板剪切。
我在想我能做的是绘制模具时,将其写入的任何像素增加1,并跟踪我正在使用的当前“层”。
然后在绘制时,如果该像素处的模板的值> =当前图层#,则仅将像素数据写入颜色缓冲区。
这是我现在拥有的代码。 它不太起作用。 我在哪里弄糟?
首先,我调用SetupStencilForMask()。 然后绘制模具图元。 接下来,调用SetupStencilForDraw()。 现在绘制实际图像完成图层后,调用DisableStencil()。
编辑:更新了解决方案。 它不适用于同一层上的单个项目,否则可以。 找到了一篇很棒的文章,介绍了如何真正实现这一目标,尽管它相当有限。 http://cranialburnout.blogspot.com/2014/03/nesting-and-overlapping-translucent.html
// glClear(GL_STENICL_BIT) at start of each draw frame
static int stencilLayer = 0;
void SetupStencilForMask(void)
{
if (stencilLayer == 0)
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_LESS, stencilLayer, 0xff);
glStencilOp(GL_INCR, GL_KEEP, GL_KEEP);
glStencilMask(0xff);
if (stencilLayer == 0)
glClear(GL_STENCIL_BUFFER_BIT);
stencilLayer++;
}
void SetupStencilForDraw()
{
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, stencilLayer, 0xff);
glStencilMask(0x00);
}
void DisableStencil(void)
{
if (--stencilLayer == 0)
glDisable(GL_STENCIL_TEST);
}
我已经找到了在libgdx中执行此操作的方法。 我不确定您是否仍然需要此代码,但以下代码供将来参考:
/**
* Start cropping
*
* @param cropMask
* Mask plane
*/
public void startCropping(Plane cropMask) {
// Check if there is active masking group
if (activeCropMaskGroup == null) {
// Create new one
activeCropMaskGroup = new CropMaskingGroupDescriptor(cropMask);
} else {
// Increase hierarchy level
activeCropMaskGroup.increaseHierachy(cropMask);
}
}
/** End cropping */
public void endCropping() throws IllegalStateException {
// Check if there is active group mask
if (activeCropMaskGroup == null) {
throw new IllegalStateException("Call start cropping before this!");
}
if (activeCropMaskGroup.getHierachy() > 0) {
activeCropMaskGroup.decreaseHierachy();
} else {
// Finish setup of crop data
cropMaskGroups.add(activeCropMaskGroup);
activeCropMaskGroup = null;
}
}
/** Crop registered planes for cropping */
private void cropRender(CropMaskingGroupDescriptor cropMaskGroupDescriptor) {
// Draw mask to stencil buffer
Gdx.gl.glClear(GL20.GL_STENCIL_BUFFER_BIT);
// setup drawing to stencil buffer
Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
// Number of registered hierarchy levels
int hierarchyLevels = cropMaskGroupDescriptor.getRegisteredBatch().size();
// Loop trough hierarchy
for (int hierarchyLevel = 0; hierarchyLevel < hierarchyLevels; hierarchyLevel++) {
Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
Gdx.gl20.glStencilOp(GL20.GL_INCR, GL20.GL_INCR, GL20.GL_INCR);
Gdx.gl20.glColorMask(false, false, false, false);
Gdx.gl20.glDepthMask(false);
// Draw mask with decal batch
cropMaskBatch.add(((NativePlane) cropMaskGroupDescriptor.getCroppingMasks().get(hierarchyLevel)).getPlane());
cropMaskBatch.flush();
// fix stencil buffer, enable color buffer
Gdx.gl20.glColorMask(true, true, true, true);
Gdx.gl20.glDepthMask(true);
Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);
// draw where pattern has been drawn
Gdx.gl20.glStencilFunc(GL20.GL_LEQUAL, hierarchyLevel + 1, 0xffffffff);
// Loop trough registered masked layers and found which one belongs
// to
// current hierarchy level
for (int i = 0; i < cropMaskGroupDescriptor.getMaskedLayers().size(); i++) {
if (cropMaskGroupDescriptor.getMaskedLayers().get(i).getHierarchyId() == hierarchyLevel) {
Plane plane = cropMaskGroupDescriptor.getMaskedLayers().get(i).getMaskedPlane();
cropMaskGroupDescriptor.getRegisteredBatch().get(hierarchyLevel).add(((NativePlane) plane).getPlane());
}
}
cropMaskGroupDescriptor.getRegisteredBatch().get(hierarchyLevel).flush();
}
Gdx.gl20.glDisable(GL20.GL_STENCIL_TEST);
}
以及渲染器模块内部的内部类。
/ ** *裁剪的图层描述符* * @author Veljko Ilkic * * /私有类CropMaskLayerDescriptor {
/** Layer that needs to be masked */
private Plane maskedPlane;
/** Hierarchy level in which belongs */
private int hierarchyId = 0;
/** Constructor 1 */
public CropMaskLayerDescriptor(Plane maskedPlane, int hierarchyId) {
this.maskedPlane = maskedPlane;
this.hierarchyId = hierarchyId;
}
public Plane getMaskedPlane() {
return maskedPlane;
}
public int getHierarchyId() {
return hierarchyId;
}
}
/**
* Crop masking group descriptor class
*
* @author Veljko Ilkic
*
*/
private class CropMaskingGroupDescriptor {
/** Crop mask */
private ArrayList<Plane> croppingMasks = new ArrayList<Plane>();
/** Planes that will be masked by crop mask */
private ArrayList<CropMaskLayerDescriptor> maskedLayers = new ArrayList<Renderer.CropMaskLayerDescriptor>();
/** Batch for drawing masked planes */
private ArrayList<DecalBatch> hierarchyBatches = new ArrayList<DecalBatch>();
private int activeHierarchyLayerId = 0;
/** Constructor 1 */
public CropMaskingGroupDescriptor(Plane topLevelCropMask) {
// Create batch for top level hierarchy
hierarchyBatches.add(new DecalBatch(new CameraGroupStrategy(perspectiveCamera)));
// Register top level crop mask
croppingMasks.add(topLevelCropMask);
}
/** Increase hierarchy level of the group */
public void increaseHierachy(Plane hierarchyCropMask) {
activeHierarchyLayerId++;
// Create individual batch for hierarchy level
hierarchyBatches.add(new DecalBatch(new CameraGroupStrategy(perspectiveCamera)));
// Register crop mask for current hierarchy level
croppingMasks.add(hierarchyCropMask);
}
/** Decrease hierarchy group */
public void decreaseHierachy() {
activeHierarchyLayerId--;
}
/** Get current hierarchy level */
public int getHierachy() {
return activeHierarchyLayerId;
}
/** Register plane for masking */
public void registerLayer(Plane maskedPlane) {
hierarchyBatches.get(activeHierarchyLayerId).add(((NativePlane) maskedPlane).getPlane());
maskedLayers.add(new CropMaskLayerDescriptor(maskedPlane, activeHierarchyLayerId));
}
/** Get all registered batched */
public ArrayList<DecalBatch> getRegisteredBatch() {
return hierarchyBatches;
}
/** Get registered cropping masks */
public ArrayList<Plane> getCroppingMasks() {
return croppingMasks;
}
/** Get layer that should be masked */
public ArrayList<CropMaskLayerDescriptor> getMaskedLayers() {
return maskedLayers;
}
/** Dispose */
public void dispose() {
for (int i = 0; i < hierarchyBatches.size(); i++) {
hierarchyBatches.get(i).dispose();
hierarchyBatches.set(i, null);
}
hierarchyBatches.clear();
}
}
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.