public void DrawLights(RenderObjects renderObjects, List<Light> lights, Matrix4 projectionMatrix, float zNear, Camera camera) { if (lights.Count == 0) { return; } Matrix4 invProjectionMatrix = Matrix4.Invert(projectionMatrix); Matrix4 invViewMatrix = Matrix4.Invert(camera.ViewMatrix); Matrix4 m = new Matrix4( new Vector4(2.0f, 0.0f, 0.0f, 0.0f), new Vector4(0.0f, 2.0f, 0.0f, 0.0f), new Vector4(0.0f, 0.0f, 2.0f, 0.0f), new Vector4(-1.0f, -1.0f, -1.0f, 1.0f)) * invProjectionMatrix; int idx = 0; foreach (Light light in lights) { idx++; if (light is SpotLight) { DrawLight(idx, renderObjects, (SpotLight)light, m, projectionMatrix, invViewMatrix, camera, zNear); } else // light is PointLight { DrawLight(idx, renderObjects, (PointLight)light, m, projectionMatrix, invViewMatrix, camera, zNear); } } }
void DrawLight(int idx, RenderObjects renderObjects, SpotLight light, Matrix4 m, Matrix4 projectionMatrix, Matrix4 invViewMatrix, Camera camera, float zNear) { using (RenderStateBinder binder = device.ChangeRenderState()) { device.RenderState.DepthWrite = true; device.RenderState.DepthTest = true; device.RenderState.ColorWrite = false; device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.PolygonOffset = true; device.RenderState.PolygonOffsetFactor = 0.0f; device.RenderState.PolygonOffsetUnits = -1.0f; device.ApplyRenderState(); shadow_fb.SetTexture2D(FramebufferAttachment.DepthAttachment, 0, shadow_texture); device.SetFramebuffer(shadow_fb); device.Clear(BufferMask.DepthBuffer); device.SetShader(generate_shadowmap); device.SetMatrix(MatrixModeEnum.Projection, light.ProjectionMatrix); renderObjects(light.ViewMatrix); } device.SetFramebuffer(lighting_fb); device.SetMatrix(MatrixModeEnum.Projection, projectionMatrix); using (RenderStateBinder binder = device.ChangeRenderState()) { device.SetShader(deferred_spotlight); deferred_spotlight.GetSampler("color_texture").Set(color_texture); deferred_spotlight.GetSampler("normal_texture").Set(normal_texture); deferred_spotlight.GetSampler("depth_texture").Set(depth_texture); deferred_spotlight.GetSampler("shadow_texture").Set(shadow_texture); deferred_spotlight.GetUniform("buffer_range").Set(1.0f / device.Width, 1.0f / device.Height); deferred_spotlight.GetUniform("ndc_to_view").Set(m); deferred_spotlight.GetUniform("shadow_matrix").Set(invViewMatrix * light.ShadowMatrix); deferred_spotlight.GetUniform("light_params").Set(light.Ambient, light.Diffuse, light.Specular, light.Shininess); deferred_spotlight.GetUniform("light_params2").Set(light.Length2, light.AngleParam1, light.AngleParam2, light.Exponent); deferred_spotlight.GetUniform("light_position").Set(Vector3.TransformPosition(light.Position, camera.ViewMatrix)); deferred_spotlight.GetUniform("light_direction").Set(Vector3.TransformVector(light.Direction, camera.ViewMatrix)); deferred_spotlight.GetUniform("light_color").Set(light.Color); device.SetVertexBuffer(spot_light_VB, 0); device.SetIndexBuffer(spot_light_IB); device.SetMatrix(MatrixModeEnum.ModelView, light.WorldMatrix * camera.ViewMatrix); bool inside = false; Vector3 p = (camera.Position + camera.ZAxis * zNear) - light.Position; float dot = Vector3.Dot(p, light.Direction); if (dot > 0.0f || dot < light.Length) { float cosBeta = dot / p.Length; if (cosBeta > Degrees.Cos(light.Angle + 5)) { inside = true; } } device.RenderState.DepthWrite = false; device.RenderState.Blend = true; device.RenderState.BlendingFuncDst = BlendingFactorDest.One; device.RenderState.BlendingFuncSrc = BlendingFactorSrc.One; if (inside) { device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.DepthFunction = DepthFunction.GEqual; device.RenderState.StencilTest = false; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, spot_light_primitives); } else { if (has_stencil) { device.RenderState.FrontFace = FrontFaceDirection.CW; device.RenderState.ColorWrite = false; device.RenderState.DepthFunction = DepthFunction.Less; device.RenderState.StencilTest = true; device.RenderState.StencilFunc = StencilFunction.Always; device.RenderState.StencilFail = StencilOpEnum.Keep; device.RenderState.StencilZFail = StencilOpEnum.Keep; device.RenderState.StencilZPass = StencilOpEnum.Replace; device.RenderState.StencilFuncReference = idx; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, spot_light_primitives); device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.ColorWrite = true; device.RenderState.DepthFunction = DepthFunction.GEqual; device.RenderState.StencilFunc = StencilFunction.Equal; device.RenderState.StencilZPass = StencilOpEnum.Keep; device.RenderState.StencilFuncReference = idx; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, spot_light_primitives); } else { device.RenderState.FrontFace = FrontFaceDirection.CW; device.RenderState.DepthFunction = DepthFunction.Less; device.RenderState.StencilTest = false; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, spot_light_primitives); } } } }
void DrawLight(int idx, RenderObjects renderObjects, PointLight light, Matrix4 m, Matrix4 projectionMatrix, Matrix4 invViewMatrix, Camera camera, float zNear) { using (RenderStateBinder binder = device.ChangeRenderState()) { device.RenderState.DepthWrite = true; device.RenderState.DepthTest = true; device.RenderState.ColorWrite = false; device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.PolygonOffset = true; device.RenderState.PolygonOffsetFactor = -1.0f; device.RenderState.PolygonOffsetUnits = -1.0f; device.ApplyRenderState(); device.SetShader(generate_dp_shadowmap); Vector3[,] direction = new Vector3[6, 2] { { -Vector3.UnitX, Vector3.UnitY }, { Vector3.UnitX, Vector3.UnitY }, { -Vector3.UnitY, -Vector3.UnitZ }, { Vector3.UnitY, Vector3.UnitZ }, { -Vector3.UnitZ, Vector3.UnitY }, { Vector3.UnitZ, Vector3.UnitY }, }; TextureTarget[] targets = new TextureTarget[6] { TextureTarget.TextureCubeMapPositiveX, TextureTarget.TextureCubeMapNegativeX, TextureTarget.TextureCubeMapPositiveY, TextureTarget.TextureCubeMapNegativeY, TextureTarget.TextureCubeMapPositiveZ, TextureTarget.TextureCubeMapNegativeZ, }; device.SetMatrix(MatrixModeEnum.Projection, Matrix4.Perspective(90.0f, 1.0f, Light.zNear, light.Radius)); device.SetFramebuffer(shadow_fb); for (int i = 0; i < 6; i++) { shadow_fb.SetTextureCubeMap(FramebufferAttachment.DepthAttachment, targets[i], 0, shadow_texture_cube); device.Clear(BufferMask.DepthBuffer); Matrix4 lightViewMatrix = Matrix4.LookAt(light.Position, light.Position + direction[i, 0], direction[i, 1]); renderObjects(lightViewMatrix); } //// front //shadow_fb.SetTexture2D(FramebufferAttachment.DepthAttachment, 0, shadow_texture[1]); //device.SetFramebuffer(shadow_fb); //device.Clear(BufferMask.DepthBuffer); //generate_dp_shadowmap.GetUniform("direction").Set(1.0f); //Vector3 pos = light.Position;// -new Vector3(0.0f, 0.0f, 0.02f); //Matrix4 lightViewMatrix = Matrix4.LookAt(pos, pos + Vector3.UnitZ, Vector3.UnitY); //renderObjects(lightViewMatrix); //// back //shadow_fb.SetTexture2D(FramebufferAttachment.DepthAttachment, 0, shadow_texture[2]); //device.Clear(BufferMask.DepthBuffer); //generate_dp_shadowmap.GetUniform("direction").Set(-1.0f); //pos = light.Position;// -new Vector3(0.0f, 0.0f, 0.02f); //lightViewMatrix = Matrix4.LookAt(pos, pos + Vector3.UnitZ, Vector3.UnitY); //renderObjects(lightViewMatrix); } device.SetFramebuffer(lighting_fb); device.SetMatrix(MatrixModeEnum.Projection, projectionMatrix); using (RenderStateBinder binder = device.ChangeRenderState()) { device.SetShader(deferred_pointlight); deferred_pointlight.GetSampler("color_texture").Set(color_texture); deferred_pointlight.GetSampler("normal_texture").Set(normal_texture); deferred_pointlight.GetSampler("depth_texture").Set(depth_texture); //deferred_pointlight.GetSampler("shadowFront_texture").Set(shadow_texture[1]); //deferred_pointlight.GetSampler("shadowBack_texture").Set(shadow_texture[2]); deferred_pointlight.GetSampler("shadow_texture").Set(shadow_texture_cube); deferred_pointlight.GetUniform("buffer_range").Set(1.0f / device.Width, 1.0f / device.Height); deferred_pointlight.GetUniform("ndc_to_view").Set(m); device.SetVertexBuffer(point_light_VB, 0); device.SetIndexBuffer(point_light_IB); deferred_pointlight.GetUniform("shadow_matrix").Set(invViewMatrix); deferred_pointlight.GetUniform("light_params").Set(light.Ambient, light.Diffuse, light.Specular, light.Shininess); deferred_pointlight.GetUniform("light_position").Set(Vector3.TransformPosition(light.Position, camera.ViewMatrix)); deferred_pointlight.GetUniform("light_positionW").Set(light.Position); deferred_pointlight.GetUniform("light_radius2").Set(light.Radius2); deferred_pointlight.GetUniform("light_color").Set(light.Color); deferred_pointlight.GetUniform("depth_param1").Set(light.DepthParam1); deferred_pointlight.GetUniform("depth_param2").Set(light.DepthParam2); device.SetMatrix(MatrixModeEnum.ModelView, light.WorldMatrix * camera.ViewMatrix); Vector3 p = camera.Position - light.Position; device.RenderState.DepthWrite = false; device.RenderState.Blend = true; device.RenderState.BlendingFuncDst = BlendingFactorDest.One; device.RenderState.BlendingFuncSrc = BlendingFactorSrc.One; if (p.Length < light.Radius + 2.0f * zNear) { device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.DepthFunction = DepthFunction.GEqual; device.RenderState.StencilTest = false; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, point_light_primitives); } else { if (has_stencil) { device.RenderState.FrontFace = FrontFaceDirection.CW; device.RenderState.ColorWrite = false; device.RenderState.DepthFunction = DepthFunction.Less; device.RenderState.StencilTest = true; device.RenderState.StencilFunc = StencilFunction.Always; device.RenderState.StencilFail = StencilOpEnum.Keep; device.RenderState.StencilZFail = StencilOpEnum.Keep; device.RenderState.StencilZPass = StencilOpEnum.Replace; device.RenderState.StencilFuncReference = idx; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, point_light_primitives); device.RenderState.FrontFace = FrontFaceDirection.CCW; device.RenderState.ColorWrite = true; device.RenderState.DepthFunction = DepthFunction.GEqual; device.RenderState.StencilFunc = StencilFunction.Equal; device.RenderState.StencilZPass = StencilOpEnum.Keep; device.RenderState.StencilFuncReference = idx; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, point_light_primitives); } else { device.RenderState.FrontFace = FrontFaceDirection.CW; device.RenderState.DepthFunction = DepthFunction.Less; device.RenderState.StencilTest = false; device.ApplyRenderState(); device.DrawElements(BeginMode.TriangleStrip, 0, point_light_primitives); } } } }
public void Render(RenderObjects renderObjects, Matrix4 projectionMatrix, Matrix4 viewMatrix) { device.SetFramebuffer(deferred_fb); using (RenderStateBinder binder = device.ChangeRenderState()) { device.RenderState.DepthWrite = true; device.RenderState.DepthTest = true; device.ApplyRenderState(); device.Clear(BufferMask.ColorBuffer | BufferMask.DepthBuffer | BufferMask.StencilBuffer); } device.SetShader(deferred_geometry); device.SetMatrix(MatrixModeEnum.Projection, projectionMatrix); renderObjects(viewMatrix); // TODO: add this as last pass device.SetFramebuffer(lighting_fb); using (RenderStateBinder binder = device.ChangeRenderState()) { device.RenderState.DepthTest = false; device.RenderState.DepthWrite = false; device.ApplyRenderState(); device.SetShader(deferred_ambient); deferred_ambient.GetSampler("color_texture").Set(color_texture); deferred_ambient.GetUniform("ambient_light").Set(0.7f); // TODO: full diffuse color for directional light device.SetVertexBuffer(unit_quad_VB, 0); device.DrawArrays(BeginMode.TriangleStrip, 0, 4); } }