繁体   English   中英

嵌套模具-OpenGL ES

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM