Пример #1
0
//-----------------------------------------------------------------------------
//
// End
//
//-----------------------------------------------------------------------------
void GLPortal::End(bool usestencil)
{
	bool needdepth = NeedDepthBuffer();

	PortalAll.Clock();
	GLRenderer->mCurrentPortal = NextPortal;
	if (clipsave) glEnable (GL_CLIP_PLANE0+renderdepth-1);
	if (usestencil)
	{
		if (needdepth) FDrawInfo::EndDrawInfo();

		// Restore the old view
		viewx=savedviewx;
		viewy=savedviewy;
		viewz=savedviewz;
		viewangle=savedviewangle;
		GLRenderer->mViewActor=savedviewactor;
		in_area=savedviewarea;
		GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

		glColor4f(1,1,1,1);
		glColorMask(0,0,0,0);						// no graphics
		glColor3f(1,1,1);
		gl_RenderState.EnableTexture(false);
		gl_RenderState.Apply();

		if (needdepth) 
		{
			// first step: reset the depth buffer to max. depth
			glDepthRange(1,1);							// always
			glDepthFunc(GL_ALWAYS);						// write the farthest depth value
			DrawPortalStencil();
		}
		else
		{
			glEnable(GL_DEPTH_TEST);
		}
		
		// second step: restore the depth buffer to the previous values and reset the stencil
		glDepthFunc(GL_LEQUAL);
		glDepthRange(0,1);
		glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
		glStencilFunc(GL_EQUAL,recursion,~0);		// draw sky into stencil
		DrawPortalStencil();
		glDepthFunc(GL_LESS);


		gl_RenderState.EnableTexture(true);
		glColorMask(1,1,1,1);
		recursion--;

		// restore old stencil op.
		glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
		glStencilFunc(GL_EQUAL,recursion,~0);		// draw sky into stencil
	}
	else
	{
		if (needdepth) 
		{
			FDrawInfo::EndDrawInfo();
			glClear(GL_DEPTH_BUFFER_BIT);
		}
		else
		{
			glEnable(GL_DEPTH_TEST);
			glDepthMask(true);
		}
		// Restore the old view
		viewx=savedviewx;
		viewy=savedviewy;
		viewz=savedviewz;
		viewangle=savedviewangle;
		GLRenderer->mViewActor=savedviewactor;
		in_area=savedviewarea;
		GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

		// This draws a valid z-buffer into the stencil's contents to ensure it
		// doesn't get overwritten by the level's geometry.

		glColor4f(1,1,1,1);
		glDepthFunc(GL_LEQUAL);
		glDepthRange(0,1);
		glColorMask(0,0,0,0);						// no graphics
		gl_RenderState.EnableTexture(false);
		DrawPortalStencil();
		gl_RenderState.EnableTexture(true);
		glColorMask(1,1,1,1);
		glDepthFunc(GL_LESS);
	}
	PortalAll.Unclock();
}
Пример #2
0
bool GLPortal::Start(bool usestencil, bool doquery)
{
	rendered_portals++;
	PortalAll.Clock();
	if (usestencil)
	{
		if (!gl_portals) 
		{
			PortalAll.Unclock();
			return false;
		}
	
		// Create stencil 
		glStencilFunc(GL_EQUAL,recursion,~0);		// create stencil
		glStencilOp(GL_KEEP,GL_KEEP,GL_INCR);		// increment stencil of valid pixels
		glColorMask(0,0,0,0);						// don't write to the graphics buffer
		gl_RenderState.EnableTexture(false);
		glColor3f(1,1,1);
		glDepthFunc(GL_LESS);
		gl_RenderState.Apply();

		if (NeedDepthBuffer())
		{
			glDepthMask(false);							// don't write to Z-buffer!
			if (!NeedDepthBuffer()) doquery = false;		// too much overhead and nothing to gain.
			else if (gl_noquery) doquery = false;
			
			// If occlusion query is supported let's use it to avoid rendering portals that aren't visible
			if (!QueryObject) glGenQueries(1, &QueryObject);
			if (QueryObject) 
			{
				glBeginQuery(GL_SAMPLES_PASSED_ARB, QueryObject);
			}
			else doquery = false;	// some kind of error happened

			DrawPortalStencil();

			glEndQuery(GL_SAMPLES_PASSED_ARB);

			// Clear Z-buffer
			glStencilFunc(GL_EQUAL,recursion+1,~0);		// draw sky into stencil
			glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);		// this stage doesn't modify the stencil
			glDepthMask(true);							// enable z-buffer again
			glDepthRange(1,1);
			glDepthFunc(GL_ALWAYS);
			DrawPortalStencil();

			// set normal drawing mode
			gl_RenderState.EnableTexture(true);
			glDepthFunc(GL_LESS);
			glColorMask(1,1,1,1);
			glDepthRange(0,1);

			GLuint sampleCount;

			glGetQueryObjectuiv(QueryObject, GL_QUERY_RESULT_ARB, &sampleCount);

			if (sampleCount==0) 	// not visible
			{
				// restore default stencil op.
				glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
				glStencilFunc(GL_EQUAL,recursion,~0);		// draw sky into stencil
				PortalAll.Unclock();
				return false;
			}
			FDrawInfo::StartDrawInfo();
		}
		else
		{
			// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
			// No occlusion queries will be done here. For these portals the overhead is far greater
			// than the benefit.
			// Note: We must draw the stencil with z-write enabled here because there is no second pass!

			glDepthMask(true);
			DrawPortalStencil();
			glStencilFunc(GL_EQUAL,recursion+1,~0);		// draw sky into stencil
			glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);		// this stage doesn't modify the stencil
			gl_RenderState.EnableTexture(true);
			glColorMask(1,1,1,1);
			glDisable(GL_DEPTH_TEST);
			glDepthMask(false);							// don't write to Z-buffer!
		}
		recursion++;


	}
	else
	{
		if (NeedDepthBuffer())
		{
			FDrawInfo::StartDrawInfo();
		}
		else
		{
			glDepthMask(false);
			glDisable(GL_DEPTH_TEST);
		}
	}
	// The clip plane from the previous portal must be deactivated for this one.
	clipsave = glIsEnabled(GL_CLIP_PLANE0+renderdepth-1);
	if (clipsave) glDisable(GL_CLIP_PLANE0+renderdepth-1);

	// save viewpoint
	savedviewx=viewx;
	savedviewy=viewy;
	savedviewz=viewz;
	savedviewactor=GLRenderer->mViewActor;
	savedviewangle=viewangle;
	savedviewarea=in_area;

	NextPortal = GLRenderer->mCurrentPortal;
	GLRenderer->mCurrentPortal = NULL;	// Portals which need this have to set it themselves
	PortalAll.Unclock();
	return true;
}
Пример #3
0
//-----------------------------------------------------------------------------
//
// End
//
//-----------------------------------------------------------------------------
void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
	Clocker c(PortalAll);
	bool needdepth = NeedDepthBuffer();

	// Restore the old view
	auto &vp = di->Viewpoint;
	if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;

	if (usestencil)
	{
		
		state.SetColorMask(false);						// no graphics
		state.SetEffect(EFF_NONE);
		state.ResetColor();
		state.EnableTexture(false);
		
		if (needdepth)
		{
			// first step: reset the depth buffer to max. depth
			state.SetDepthRange(1, 1);							// always
			state.SetDepthFunc(DF_Always);						// write the farthest depth value
			DrawPortalStencil(state, STP_DepthClear);
		}
		else
		{
			state.EnableDepthTest(true);
		}
		
		// second step: restore the depth buffer to the previous values and reset the stencil
		state.SetDepthFunc(DF_LEqual);
		state.SetDepthRange(0, 1);
		state.SetStencil(0, SOP_Decrement);
		DrawPortalStencil(state, STP_DepthRestore);
		state.SetDepthFunc(DF_Less);
		
		
		state.EnableTexture(true);
		state.SetEffect(EFF_NONE);
		state.SetColorMask(true);
		screen->stencilValue--;
		
		// restore old stencil op.
		state.SetStencil(0, SOP_Keep);
	}
	else
	{
		if (needdepth)
		{
			state.Clear(CT_Depth);
		}
		else
		{
			state.EnableDepthTest(true);
			state.SetDepthMask(true);
		}
		
		// This draws a valid z-buffer into the stencil's contents to ensure it
		// doesn't get overwritten by the level's geometry.
		
		state.ResetColor();
		state.SetDepthFunc(DF_LEqual);
		state.SetDepthRange(0, 1);
		state.SetColorMask(0, 0, 0, 1); // mark portal in alpha channel but don't touch color
		state.SetEffect(EFF_STENCIL);
		state.EnableTexture(false);
		state.SetRenderStyle(STYLE_Source);
		DrawPortalStencil(state, STP_DepthRestore);
		state.SetEffect(EFF_NONE);
		state.EnableTexture(true);
		state.SetColorMask(true);
		state.SetDepthFunc(DF_Less);
	}
}
Пример #4
0
void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
	Clocker c(PortalAll);

	rendered_portals++;
	
	if (usestencil)
	{
		// Create stencil
		state.SetStencil(0, SOP_Increment);	// create stencil, increment stencil of valid pixels
		state.SetColorMask(false);
		state.SetEffect(EFF_STENCIL);
		state.EnableTexture(false);
		state.ResetColor();
		state.SetDepthFunc(DF_Less);
			
		if (NeedDepthBuffer())
		{
			state.SetDepthMask(false);							// don't write to Z-buffer!
				
			DrawPortalStencil(state, STP_Stencil);
				
			// Clear Z-buffer
			state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
			state.SetDepthMask(true);							// enable z-buffer again
			state.SetDepthRange(1, 1);
			state.SetDepthFunc(DF_Always);
			DrawPortalStencil(state, STP_DepthClear);
				
			// set normal drawing mode
			state.EnableTexture(true);
			state.SetDepthRange(0, 1);
			state.SetDepthFunc(DF_Less);
			state.SetColorMask(true);
			state.SetEffect(EFF_NONE);
		}
		else
		{
			// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
			// Note: We must draw the stencil with z-write enabled here because there is no second pass!
				
			state.SetDepthMask(true);
			DrawPortalStencil(state, STP_AllInOne);
			state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
			state.EnableTexture(true);
			state.SetColorMask(true);
			state.SetEffect(EFF_NONE);
			state.EnableDepthTest(false);
			state.SetDepthMask(false);							// don't write to Z-buffer!
		}
		screen->stencilValue++;
		
		
	}
	else
	{
		if (!NeedDepthBuffer())
		{
			state.SetDepthMask(false);
			state.EnableDepthTest(false);
		}
	}

	// save viewpoint
	savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
}
Пример #5
0
//-----------------------------------------------------------------------------
//
// End
//
//-----------------------------------------------------------------------------
void GLPortal::End(bool usestencil)
{
	bool needdepth = NeedDepthBuffer();

	PortalAll.Clock();
	if (PrevPortal != NULL) PrevPortal->PopState();
	GLRenderer->mCurrentPortal = PrevPortal;
	GLRenderer->mClipPortal = PrevClipPortal;

	if (usestencil)
	{
		if (needdepth) FDrawInfo::EndDrawInfo();

		// Restore the old view
		ViewPath[0] = savedviewpath[0];
		ViewPath[1] = savedviewpath[1];
		ViewPos = savedViewPos;
		ViewAngle = savedAngle;
		GLRenderer->mViewActor=savedviewactor;
		in_area=savedviewarea;
		if (camera != nullptr) camera->renderflags = (camera->renderflags & ~RF_INVISIBLE) | savedvisibility;
		GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));

		{
			ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0, 0, 0, 0);						// no graphics
			gl_RenderState.SetEffect(EFF_NONE);
			gl_RenderState.ResetColor();
			gl_RenderState.EnableTexture(false);
			gl_RenderState.Apply();

			if (needdepth)
			{
				// first step: reset the depth buffer to max. depth
				glDepthRange(1, 1);							// always
				glDepthFunc(GL_ALWAYS);						// write the farthest depth value
				DrawPortalStencil();
			}
			else
			{
				glEnable(GL_DEPTH_TEST);
			}

			// second step: restore the depth buffer to the previous values and reset the stencil
			glDepthFunc(GL_LEQUAL);
			glDepthRange(0, 1);
			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
			glStencilFunc(GL_EQUAL, recursion, ~0);		// draw sky into stencil
			DrawPortalStencil();
			glDepthFunc(GL_LESS);


			gl_RenderState.EnableTexture(true);
			gl_RenderState.SetEffect(EFF_NONE);
		}  // glColorMask(1, 1, 1, 1);
		recursion--;

		// restore old stencil op.
		glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
		glStencilFunc(GL_EQUAL,recursion,~0);		// draw sky into stencil
	}
	else
	{
		if (needdepth) 
		{
			FDrawInfo::EndDrawInfo();
			glClear(GL_DEPTH_BUFFER_BIT);
		}
		else
		{
			glEnable(GL_DEPTH_TEST);
			glDepthMask(true);
		}
		// Restore the old view
		ViewPos = savedViewPos;
		ViewAngle = savedAngle;
		GLRenderer->mViewActor=savedviewactor;
		in_area=savedviewarea;
		if (camera != nullptr) camera->renderflags |= savedvisibility;
		GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

		// This draws a valid z-buffer into the stencil's contents to ensure it
		// doesn't get overwritten by the level's geometry.

		gl_RenderState.ResetColor();
		glDepthFunc(GL_LEQUAL);
		glDepthRange(0, 1);
		{
			ScopedColorMask colorMask(0, 0, 0, 0); 
			// glColorMask(0,0,0,0);						// no graphics
			gl_RenderState.SetEffect(EFF_STENCIL);
			gl_RenderState.EnableTexture(false);
			DrawPortalStencil();
			gl_RenderState.SetEffect(EFF_NONE);
			gl_RenderState.EnableTexture(true);
		} // glColorMask(1, 1, 1, 1);
		glDepthFunc(GL_LESS);
	}
	PortalAll.Unclock();
}
Пример #6
0
bool GLPortal::Start(bool usestencil, bool doquery)
{
	rendered_portals++;
	PortalAll.Clock();
	if (usestencil)
	{
		if (!gl_portals) 
		{
			PortalAll.Unclock();
			return false;
		}
	
		// Create stencil 
		glStencilFunc(GL_EQUAL,recursion,~0);		// create stencil
		glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);		// increment stencil of valid pixels
		{
			ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0,0,0,0);						// don't write to the graphics buffer
			gl_RenderState.SetEffect(EFF_STENCIL);
			gl_RenderState.EnableTexture(false);
			gl_RenderState.ResetColor();
			glDepthFunc(GL_LESS);
			gl_RenderState.Apply();

			if (NeedDepthBuffer())
			{
				glDepthMask(false);							// don't write to Z-buffer!
				if (!NeedDepthBuffer()) doquery = false;		// too much overhead and nothing to gain.
				else if (gl_noquery) doquery = false;

				// If occlusion query is supported let's use it to avoid rendering portals that aren't visible
				if (!QueryObject && doquery) glGenQueries(1, &QueryObject);
				if (QueryObject)
				{
					glBeginQuery(GL_SAMPLES_PASSED, QueryObject);
				}
				else doquery = false;	// some kind of error happened

				DrawPortalStencil();

				glEndQuery(GL_SAMPLES_PASSED);

				// Clear Z-buffer
				glStencilFunc(GL_EQUAL, recursion + 1, ~0);		// draw sky into stencil
				glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);		// this stage doesn't modify the stencil
				glDepthMask(true);							// enable z-buffer again
				glDepthRange(1, 1);
				glDepthFunc(GL_ALWAYS);
				DrawPortalStencil();

				// set normal drawing mode
				gl_RenderState.EnableTexture(true);
				glDepthFunc(GL_LESS);
				// glColorMask(1, 1, 1, 1);
				gl_RenderState.SetEffect(EFF_NONE);
				glDepthRange(0, 1);

				GLuint sampleCount;

				if (QueryObject)
				{
					glGetQueryObjectuiv(QueryObject, GL_QUERY_RESULT, &sampleCount);

					if (sampleCount == 0) 	// not visible
					{
						// restore default stencil op.
						glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
						glStencilFunc(GL_EQUAL, recursion, ~0);		// draw sky into stencil
						PortalAll.Unclock();
						return false;
					}
				}
				FDrawInfo::StartDrawInfo();
			}
			else
			{
				// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
				// No occlusion queries will be done here. For these portals the overhead is far greater
				// than the benefit.
				// Note: We must draw the stencil with z-write enabled here because there is no second pass!

				glDepthMask(true);
				DrawPortalStencil();
				glStencilFunc(GL_EQUAL, recursion + 1, ~0);		// draw sky into stencil
				glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);		// this stage doesn't modify the stencil
				gl_RenderState.EnableTexture(true);
				// glColorMask(1,1,1,1);
				gl_RenderState.SetEffect(EFF_NONE);
				glDisable(GL_DEPTH_TEST);
				glDepthMask(false);							// don't write to Z-buffer!
			}
		}
		recursion++;


	}
	else
	{
		if (NeedDepthBuffer())
		{
			FDrawInfo::StartDrawInfo();
		}
		else
		{
			glDepthMask(false);
			glDisable(GL_DEPTH_TEST);
		}
	}

	// save viewpoint
	savedViewPos = ViewPos;
	savedAngle = ViewAngle;
	savedviewactor=GLRenderer->mViewActor;
	savedviewarea=in_area;
	savedviewpath[0] = ViewPath[0];
	savedviewpath[1] = ViewPath[1];
	savedvisibility = camera ? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0);


	PrevPortal = GLRenderer->mCurrentPortal;
	PrevClipPortal = GLRenderer->mClipPortal;
	GLRenderer->mClipPortal = NULL;	// Portals which need this have to set it themselves
	GLRenderer->mCurrentPortal = this;

	if (PrevPortal != NULL) PrevPortal->PushState();
	PortalAll.Unclock();
	return true;
}