2 个三角形(图片 A)只是在四边形(图片 B)内的区域中绘制,因此结果看起来会被剪裁(图片 C)。
首先,我只是在模板缓冲区中绘制四边形。
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
gl.stencilFunc(gl.ALWAYS, 1, 0xff);
gl.stencilMask(0xff);
gl.depthMask(false);
gl.colorMask(false, false, false, false);
drawQuads();
Run Code Online (Sandbox Code Playgroud)
根据我的理解,现在模板缓冲区在四边形区域的值为 1。然后,绘制三角形。
gl.stencilFunc(gl.EQUAL, 1, 0xff);
gl.stencilMask(0x00);
gl.depthMask(true);
gl.colorMask(true, true, true, true);
drawTriagles();
Run Code Online (Sandbox Code Playgroud)
我原以为结果会像图片 (C) 那样,但事实并非如此。我做错了什么?
请在这里找到完整的代码https://jsfiddle.net/z11zhf01/1
Unity版本2019.1.2f1 HDRP项目。
我试图在一个完成的游戏对象上打个洞,该对象具有不想干扰的材质和着色器,要点是,它应该与完成的任何对象一起工作。我在其他地方找到了这种方法,但似乎不适用于HD Render Pipeline版本。基本上,要在要打洞的地方放置两个额外的游戏对象/形状,一个对象具有准备阶段,另一个则可以打孔。
着色器示例:
Shader "Custom/HolePrepare" {
Properties{
}
SubShader{
Tags { "RenderType" = "Opaque" "Queue" = "Geometry+1"}
ColorMask 0
ZWrite off
Stencil {
Ref 1
Comp always
Pass replace
}
CGINCLUDE
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(1,1,0,1);
}
ENDCG
Pass {
Cull Front
ZTest Less
CGPROGRAM
#pragma …Run Code Online (Sandbox Code Playgroud) 使用opengl-es for Android中的模板缓冲区,我只是试图屏蔽绘制部分屏幕.我认为我设置正确,但它没有掩盖非模板部分.下面是我正在做的代码的提取.
gl.glEnable(GL10.GL_STENCIL_TEST);
gl.glClearStencil(0);
gl.glClear(GL10.GL_STENCIL_BUFFER_BIT);
gl.glColorMask(false, false, false, false);
gl.glDepthMask(false);
gl.glStencilFunc(GL10.GL_ALWAYS, 1, 1);
gl.glStencilOp(GL10.GL_REPLACE, GL10.GL_REPLACE, GL10.GL_REPLACE);
drawMask(); //I have confirmed this draws to the correct location by allowing colour to show. Trust that this draws the mask to the correct location.
gl.glColorMask(true, true, true, true);
gl.glDepthMask(true);
gl.glStencilFunc(GL10.GL_EQUAL, 1, 1);
gl.glStencilOp(GL10.GL_KEEP, GL10.GL_KEEP, GL10.GL_KEEP);
drawItems(); //Draw everything. Only items inside the masked area should be drawn. But everything is drawn with this code...
gl.glDisable(GL10.GL_STENCIL_TEST);
Run Code Online (Sandbox Code Playgroud)
有人发现这有什么不对吗?它的作用基本上是绘制一个框,比如屏幕的一半(如果我启用了颜色,这可以工作),它将模板缓冲区设置为该区域的1.最后我画到了整个屏幕.我希望它只画到上半部分,但它会吸引一切.
提前致谢.
我不确定这是否可行,但值得一试.我正在使用模板缓冲区来减少使用此算法的延迟渲染器中的光量过度绘制(当摄像机位于卷外时):
这将仅导致光量内的像素被着色.绘制多个灯时会出现问题.首先,由于状态变化很昂贵,因此对于每种灯光反复在廉价和昂贵的着色器之间切换可能不是最佳选择.理想情况下,我想利用模板缓冲区的所有8位,通过使用廉价着色器渲染8个轻量级,然后使用昂贵的着色器渲染8个轻量级.但是,当灯光重叠时会出现问题,因为无法分辨哪些像素属于哪些灯光.
想到的解决方案是每个灯在模板缓冲区中使用1位.因此,对于光n,在廉价通道中标记模板缓冲区中的第n位,然后在昂贵的通过期间仅渲染具有该位的像素.
我之前没有使用模板缓冲区,但从我正在阅读的内容看起来似乎不太可能.为此,我必须使用按位OR设置模板缓冲区,并且模板函数必须是按位AND.但是,我可以看到的模板缓冲区上的唯一操作是:KEEP,ZERO,REPLACE,INCR,DECR和INVERT,唯一的功能是:NEVER,ALWAYS,LESS,EQUAL,LEQUAL,GEQUAL,GREATER和NOTEQUAL.
有没有办法以某种方式使用模板缓冲区获得此OR和AND行为?如果没有,是否有另一种方法可以有效地渲染光量?
我是否可以在OpenGL 2.0中使用纹理(图像)准备模板,以便图像的某些部分是透明的,因此它将按原样传输
到模板缓冲区,然后使用此模板缓冲区进行进一步绘制.
@datenwolf非常感谢您的回复,但没有成功:(这是我的代码
- (void)render
{
[EAGLContext setCurrentContext:context];
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glUseProgram(program);
glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
glViewport(0, 0, backingWidth, backingHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Set the stencil clear value
glClearStencil ( 0x1 );
// Set the depth clear value
glClearDepthf( 0.75f );
////////
////
GLfloat threshold = 0.5f;//half transparency
/* the order in which orthogonal OpenGL state is set doesn't matter */
glEnable(GL_STENCIL_TEST);
glEnable(GL_ALPHA_TEST);
/* don't write to color or depth buffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, …Run Code Online (Sandbox Code Playgroud) 过去一周,我一直在努力实现类似游戏Antichamber(更准确地说是下面显示的这个技巧):
这是我希望实现的视频(尽管它是使用虚幻引擎4完成的;我没有使用它):https://www.youtube.com/watch?v = Off3JcoWrMZs
我查找了最好的方法,我发现了模板缓冲区.在这篇文章和这个代码("drawPortals()"函数)之间,我在网上找到了我几乎实现它.
它可以很好地与一个门户到另一个房间(不是一个可交叉的门户,这意味着你无法穿过它并被传送到另一个房间).在我的例子中,我正在绘制一个门户到一个简单的方形房间,里面有一个球体; 在门户网站后面还有另一个球体,我用来检查深度缓冲区是否正常工作并将其绘制在门户网站后面:
当我添加另一个接近此门户的门户时,会出现问题.在这种情况下,我设法正确显示另一个门户(灯光关闭,但右侧的球体颜色不同,表明它是另一个球体):
但是如果我转动相机以便第一个门户必须被绘制在第二个门户上,那么第一个门户的深度就会出错,而第二个门户将被绘制在第一个门户上,如下所示:
虽然应该是这样的:
所以,这就是问题所在.我可能在深度缓冲区做错了,但我找不到什么.
我的渲染部分的代码就是这样的:
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
// First portal
glPushMatrix();
// Disable writing to the color and depht buffer; disable depth testing
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
// Make sure that the stencil always fails
glStencilFunc(GL_NEVER, 1, 0xFF);
// On fail, put 1 on the buffer
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
// Enable writing to the stencil buffer
glStencilMask(0xFF);
// Clean the …Run Code Online (Sandbox Code Playgroud) 我代码作为NeHe导师Lesson27告诉我,但它是一个z-pass算法.当我在阴影中时,阴影消失.有人告诉我,我可以使用z-fail算法来解决这个问题.所以我花了两天时间来研究z-fail算法.最后,我无法弄明白.我的程序永远不会像我想的那样运行.
作为wiki列出的z-fail算法:
深度失败在2000年左右,有几个人发现Heidmann的方法可以通过反转深度来适用于所有摄像机位置.而不是计算对象表面前面的阴影表面,它后面的表面可以很容易地计算,具有相同的最终结果.这解决了眼睛处于阴影中的问题,因为眼睛和物体之间的阴影体积不计算,但是引入了阴影体积的后端必须加盖的条件,或者阴影将最终丢失在体积指向的位置向后无穷大.
禁用对深度和颜色缓冲区的写入.
使用正面剔除.
将模板操作设置为在深度失败时递增(仅计算对象后面的阴影).
渲染阴影卷.
使用背面剔除.
将模板操作设置为在深度失败时递减.
渲染阴影卷.
我认为的主要问题是深度测试.在步骤3和6,模板操作基于深度失败.虽然它可以显示阴影,但它可能在它之前的对象上阴影(即:深度缓冲值小于它的对象).所有阴影效果看起来很乱.
但是在z-pass算法中,模板操作基于深度通过,这意味着它不仅可以显示阴影,而且仅在其后面的对象上阴影,符合眼睛系统.
所以如何解决这个问题使我的深度失败算法显示出正确对象的阴影.
这是我的z-fail算法代码(某处可能在哪里,请帮我看看,阴影效果很糟糕)
VECTOR vec;
void shadowvolume(SECTOR &sec,float *lp)
{
unsigned int p1, p2;
VECTOR v1, v2;
int i, j, k, jj;
for (i=0; i<sec.numplanes;i++)
{
if (sec.planes[i].visible)
{
for (j=0;j<3;j++)
{
k = sec.planes[i].neigh[j];
if ((!k) || (!sec.planes[k-1].visible))//????k??????????????????????
{
// here we have an edge, we must draw a polygon
p1 = sec.planes[i].p[j]-1;//?????
jj = (j+1)%3;
p2 = sec.planes[i].p[jj]-1;//?????
//calculate the length of the vector
v1.x = (sec.points[p1].vec.x …Run Code Online (Sandbox Code Playgroud) 我正在使用libgdx和OpenGL ES 1.0,我想知道SpriteBatch是否可以写入/绘制到模板缓冲区.我一直在尝试写它并且我根本没有得到任何结果,我没有使用模板缓冲区的经验,但我已经阅读了很多,所以如果我在后面的任何事情上错了,请纠正我.基本上我想要做的是用模板缓冲区绘制带有SpriteBatch的纹理,这样当我绘制其他东西时(禁用模板缓冲区)它只会在模板缓冲区等于1的区域上绘制.
这是我想要的结果:如果我将一个星形的纹理绘制到模板缓冲区,然后我在颜色缓冲区中绘制一个红色纹理,我希望红色纹理省略星形在模板缓冲区中的像素.
到目前为止这是我的代码:
batch.begin();
Gdx.gl10.glEnable(GL10.GL_STENCIL_TEST);
Gdx.gl10.glEnable(GL10.GL_ALPHA_TEST);
Gdx.gl10.glStencilFunc(GL10.GL_ALWAYS, 0x1, 0xffffffff);
Gdx.gl10.glStencilOp(GL10.GL_REPLACE, GL10.GL_REPLACE, GL10.GL_REPLACE);
Gdx.gl10.glColorMask(false, false, false, false);
batch.draw(myShape, 100, 100); //draw to the stencil buffer a shape (texture region)
batch.end();
batch.begin();
Gdx.gl10.glColorMask(true, true, true, true);
Gdx.gl10.glStencilOp(GL10.GL_KEEP, GL10.GL_KEEP, GL10.GL_KEEP);
// draw where the shape has NOT been drawn
Gdx.gl10.glStencilFunc(GL10.GL_NOTEQUAL, 0x1, 0xff);
batch.draw(BackGroundLayer, 0, 0);// draw background
Gdx.gl10.glDisable(GL10.GL_STENCIL_TEST);
Run Code Online (Sandbox Code Playgroud) 我一直在阅读有关 OpenGL 中的模板缓冲区的信息。基本概念是有道理的;片段只有在与模板缓冲区中的值进行按位与运算后满足特定条件时才会绘制。但是我不明白的一件事是您实际上如何写入模板缓冲区。有没有我在这里缺少的功能?
PS 当我说写时,我的意思是指定模板缓冲区中的特定值。
我想在 OpenGL 中设置多个模板,然后绘制它们的多个组合。
例如:我有两个这样的矩形模板:

然后我想画成:
我发现可以在模板缓冲区的不同位中声明多个模板,但我不知道如何。我如何设置glStencilOp并glStencilFunc使其工作?
或者我可以(应该)使用glScissor它吗?