mirror of
https://github.com/neoforged/NeoForge.git
synced 2026-10-12 02:19:42 +00:00
[26.3] Fix various issues with stencil support (#3510)
Co-authored-by: RogueLogix <[email protected]>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
--- a/com/mojang/blaze3d/resource/RenderTargetDescriptor.java
|
||||
+++ b/com/mojang/blaze3d/resource/RenderTargetDescriptor.java
|
||||
@@ -20,14 +_,18 @@
|
||||
}
|
||||
|
||||
public void prepare(RenderTarget resource) {
|
||||
- if (this.color != null && this.depth != null && this.color.clearColor != null && this.depth.clearColor != null) {
|
||||
+ if (this.color != null && this.depth != null && this.color.clearColor != null && this.depth.clearColor != null && this.depth.format.hasDepthAspect()) {
|
||||
RenderSystem.getDevice()
|
||||
.createCommandEncoder()
|
||||
.clearColorAndDepthTextures(resource.getColorTexture(), this.color.clearColor, resource.getDepthTexture(), this.depth.clearColor.x());
|
||||
} else if (this.color != null && this.color.clearColor != null) {
|
||||
RenderSystem.getDevice().createCommandEncoder().clearColorTexture(resource.getColorTexture(), this.color.clearColor);
|
||||
- } else if (this.depth != null && this.depth.clearColor != null) {
|
||||
+ } else if (this.depth != null && this.depth.clearColor != null && this.depth.format.hasDepthAspect()) {
|
||||
RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(resource.getDepthTexture(), this.depth.clearColor.x());
|
||||
+ }
|
||||
+ if (this.depth != null && this.depth.clearColor != null && this.depth.format.hasStencilAspect()) {
|
||||
+ int value = (int) (this.depth.format.hasDepthAspect() ? this.depth.clearColor.y() : this.depth.clearColor.x());
|
||||
+ RenderSystem.getDevice().createCommandEncoder().clearStencilTexture(resource.getDepthTexture(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,38 +5,34 @@
|
||||
public abstract int createFrameBufferObject();
|
||||
|
||||
- public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot);
|
||||
+ public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil);
|
||||
+ public abstract void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel);
|
||||
+
|
||||
+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) {
|
||||
+ this.bindFrameBufferTextures(fbo, color, colorMipLevels, depth, depthMipLevel, bindSlot, false);
|
||||
+ this.bindFrameBufferTextures(fbo, color, colorMipLevels, depth, depthMipLevel, bindSlot, 0, 0);
|
||||
+ }
|
||||
|
||||
public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot) {
|
||||
- this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot);
|
||||
+ this.bindFrameBufferTextures(fbo, color, depth, mipLevel, bindSlot, false);
|
||||
+ this.bindFrameBufferTextures(fbo, color, depth, mipLevel, bindSlot, 0, 0);
|
||||
+ }
|
||||
+
|
||||
+ public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot, boolean useStencil) {
|
||||
+ this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot, useStencil);
|
||||
+ public void bindFrameBufferTextures(int fbo, int color, int depth, int mipLevel, int bindSlot, int stencil, int stencilMipLevel) {
|
||||
+ this.bindFrameBufferTextures(fbo, new int[]{color}, new int[]{mipLevel}, depth, mipLevel, bindSlot, stencil, stencilMipLevel);
|
||||
}
|
||||
|
||||
public abstract void blitFrameBuffers(
|
||||
@@ -102,12 +_,17 @@
|
||||
@@ -102,12 +_,13 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) {
|
||||
+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil) {
|
||||
+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel) {
|
||||
for (int i = 0; i < color.length; i++) {
|
||||
ARBDirectStateAccess.glNamedFramebufferTexture(fbo, 36064 + i, color[i], colorMipLevels[i]);
|
||||
}
|
||||
|
||||
ARBDirectStateAccess.glNamedFramebufferTexture(fbo, 36096, depth, depthMipLevel);
|
||||
+ if (useStencil) {
|
||||
+ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, depth, depthMipLevel);
|
||||
+ } else {
|
||||
+ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, 0, 0);
|
||||
+ }
|
||||
+ ARBDirectStateAccess.glNamedFramebufferTexture(fbo, GL33C.GL_STENCIL_ATTACHMENT, stencil, stencilMipLevel);
|
||||
if (bindSlot != 0) {
|
||||
GlStateManager._glBindFramebuffer(bindSlot, fbo);
|
||||
}
|
||||
@@ -45,19 +41,15 @@
|
||||
|
||||
@Override
|
||||
- public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot) {
|
||||
+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, boolean useStencil) {
|
||||
+ public void bindFrameBufferTextures(int fbo, int[] color, int[] colorMipLevels, int depth, int depthMipLevel, int bindSlot, int stencil, int stencilMipLevel) {
|
||||
int tempBindSlot = bindSlot == 0 ? 36009 : bindSlot;
|
||||
int oldFbo = GlStateManager.getFrameBuffer(tempBindSlot);
|
||||
GlStateManager._glBindFramebuffer(tempBindSlot, fbo);
|
||||
@@ -227,6 +_,11 @@
|
||||
@@ -227,6 +_,7 @@
|
||||
}
|
||||
|
||||
GlStateManager._glFramebufferTexture2D(tempBindSlot, 36096, 3553, depth, depthMipLevel);
|
||||
+ if (useStencil) {
|
||||
+ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, depth, depthMipLevel);
|
||||
+ } else {
|
||||
+ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, 0, 0);
|
||||
+ }
|
||||
+ GlStateManager._glFramebufferTexture2D(tempBindSlot, GL33C.GL_STENCIL_ATTACHMENT, 3553, stencil, stencilMipLevel);
|
||||
if (bindSlot == 0) {
|
||||
GlStateManager._glBindFramebuffer(tempBindSlot, oldFbo);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
--- a/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java
|
||||
+++ b/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java
|
||||
@@ -51,7 +_,7 @@
|
||||
}
|
||||
@@ -52,6 +_,7 @@
|
||||
|
||||
dsa.bindFrameBufferTextures(
|
||||
- fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0
|
||||
+ fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0, depthAttachment != null && depthAttachment.hasStencilAspect()
|
||||
fbo, colorIds, mipLevels, depthAttachment == null ? 0 : depthAttachment.glId(), depthAttachment == null ? 0 : depthAttachment.fboMipLevel(), 0
|
||||
+ , depthAttachment != null && depthAttachment.hasStencilAspect() ? depthAttachment.glId() : 0, depthAttachment != null && depthAttachment.hasStencilAspect() ? depthAttachment.fboMipLevel() : 0
|
||||
);
|
||||
return fbo;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,23 @@
|
||||
--- a/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java
|
||||
+++ b/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java
|
||||
@@ -262,8 +_,9 @@
|
||||
GlStateManager._depthMask(true);
|
||||
GlStateManager._disableScissorTest();
|
||||
|
||||
+ boolean hasStencil = depthTexture.getFormat().hasStencilAspect();
|
||||
for (int i = 0; i < depthTexture.getMipLevels(); i++) {
|
||||
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160);
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160, hasStencil);
|
||||
GL33C.glDrawBuffer(0);
|
||||
GlStateManager._clear(256);
|
||||
}
|
||||
@@ -274,6 +_,17 @@
|
||||
@@ -274,6 +_,24 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
+ public void clearStencilTexture(GpuTexture texture, int value) {
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)texture).id, 0, GlConst.GL_FRAMEBUFFER, true);
|
||||
+ GL33C.glDrawBuffer(GlConst.GL_NONE);
|
||||
+ GL33C.glClearStencil(value);
|
||||
+ GlStateManager._stencilMask(-1);
|
||||
+ GlStateManager._depthMask(true);
|
||||
+ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT);
|
||||
+ GlStateManager._disableScissorTest();
|
||||
+
|
||||
+ for (int i = 0; i < texture.getMipLevels(); i++) {
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, 0, 0, GlConst.GL_FRAMEBUFFER, ((GlTexture)texture).id, i);
|
||||
+ GL33C.glDrawBuffer(GlConst.GL_NONE);
|
||||
+ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT);
|
||||
+ }
|
||||
+
|
||||
+ GL33C.glDrawBuffer(GlConst.GL_COLOR_ATTACHMENT0);
|
||||
+ GlStateManager._glFramebufferTexture2D(GlConst.GL_FRAMEBUFFER, GL33C.GL_STENCIL_ATTACHMENT, GlConst.GL_TEXTURE_2D, 0, 0);
|
||||
+ GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, 0);
|
||||
+ }
|
||||
+
|
||||
@@ -36,8 +32,8 @@
|
||||
- this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, mipLevel, 0);
|
||||
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, mipLevel, 0);
|
||||
+ boolean hasStencil = source.getFormat().hasStencilAspect();
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil);
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil);
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, (isDepth || hasStencil) ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil ? sourceId : 0, 0);
|
||||
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, (isDepth || hasStencil) ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil ? destId : 0, 0);
|
||||
+ int bufferMask = 0;
|
||||
+ if (source.getFormat().hasColorAspect()) {
|
||||
+ bufferMask |= GlConst.GL_COLOR_BUFFER_BIT;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
--- a/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java
|
||||
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java
|
||||
@@ -320,11 +_,21 @@
|
||||
@@ -319,12 +_,24 @@
|
||||
depthAttachmentInfo.loadOp(0);
|
||||
}
|
||||
|
||||
+ if (depthAttachment.textureView().texture().getFormat().hasDepthAspect())
|
||||
renderingInfo.pDepthAttachment(depthAttachmentInfo);
|
||||
+
|
||||
+ if (vulkanDepthAttachment.texture().getFormat().hasStencilAspect()) {
|
||||
@@ -16,10 +18,11 @@
|
||||
}
|
||||
|
||||
KHRDynamicRendering.vkCmdBeginRenderingKHR(this.commandBuffer(), renderingInfo);
|
||||
+ boolean hasDepth = depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasDepthAspect();
|
||||
+ boolean hasStencil = depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasStencilAspect();
|
||||
this.currentRenderPass = new VulkanRenderPass(
|
||||
- this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, descriptor.label()
|
||||
+ this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, hasStencil, descriptor.label()
|
||||
+ this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, hasDepth, hasStencil, descriptor.label()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java
|
||||
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanGpuTexture.java
|
||||
@@ -63,7 +_,8 @@
|
||||
barrier.dstQueueFamilyIndex(-1);
|
||||
barrier.image(this.vkImage);
|
||||
VkImageSubresourceRange subresourceRange = barrier.subresourceRange();
|
||||
- subresourceRange.aspectMask(this.getFormat().hasColorAspect() ? 1 : 2);
|
||||
+ // Neo: respect stencil aspect in aspect mask
|
||||
+ subresourceRange.aspectMask(VulkanConst.formatAspectMask(this.getFormat()));
|
||||
subresourceRange.baseMipLevel(0);
|
||||
subresourceRange.levelCount(this.getMipLevels());
|
||||
subresourceRange.baseArrayLayer(0);
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java
|
||||
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanGpuTextureView.java
|
||||
@@ -26,7 +_,8 @@
|
||||
imageViewCreateInfo.viewType(isCubemap ? 3 : 1);
|
||||
imageViewCreateInfo.format(VulkanConst.toVk(texture.getFormat()));
|
||||
VkImageSubresourceRange subresourceRange = imageViewCreateInfo.subresourceRange();
|
||||
- subresourceRange.aspectMask(texture.getFormat().hasColorAspect() ? 1 : 2);
|
||||
+ // Neo: respect stencil aspect in aspect mask
|
||||
+ subresourceRange.aspectMask(VulkanConst.formatAspectMask(texture.getFormat()));
|
||||
subresourceRange.baseMipLevel(baseMipLevel);
|
||||
subresourceRange.levelCount(mipLevels);
|
||||
subresourceRange.baseArrayLayer(0);
|
||||
@@ -29,7 +29,7 @@
|
||||
this.uniforms.clear();
|
||||
this.uniforms.size(vulkanRenderPipeline.uniforms().size());
|
||||
+ if (this.hasStencil) {
|
||||
+ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.pipeline.withDepthStencilPipeline());
|
||||
+ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.hasDepth ? this.pipeline.withDepthStencilPipeline() : this.pipeline.withStencilPipeline());
|
||||
+ return;
|
||||
+ }
|
||||
VK12.vkCmdBindPipeline(this.commandBuffer(), 0, this.hasDepth ? this.pipeline.withDepthPipeline() : this.pipeline.withoutDepthPipeline());
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
--- a/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java
|
||||
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java
|
||||
@@ -41,6 +_,7 @@
|
||||
@@ -41,6 +_,8 @@
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public final class VulkanRenderPipeline implements BackendRenderPipeline, Destroyable {
|
||||
private final VulkanDevice device;
|
||||
+ private final long withStencilPipeline;
|
||||
+ private final long withDepthStencilPipeline;
|
||||
private final long withDepthPipeline;
|
||||
private final long withoutDepthPipeline;
|
||||
private final long pipelineLayout;
|
||||
@@ -51,6 +_,7 @@
|
||||
@@ -51,6 +_,8 @@
|
||||
|
||||
public VulkanRenderPipeline(
|
||||
VulkanDevice device,
|
||||
+ long withStencilPipeline,
|
||||
+ long withDepthStencilPipeline,
|
||||
long withDepthPipeline,
|
||||
long withoutDepthPipeline,
|
||||
long pipelineLayout,
|
||||
@@ -59,6 +_,7 @@
|
||||
@@ -59,6 +_,8 @@
|
||||
List<BindGroupLayout.UniformDescription> uniforms
|
||||
) {
|
||||
this.device = device;
|
||||
+ this.withStencilPipeline = withStencilPipeline;
|
||||
+ this.withDepthStencilPipeline = withDepthStencilPipeline;
|
||||
this.withDepthPipeline = withDepthPipeline;
|
||||
this.withoutDepthPipeline = withoutDepthPipeline;
|
||||
@@ -52,40 +55,47 @@
|
||||
}
|
||||
|
||||
List<ColorTargetState> colorTargetStates = pipelineCreateInfo.colorTargetStates();
|
||||
@@ -289,6 +_,7 @@
|
||||
@@ -289,7 +_,7 @@
|
||||
long withDepthPipeline = pointer.get(0);
|
||||
device.instance().debug().setObjectName(device.vkDevice(), 19, withDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
|
||||
long withoutDepthPipeline;
|
||||
+ long withDepthStencilPipeline = 0L;
|
||||
if (depthStencilState == null) {
|
||||
- if (depthStencilState == null) {
|
||||
+ if (true) {
|
||||
renderingInfo.depthAttachmentFormat(0);
|
||||
VulkanUtils.crashIfFailure(
|
||||
@@ -300,10 +_,18 @@
|
||||
device.instance().debug().setObjectName(device.vkDevice(), 19, withoutDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
|
||||
} else {
|
||||
device,
|
||||
@@ -302,8 +_,20 @@
|
||||
withoutDepthPipeline = 0L;
|
||||
+
|
||||
+ if (depthStencilState.stencilTest() != null) {
|
||||
+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name());
|
||||
+ withDepthStencilPipeline = pointer.get(0);
|
||||
+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
|
||||
+ }
|
||||
}
|
||||
|
||||
+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name());
|
||||
+ long withDepthStencilPipeline = pointer.get(0);
|
||||
+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
|
||||
+
|
||||
+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_UNDEFINED);
|
||||
+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_S8_UINT);
|
||||
+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name());
|
||||
+ long withStencilPipeline = pointer.get(0);
|
||||
+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
|
||||
+
|
||||
return new VulkanRenderPipeline(
|
||||
- device, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms()
|
||||
+ device, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms()
|
||||
+ device, withStencilPipeline, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -334,6 +_,10 @@
|
||||
@@ -334,6 +_,14 @@
|
||||
|
||||
public VulkanDevice device() {
|
||||
return this.device;
|
||||
+ }
|
||||
+
|
||||
+ public long withStencilPipeline() {
|
||||
+ return this.withStencilPipeline;
|
||||
+ }
|
||||
+
|
||||
+ public long withDepthStencilPipeline() {
|
||||
+ return this.withDepthStencilPipeline;
|
||||
}
|
||||
|
||||
+32
-143
@@ -5,38 +5,21 @@
|
||||
|
||||
package net.neoforged.neoforge.oldtest.client.rendering;
|
||||
|
||||
import com.mojang.blaze3d.platform.Lighting;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.renderpearl.api.pipeline.CompareOp;
|
||||
import com.mojang.renderpearl.api.pipeline.DepthStencilState;
|
||||
import com.mojang.renderpearl.api.pipeline.RenderPipeline;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
||||
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
|
||||
import net.minecraft.client.renderer.SubmitNodeCollector;
|
||||
import net.minecraft.client.renderer.feature.FeatureRenderDispatcher;
|
||||
import net.minecraft.client.renderer.item.ItemModelResolver;
|
||||
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
|
||||
import net.minecraft.client.renderer.state.gui.pip.PictureInPictureRenderState;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.RenderPipelines;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.util.LightCoordsUtil;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.neoforge.client.event.ConfigureMainRenderTargetEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterPictureInPictureRenderersEvent;
|
||||
import net.neoforged.neoforge.client.pipeline.PipelineModifier;
|
||||
import net.neoforged.neoforge.client.pipeline.RegisterPipelineModifiersEvent;
|
||||
import net.neoforged.neoforge.client.stencil.StencilOperation;
|
||||
import net.neoforged.neoforge.client.stencil.StencilPerFaceTest;
|
||||
import net.neoforged.neoforge.client.stencil.StencilTest;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Basic test that uses the stencil buffer.
|
||||
@@ -60,8 +43,31 @@ public class StencilEnableTest {
|
||||
|
||||
private static final State ENABLED = State.ENABLE_REGISTRATION;
|
||||
|
||||
private static final ResourceKey<PipelineModifier> STENCIL_FILL_KEY = ResourceKey.create(PipelineModifier.MODIFIERS_KEY, Identifier.fromNamespaceAndPath(MOD_ID, "stencil_fill"));
|
||||
private static final ResourceKey<PipelineModifier> STENCIL_APPLY_KEY = ResourceKey.create(PipelineModifier.MODIFIERS_KEY, Identifier.fromNamespaceAndPath(MOD_ID, "stencil_apply"));
|
||||
private static final RenderPipeline GUI_TEXTURED_STENCIL_FILL = RenderPipelines.GUI_TEXTURED.toBuilder()
|
||||
.withLocation(Identifier.fromNamespaceAndPath(MOD_ID, "pipeline/gui_textured_stencil_fill"))
|
||||
.withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest(
|
||||
new StencilPerFaceTest(
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.REPLACE,
|
||||
CompareOp.ALWAYS_PASS),
|
||||
0xFF,
|
||||
0xFF,
|
||||
1)))
|
||||
.build();
|
||||
private static final RenderPipeline GUI_STENCIL_APPLY = RenderPipelines.GUI.toBuilder()
|
||||
.withLocation(Identifier.fromNamespaceAndPath(MOD_ID, "pipeline/gui_textured_stencil_apply"))
|
||||
.withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest(
|
||||
new StencilPerFaceTest(
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
CompareOp.NOT_EQUAL),
|
||||
0xFF,
|
||||
0,
|
||||
1)))
|
||||
.build();
|
||||
private static final Identifier MASK_TEXTURE = Identifier.withDefaultNamespace("textures/gui/sprites/icon/new_realm.png");
|
||||
|
||||
public StencilEnableTest(IEventBus modEventBus) {
|
||||
if (ENABLED == State.DISABLE) {
|
||||
@@ -70,137 +76,20 @@ public class StencilEnableTest {
|
||||
modEventBus.addListener(ConfigureMainRenderTargetEvent.class, event -> {
|
||||
event.enableStencil();
|
||||
});
|
||||
modEventBus.addListener(RegisterPipelineModifiersEvent.class, event -> {
|
||||
event.register(STENCIL_FILL_KEY, (pipeline, name) -> pipeline.toBuilder()
|
||||
.withLocation(name)
|
||||
.withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest(
|
||||
new StencilPerFaceTest(
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.REPLACE,
|
||||
CompareOp.ALWAYS_PASS),
|
||||
0xFF,
|
||||
0xFF,
|
||||
1)))
|
||||
.build());
|
||||
event.register(STENCIL_APPLY_KEY, (pipeline, name) -> pipeline.toBuilder()
|
||||
.withLocation(name)
|
||||
.withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true, 0F, 0F, new StencilTest(
|
||||
new StencilPerFaceTest(
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
StencilOperation.KEEP,
|
||||
CompareOp.NOT_EQUAL),
|
||||
0xFF,
|
||||
0,
|
||||
1)))
|
||||
.build());
|
||||
});
|
||||
modEventBus.addListener(RegisterPictureInPictureRenderersEvent.class, event -> {
|
||||
if (ENABLED != State.ENABLE_UI_LAYER) {
|
||||
return;
|
||||
}
|
||||
event.register(StenciledItemPictureInPictureRenderState.class, StenciledItemPictureInPictureRenderer::new);
|
||||
});
|
||||
modEventBus.addListener(RegisterGuiLayersEvent.class, event -> {
|
||||
if (ENABLED != State.ENABLE_UI_LAYER) {
|
||||
return;
|
||||
}
|
||||
event.registerAboveAll(
|
||||
Identifier.fromNamespaceAndPath(MOD_ID, "block_outline"),
|
||||
Identifier.fromNamespaceAndPath(MOD_ID, "stenciled_ui_element"),
|
||||
(guiGraphics, _) -> {
|
||||
ItemModelResolver itemModelResolver = Minecraft.getInstance().getItemModelResolver();
|
||||
|
||||
TrackingItemStackRenderState maskState = new TrackingItemStackRenderState();
|
||||
itemModelResolver.updateForTopItem(maskState, new ItemStack(Blocks.GRASS_BLOCK), ItemDisplayContext.GUI, null, null, 0);
|
||||
TrackingItemStackRenderState maskedState = new TrackingItemStackRenderState();
|
||||
itemModelResolver.updateForTopItem(maskedState, new ItemStack(Blocks.DIAMOND_BLOCK), ItemDisplayContext.GUI, null, null, 0);
|
||||
RenderSystem.getDevice().createCommandEncoder().clearStencilTexture(Minecraft.getInstance().gameRenderer.mainRenderTarget().getDepthTexture(), 0);
|
||||
|
||||
int maxX = guiGraphics.guiWidth();
|
||||
guiGraphics.submitPictureInPictureRenderState(new StenciledItemPictureInPictureRenderState(
|
||||
maskState,
|
||||
maskedState,
|
||||
maxX - 50, 10, maxX - 10, 50,
|
||||
16F,
|
||||
guiGraphics.peekScissorStack()));
|
||||
guiGraphics.blit(GUI_TEXTURED_STENCIL_FILL, MASK_TEXTURE, maxX - 100, 10, 0, 0, 40, 20, 40, 20, 0x01FFFFFF);
|
||||
guiGraphics.nextStratum();
|
||||
guiGraphics.fill(GUI_STENCIL_APPLY, maxX - 100, 10, maxX - 60, 30, 0xFF0000AA);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// FIXME: it is no longer possible to render twice in a PiP
|
||||
private static final class StenciledItemPictureInPictureRenderer extends PictureInPictureRenderer<StenciledItemPictureInPictureRenderState> {
|
||||
@Override
|
||||
protected void renderToTexture(StenciledItemPictureInPictureRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector) {
|
||||
Minecraft.getInstance().gameRenderer.lighting().setupFor(Lighting.Entry.ITEMS_3D);
|
||||
poseStack.scale(1, -1, -1);
|
||||
float scale = state.scale;
|
||||
FeatureRenderDispatcher dispatcher = Minecraft.getInstance().gameRenderer.featureRenderDispatcher();
|
||||
RenderSystem.pushPipelineModifier(STENCIL_FILL_KEY);
|
||||
{
|
||||
state.maskRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0);
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(10F / scale, -10F / scale, 0);
|
||||
state.maskRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0);
|
||||
poseStack.popPose();
|
||||
|
||||
//dispatcher.renderAllFeatures((SubmitNodeStorage) submitNodeCollector);
|
||||
}
|
||||
RenderSystem.popPipelineModifier();
|
||||
|
||||
RenderSystem.pushPipelineModifier(STENCIL_APPLY_KEY);
|
||||
{
|
||||
poseStack.scale(1.1F, 1.1F, 1.1F);
|
||||
poseStack.translate(-.5F / scale, .5F / scale, 0);
|
||||
|
||||
state.maskedRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0);
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(10F / scale, -10F / scale, 0);
|
||||
state.maskedRenderState.submit(poseStack, submitNodeCollector, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 0);
|
||||
poseStack.popPose();
|
||||
|
||||
//dispatcher.renderAllFeatures((SubmitNodeStorage) submitNodeCollector);
|
||||
}
|
||||
RenderSystem.popPipelineModifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getTranslateY(int height, int guiScale) {
|
||||
return height / 2F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StenciledItemPictureInPictureRenderState> getRenderStateClass() {
|
||||
return StenciledItemPictureInPictureRenderState.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTextureLabel() {
|
||||
return "stencil enable test";
|
||||
}
|
||||
}
|
||||
|
||||
private record StenciledItemPictureInPictureRenderState(
|
||||
TrackingItemStackRenderState maskRenderState,
|
||||
TrackingItemStackRenderState maskedRenderState,
|
||||
int x0,
|
||||
int y0,
|
||||
int x1,
|
||||
int y1,
|
||||
float scale,
|
||||
@Nullable ScreenRectangle bounds,
|
||||
@Nullable ScreenRectangle scissorArea) implements PictureInPictureRenderState {
|
||||
public StenciledItemPictureInPictureRenderState(
|
||||
TrackingItemStackRenderState maskRenderState,
|
||||
TrackingItemStackRenderState maskedRenderState,
|
||||
int x0,
|
||||
int y0,
|
||||
int x1,
|
||||
int y1,
|
||||
float scale,
|
||||
@Nullable ScreenRectangle scissorArea) {
|
||||
this(maskRenderState, maskedRenderState, x0, y0, x1, y1, scale, PictureInPictureRenderState.getBounds(x0, y0, x1, y1, scissorArea), scissorArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user