Beispiel #1
0
        void SetupDeferredPathway()
        {
            if (DeferredSetup || !DeferredEnabled)
            {
                return;
            }
            DeferredSetup = true;
            FBO           = new FrameBuffer(Width, Height,
                                            FrameBufferAttachment.Rgb, FrameBufferAttachment.Xyz,
                                            FrameBufferAttachment.Depth);
            Resize += (_, __) => FBO.Resize(Width, Height);

            QuadVAO = new Vao();
            QuadVAO.Attach(new Buffer <uint>(new[] { 0U, 1U, 2U, 3U, 4U, 5U }, BufferTarget.ElementArrayBuffer));
            QuadVAO.Attach(new Buffer <float>(new[] {
                -1f, -1f,
                1f, -1f,
                1f, 1f,

                -1f, -1f,
                1f, 1f,
                -1f, 1f
            }), (0, typeof(Vector2)));

            Program = new Program(@"
#version 410
precision highp float;
in vec2 aPosition;
out vec2 vTexCoord;
void main() {
	gl_Position = vec4(aPosition, 0.0, 1.0);
	vTexCoord = aPosition.xy * 0.5 + 0.5;
}
			"            , @"
#version 410
precision highp float;
in vec2 vTexCoord;

struct Light {
	vec3 pos, color;
	float radius;
};

uniform mat4 uInvProjectionViewMat;
uniform sampler2D uColor, uNormal, uDepth;
uniform vec3 uAmbientColor;
uniform Light uLights[" + maxLights + @"];
uniform int uLightCount;
out vec4 color;

void main() {
	gl_FragDepth = texture(uDepth, vTexCoord).x; // Copy depth from FBO to screen depth buffer
	vec3 csv = texture(uColor, vTexCoord).rgb;
	vec3 normal = normalize(texture(uNormal, vTexCoord).xyz);
	vec4 sspos = uInvProjectionViewMat * (vec4(vTexCoord.xy, gl_FragDepth, 1) * 2 - 1);
	vec3 pos = sspos.xyz / sspos.w;
	vec3 accum = uAmbientColor;
	for(int i = 0; i < uLightCount; ++i) {
		Light light = uLights[i];
		vec3 toLight = light.pos - pos;
		float dist = length(toLight);
		float intensity = min(max(dot(normal, toLight / dist), 0.0), 1);
		accum += light.color * pow(1 - min(dist / light.radius, 1), 3) * intensity;
	}
	color = vec4(csv * accum, 1);
}
			"            );

            Program.Use();
            UniformLocs = Enumerable.Range(0, maxLights).Select(i => new[] {
                Program.GetUniform($"uLights[{i}].pos"),
                Program.GetUniform($"uLights[{i}].color"),
                Program.GetUniform($"uLights[{i}].radius")
            }).SelectMany(x => x).ToArray();
            UniformLC = Program.GetUniform("uLightCount");
        }
Beispiel #2
0
        void RenderDeferredPathway()
        {
            var screenDim = vec2(Width, Height) / 2;

            Matrix4x4.Invert(ProjectionView, out var invProjView);
            Vector2 screenPos(Vector3 wpos)
            {
                var ipos = Vector4.Transform(vec4(wpos, 1), ProjectionView);

                return((ipos.XY() / ipos.W).Add(1) * screenDim);
            }

            NoProfile("- G-buffer render", () => {
                GL.Viewport(0, 0, Width, Height);
                FBO.Bind();
                GL.ClearColor(0, 0, 0, 1);
                GL.ClearStencil(0);
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);

                GL.Enable(EnableCap.CullFace);
                GL.Enable(EnableCap.DepthTest);
                GL.Disable(EnableCap.Blend);

                Models.ForEach(model => model.Draw(ProjectionView, forward: false));
                AniModels.ForEach(model => model.Draw(ProjectionView, forward: false));

                FrameBuffer.Unbind();
                GL.Finish();
            });

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            const int tileSize = 256;
            var       tw       = (int)Math.Ceiling((float)Width / tileSize);
            var       th       = (int)Math.Ceiling((float)Height / tileSize);
            IReadOnlyList <IEnumerable <(double Dist, PointLight Light)> > tiles = null;

            NoProfile("- Tile determination", () => {
                var cforward  = Vector3.Transform(FpsCamera.Forward, Camera.LookRotation).Normalized();
                var cp        = cforward.Y != 0 || cforward.Z != 0 ? vec3(1, 0, 0) : vec3(0, 1, 0);
                var perp      = cforward.Cross(cp).Normalized();
                var tileLists = Enumerable.Range(0, tw * th).Select(i => new List <(double Dist, PointLight Light)>()).ToArray();
                foreach (var light in Lights)
                {
                    var toLight = Camera.Position - light.Position;
                    var tll     = toLight.Length();
                    if (tll > light.Radius)
                    {
                        var lspos   = screenPos(light.Position);
                        var ppos    = Camera.Position + cforward * tll;
                        var pradius = (screenDim - screenPos(ppos + perp * light.Radius)).Length();
                        if (lspos.X + pradius < 0 || lspos.Y + pradius < 0 || lspos.X - pradius > Width || lspos.Y - pradius > Height)
                        {
                            continue;
                        }
                        pradius *= pradius;
                        for (var x = 0; x < tw; ++x)
                        {
                            for (var y = 0; y < th; ++y)
                            {
                                var tilePos = (x * tileSize, y * tileSize);
                                var delta   = (lspos.X - max(tilePos.Item1, min(lspos.X, tilePos.Item1 + tileSize)), lspos.Y - max(tilePos.Item2, min(lspos.Y, tilePos.Item2 + tileSize)));
                                if (delta.Item1 * delta.Item1 + delta.Item2 * delta.Item2 < pradius)
                                {
                                    tileLists[x * th + y].Add((tll, light));
                                }
                            }
                        }
                    }
                    else
                    {
                        tileLists.ForEach(tile => tile.Add((tll, light)));
                    }
                }

                tiles = tileLists.Select(tile => tile.Count <= maxLights ? tile : tile.OrderBy(x => x.Item1).Take(maxLights)).ToList();
            });
Beispiel #3
0
        void SetupDeferredPathway()
        {
            Resize += (_, __) => {
                if (FBO == null)
                {
                    FBO = new FrameBuffer(Width, Height,
                                          FrameBufferAttachment.Rgba,
                                          FrameBufferAttachment.Depth);
                }
                else
                {
                    FBO.Resize(Width, Height);
                }
            };

            GL.BindVertexArray(QuadVAO = GL.GenVertexArray());
            GL.BindBuffer(BufferTarget.ArrayBuffer, GL.GenBuffer());
            GL.BufferData(BufferTarget.ArrayBuffer, 6 * 2 * 4, new[] {
                -1f, -1f,
                1f, -1f,
                1f, 1f,

                -1f, -1f,
                1f, 1f,
                -1f, 1f
            }, BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, GL.GenBuffer());
            GL.BufferData(BufferTarget.ElementArrayBuffer, 6 * 4, new[] { 0, 1, 2, 3, 4, 5 }, BufferUsageHint.StaticDraw);

            GL.EnableVertexAttribArray(0);
            GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 0, 0);

            Program = new Program(@"
#version 410
precision highp float;
in vec2 aPosition;
out vec2 vTexCoord;
void main() {
	gl_Position = vec4(aPosition, 0.0, 1.0);
	vTexCoord = aPosition.xy * 0.5 + 0.5;
}
			"            , @"
#version 410
precision highp float;
in vec2 vTexCoord;

struct Light {
	vec3 pos, color;
	float radius;
};

uniform mat4 uInvProjectionViewMat;
uniform sampler2D uColor, uDepth;
uniform vec3 uAmbientColor;
uniform Light uLights[" + maxLights + @"];
uniform int uLightCount;
out vec3 color;

void main() {
	gl_FragDepth = texture(uDepth, vTexCoord).x; // Copy depth from FBO to screen depth buffer
	vec3 csv = texture(uColor, vTexCoord).rgb;
	vec4 sspos = uInvProjectionViewMat * (vec4(vTexCoord.xy, gl_FragDepth, 1) * 2 - 1);
	vec3 pos = sspos.xyz / sspos.w;
	vec3 accum = uAmbientColor;
	for(int i = 0; i < uLightCount; ++i) {
		Light light = uLights[i];
		float dist = length(light.pos - pos);
		accum += light.color * pow(1 - min(dist / light.radius, 1), 3);
	}
	color = csv * accum;
}
			"            );

            UniformLocs = Enumerable.Range(0, maxLights).Select(i => new[] {
                Program.GetUniform($"uLights[{i}].pos"),
                Program.GetUniform($"uLights[{i}].color"),
                Program.GetUniform($"uLights[{i}].radius")
            }).SelectMany(x => x).ToArray();
            UniformLC = Program.GetUniform("uLightCount");
        }