/// <summary> /// Adds refraction data to the G-Buffer ("FBO"). /// </summary> public void RenderPass_RefractionBuffer(Stopwatch timer) { FBOid = FBOID.REFRACT; TheClient.s_fbov_refract = TheClient.s_fbov_refract.Bind(); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform2(8, new Vector2(TheClient.sl_min, TheClient.sl_max)); TheClient.s_fbo_refract = TheClient.s_fbo_refract.Bind(); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.DepthMask(false); if (TheClient.CVars.r_3d_enable.ValueB) { GL.Viewport(Width / 2, 0, Width / 2, Height); Render3D(this); CFrust = cf2; GL.Viewport(0, 0, Width / 2, Height); CameraPos = cameraBasePos - cameraAdjust; TheClient.s_fbov_refract = TheClient.s_fbov_refract.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix_OffsetFor3D); TheClient.s_fbo_refract = TheClient.s_fbo_refract.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix_OffsetFor3D); Render3D(this); GL.Viewport(0, 0, Width, Height); CameraPos = cameraBasePos + cameraAdjust; CFrust = camFrust; } else { Render3D(this); } CheckError("AfterRefract"); GL.DepthMask(true); RenderLights = false; RenderSpecular = false; RS4P.Unbind(); FBOid = FBOID.NONE; timer.Stop(); FBOTime = (double)timer.ElapsedMilliseconds / 1000f; if (FBOTime > FBOSpikeTime) { FBOSpikeTime = FBOTime; } }
/// <summary> /// Generate the G-Buffer ("FBO") for lighting and final passes. /// </summary> public void RenderPass_GBuffer() { Stopwatch timer = new Stopwatch(); timer.Start(); SetViewport(); TheClient.s_fbov = TheClient.s_fbov.Bind(); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform2(8, new Vector2(TheClient.sl_min, TheClient.sl_max)); TheClient.s_fbot = TheClient.s_fbot.Bind(); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); TheClient.s_fbo = TheClient.s_fbo.Bind(); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); FBOid = FBOID.MAIN; RenderingShadows = false; CFrust = camFrust; GL.ActiveTexture(TextureUnit.Texture0); RS4P.Bind(); RenderLights = true; RenderSpecular = true; TheClient.Rendering.SetColor(Color4.White); StandardBlend(); if (TheClient.CVars.r_3d_enable.ValueB) { GL.Viewport(Width / 2, 0, Width / 2, Height); Render3D(this); CFrust = cf2; GL.Viewport(0, 0, Width / 2, Height); CameraPos = cameraBasePos - cameraAdjust; TheClient.s_fbov = TheClient.s_fbov.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); TheClient.s_fbot = TheClient.s_fbot.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); TheClient.s_fbo = TheClient.s_fbo.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); Render3D(this); GL.Viewport(0, 0, Width, Height); CameraPos = cameraBasePos + cameraAdjust; CFrust = camFrust; } else { Render3D(this); } CheckError("AfterFBO"); RenderPass_RefractionBuffer(timer); }
/// <summary> /// Render everything as quickly as possible: a simple forward renderer. /// </summary> public void RenderPass_FAST() { RenderingShadows = false; GL.ActiveTexture(TextureUnit.Texture0); FBOid = FBOID.FORWARD_SOLID; TheClient.s_forw_vox.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); TheClient.Rendering.SetColor(Color4.White); TheClient.s_forw.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); TheClient.Rendering.SetColor(Color4.White); Render3D(this); FBOid = FBOID.FORWARD_TRANSP; TheClient.s_forw_vox_trans.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); TheClient.Rendering.SetColor(Color4.White); TheClient.s_forw_trans.Bind(); GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(6, (float)TheClient.GlobalTickTimeLocal); TheClient.Rendering.SetColor(Color4.White); if (PostFirstRender != null) { PostFirstRender(); } GL.DepthMask(false); Render3D(this); GL.DepthMask(true); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.DrawBuffer(DrawBufferMode.Back); CheckError("AfterFast"); }
/// <summary> /// Apply godrays, bloom, and transparent data to screen. /// </summary> public void RenderPass_Bloom(int lightc) { GL.BindFramebuffer(FramebufferTarget.Framebuffer, CurrentFBO); GL.DrawBuffer(CurrentFBO == 0 ? DrawBufferMode.Back : DrawBufferMode.ColorAttachment0); StandardBlend(); FBOid = FBOID.NONE; GL.ActiveTexture(TextureUnit.Texture0); GL.Disable(EnableCap.CullFace); GL.ClearBuffer(ClearBuffer.Depth, 0, new float[] { 1f }); GL.Disable(EnableCap.DepthTest); CheckError("PreGR"); if (TheClient.CVars.r_godrays.ValueB) // TODO: Local disable? Non-primary views probably don't need godrays... { // TODO: 3d stuff for GodRays. GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(TextureTarget.Texture2D, RS4P.DepthTexture); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, fbo_godray_texture2); TheClient.s_godray = TheClient.s_godray.Bind(); GL.UniformMatrix4(1, false, ref SimpleOrthoMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(6, MainEXP); GL.Uniform1(7, Width / (float)Height); if (SunLoc.IsNaN()) { GL.Uniform2(8, new Vector2(-10f, -10f)); } else { Vector4d v = Vector4d.Transform(new Vector4d(ClientUtilities.ConvertD(SunLoc), 1.0), PrimaryMatrixd); if (v.Z / v.W > 1.0f || v.Z / v.W < 0.0f) { GL.Uniform2(8, new Vector2(-10f, -10f)); } else { Vector2d lp1 = (v.Xy / v.W) * 0.5f + new Vector2d(0.5f); GL.Uniform2(8, new Vector2((float)lp1.X, (float)lp1.Y)); float lplenadj = (float)((1.0 - Math.Min(lp1.Length, 1.0)) * (0.99 - 0.6) + 0.6); GL.Uniform1(12, 0.84f * lplenadj); } } GL.Uniform1(14, TheClient.CVars.r_znear.ValueF); GL.Uniform1(15, TheClient.CVars.r_zfar.ValueF); GL.Uniform1(16, TheClient.dist); // TODO: Local controlled variable. TranspBlend(); TheClient.Rendering.RenderRectangle(-1, -1, 1, 1); StandardBlend(); } CheckError("PostGR"); { // TODO: Merge transp-to-screen and GR pass? //GL.Enable(EnableCap.DepthTest); GL.BindTexture(TextureTarget.Texture2D, transp_fbo_texture); TheClient.s_transpadder = TheClient.s_transpadder.Bind(); GL.UniformMatrix4(1, false, ref SimpleOrthoMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(3, (float)lightc); TheClient.Rendering.RenderRectangle(-1, -1, 1, 1); } GL.UseProgram(0); GL.BindTexture(TextureTarget.Texture2D, 0); GL.DepthMask(true); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); CheckError("WrapUp"); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.DrawBuffer(DrawBufferMode.Back); }
public int RenderPass_Transparents() { if (TheClient.CVars.r_transplighting.ValueB) { if (TheClient.CVars.r_transpshadows.ValueB && TheClient.CVars.r_shadows.ValueB) { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvoxlitsh_ll = TheClient.s_transponlyvoxlitsh_ll.Bind(); } else { TheClient.s_transponlyvoxlitsh = TheClient.s_transponlyvoxlitsh.Bind(); } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvoxlit_ll = TheClient.s_transponlyvoxlit_ll.Bind(); } else { TheClient.s_transponlyvoxlit = TheClient.s_transponlyvoxlit.Bind(); } } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvox_ll = TheClient.s_transponlyvox_ll.Bind(); } else { TheClient.s_transponlyvox = TheClient.s_transponlyvox.Bind(); } } GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(4, DesaturationAmount); if (TheClient.CVars.r_transplighting.ValueB) { if (TheClient.CVars.r_transpshadows.ValueB && TheClient.CVars.r_shadows.ValueB) { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlylitsh_ll = TheClient.s_transponlylitsh_ll.Bind(); FBOid = FBOID.TRANSP_SHADOWS_LL; } else { TheClient.s_transponlylitsh = TheClient.s_transponlylitsh.Bind(); FBOid = FBOID.TRANSP_SHADOWS; } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlylit_ll = TheClient.s_transponlylit_ll.Bind(); FBOid = FBOID.TRANSP_LIT_LL; } else { TheClient.s_transponlylit = TheClient.s_transponlylit.Bind(); FBOid = FBOID.TRANSP_LIT; } } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponly_ll = TheClient.s_transponly_ll.Bind(); FBOid = FBOID.TRANSP_LL; } else { TheClient.s_transponly = TheClient.s_transponly.Bind(); FBOid = FBOID.TRANSP_UNLIT; } } GL.UniformMatrix4(1, false, ref PrimaryMatrix); GL.UniformMatrix4(2, false, ref IdentityMatrix); GL.Uniform1(4, DesaturationAmount); GL.DepthMask(false); if (TheClient.CVars.r_transpll.ValueB) { StandardBlend(); } else { TranspBlend(); } GL.BindFramebuffer(FramebufferTarget.Framebuffer, transp_fbo_main); GL.DrawBuffer(DrawBufferMode.ColorAttachment0); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, RS4P.fbo); GL.BlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, ClearBufferMask.DepthBufferBit, BlitFramebufferFilter.Nearest); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, 0); GL.ClearBuffer(ClearBuffer.Color, 0, new float[] { 0f, 0f, 0f, 0f }); int lightc = 0; CheckError("PreTransp"); if (TheClient.CVars.r_3d_enable.ValueB) { GL.Viewport(Width / 2, 0, Width / 2, Height); CameraPos = cameraBasePos + cameraAdjust; RenderTransp(ref lightc); CFrust = cf2; GL.Viewport(0, 0, Width / 2, Height); CFrust = cf2; if (TheClient.CVars.r_transplighting.ValueB) { if (TheClient.CVars.r_transpshadows.ValueB && TheClient.CVars.r_shadows.ValueB) { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvoxlitsh_ll = TheClient.s_transponlyvoxlitsh_ll.Bind(); } else { TheClient.s_transponlyvoxlitsh = TheClient.s_transponlyvoxlitsh.Bind(); } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvoxlit_ll = TheClient.s_transponlyvoxlit_ll.Bind(); } else { TheClient.s_transponlyvoxlit = TheClient.s_transponlyvoxlit.Bind(); } } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlyvox_ll = TheClient.s_transponlyvox_ll.Bind(); } else { TheClient.s_transponlyvox = TheClient.s_transponlyvox.Bind(); } } GL.UniformMatrix4(1, false, ref PrimaryMatrix_OffsetFor3D); if (TheClient.CVars.r_transplighting.ValueB) { if (TheClient.CVars.r_transpshadows.ValueB && TheClient.CVars.r_shadows.ValueB) { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlylitsh_ll = TheClient.s_transponlylitsh_ll.Bind(); FBOid = FBOID.TRANSP_SHADOWS_LL; } else { TheClient.s_transponlylitsh = TheClient.s_transponlylitsh.Bind(); FBOid = FBOID.TRANSP_SHADOWS; } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponlylit_ll = TheClient.s_transponlylit_ll.Bind(); FBOid = FBOID.TRANSP_LIT_LL; } else { TheClient.s_transponlylit = TheClient.s_transponlylit.Bind(); FBOid = FBOID.TRANSP_LIT; } } } else { if (TheClient.CVars.r_transpll.ValueB) { TheClient.s_transponly_ll = TheClient.s_transponly_ll.Bind(); FBOid = FBOID.TRANSP_LL; } else { TheClient.s_transponly = TheClient.s_transponly.Bind(); FBOid = FBOID.TRANSP_UNLIT; } } GL.UniformMatrix4(1, false, ref PrimaryMatrix_OffsetFor3D); CameraPos = cameraBasePos - cameraAdjust; RenderTransp(ref lightc, cf2); GL.Viewport(0, 0, Width, Height); CameraPos = cameraBasePos + cameraAdjust; CFrust = camFrust; } else { RenderTransp(ref lightc); } if (lightc == 0) { lightc = 1; } CheckError("AfterTransp"); return lightc; }
/// <summary> /// Calculate shadow maps for the later (lighting) render passes. /// </summary> public void RenderPass_Shadows() { if (TheClient.shouldRedrawShadows && ShadowingAllowed) { Stopwatch timer = new Stopwatch(); timer.Start(); TheClient.s_shadow = TheClient.s_shadow.Bind(); TheClient.FixPersp = Matrix4.Identity; RenderingShadows = true; ShadowsOnly = true; LightsC = 0; Location campos = CameraPos; int n = 0; Frustum tcf = CFrust; for (int i = 0; i < Lights.Count; i++) { if (Lights[i] is SkyLight || camFrust == null || camFrust.ContainsSphere(Lights[i].EyePos.ToBVector(), Lights[i].MaxDistance)) { if (Lights[i] is SkyLight || Lights[i].EyePos.DistanceSquared(CameraPos) < TheClient.CVars.r_lightmaxdistance.ValueD * TheClient.CVars.r_lightmaxdistance.ValueD + Lights[i].MaxDistance * Lights[i].MaxDistance * 6) { LightsC++; for (int x = 0; x < Lights[i].InternalLights.Count; x++) { GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo_shadow[n]); if (Lights[i].InternalLights[x].color.LengthSquared <= 0.01) { continue; } if (Lights[i].InternalLights[x] is LightOrtho) { CFrust = null; } else { CFrust = new Frustum(ClientUtilities.ConvertToD(Lights[i].InternalLights[x].GetMatrix())); } CameraPos = ClientUtilities.ConvertD(Lights[i].InternalLights[x].eye); TheClient.s_shadowvox = TheClient.s_shadowvox.Bind(); GL.UniformMatrix4(2, false, ref IdentityMatrix); Lights[i].InternalLights[x].SetProj(); if (Lights[i].InternalLights[x] is LightOrtho) { GL.Uniform1(3, 1.0f); } else { GL.Uniform1(3, 0.0f); } GL.Uniform1(4, Lights[i].InternalLights[x].transp ? 1.0f : 0.0f); FBOid = FBOID.SHADOWS; TheClient.s_shadow = TheClient.s_shadow.Bind(); GL.UniformMatrix4(2, false, ref IdentityMatrix); if (Lights[i].InternalLights[x] is LightOrtho) { GL.Uniform1(3, 1.0f); } else { GL.Uniform1(3, 0.0f); } GL.Uniform1(4, Lights[i].InternalLights[x].transp ? 1.0f : 0.0f); TranspShadows = Lights[i].InternalLights[x].transp; Lights[i].InternalLights[x].SetProj(); GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo_shadow[n]); GL.DrawBuffer(DrawBufferMode.ColorAttachment0); GL.ClearBuffer(ClearBuffer.Depth, 0, new float[] { 1f }); GL.ClearBuffer(ClearBuffer.Color, 0, new float[] { 1f }); GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.Zero); Render3D(this); FBOid = FBOID.NONE; n++; if (n >= LIGHTS_MAX) { goto complete; } } } } } complete: CFrust = tcf; GL.BindFramebuffer(FramebufferTarget.Framebuffer, CurrentFBO); GL.DrawBuffer(CurrentFBO == 0 ? DrawBufferMode.Back : DrawBufferMode.ColorAttachment0); CameraPos = campos; RenderingShadows = false; ShadowsOnly = false; timer.Stop(); ShadowTime = (double)timer.ElapsedMilliseconds / 1000f; if (ShadowTime > ShadowSpikeTime) { ShadowSpikeTime = ShadowTime; } StandardBlend(); CheckError("AfterShadows"); } }