如何摆脱奇怪的 OpenTK 渲染?
How to get rid of weird OpenTK render?
我完全知道我可以在 OpenTK 中加载纹理。但是,当我尝试仅使用点来渲染图片时,当 ClientSize.Width
完全等于所渲染图片的宽度时,它会显示出非常奇怪的线条。像这样:
如果我调整(放大)window 行的 ClientSize.Width
变得有点正常,并且它们出现是有实际原因的(它们覆盖了无法渲染的区域):
这似乎与我打开的图片无关。谁能解释一下为什么第一张图有线条?
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace Miracle
{
class Program
{
public static void Main()
{
using (Window w = new Window())
w.Run(30);
}
}
class Window : GameWindow
{
private Color[,] pixels;
private int width, height;
private bool blink = true;
private int blinkcounter;
public Window() : base(1337, 666, GraphicsMode.Default, "Miracle", GameWindowFlags.Default) { }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Bitmap pic = new Bitmap("sample.png");
width = pic.Width;
height = pic.Height;
ClientSize = new Size(width, height);
pixels = new Color[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
pixels[x, y] = pic.GetPixel(x, y);
GL.ClearColor(Color.FromArgb(0, 255, 0));
GL.Ortho(0, width, height, 0, -1, 1);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Title = ClientSize.Width + "x" + ClientSize.Height + (ClientSize.Width == width && ClientSize.Height == height ? " (original)" : "");
GL.Viewport(ClientSize);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (blinkcounter == 6)
{
GL.ClearColor(blink ? Color.FromArgb(255, 0, 0) : Color.FromArgb(0, 255, 0));
blink = !blink;
blinkcounter = 0;
}
blinkcounter++;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.Begin(PrimitiveType.Points);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
GL.Color4(pixels[x, y]);
GL.Vertex2(x, y);
}
GL.End();
SwapBuffers();
}
}
}
我将描述您的问题的解决方案以及我认为您遇到问题的原因。
首先,我认为您遇到问题的原因:
点的光栅化很奇怪并且依赖于硬件。这个问题看起来是点的光栅化阶段浮点精度的错误。投影点在2个像素之间选择的边界上,由于FP限制选择错误。
解决方法:
不推荐使用点栅格化图像。这不是点栅格化的用途。相反,光栅化一个全屏四边形,给四边形的每个顶点一个纹理坐标,然后在片段着色器中使用插值纹理坐标从存储要渲染的图像的纹理中获取。这避免了您在使用 GL_POINTS 时遇到的问题,因为它确保每个像素都被绘制一次。
我完全知道我可以在 OpenTK 中加载纹理。但是,当我尝试仅使用点来渲染图片时,当 ClientSize.Width
完全等于所渲染图片的宽度时,它会显示出非常奇怪的线条。像这样:
如果我调整(放大)window 行的 ClientSize.Width
变得有点正常,并且它们出现是有实际原因的(它们覆盖了无法渲染的区域):
这似乎与我打开的图片无关。谁能解释一下为什么第一张图有线条?
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace Miracle
{
class Program
{
public static void Main()
{
using (Window w = new Window())
w.Run(30);
}
}
class Window : GameWindow
{
private Color[,] pixels;
private int width, height;
private bool blink = true;
private int blinkcounter;
public Window() : base(1337, 666, GraphicsMode.Default, "Miracle", GameWindowFlags.Default) { }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Bitmap pic = new Bitmap("sample.png");
width = pic.Width;
height = pic.Height;
ClientSize = new Size(width, height);
pixels = new Color[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
pixels[x, y] = pic.GetPixel(x, y);
GL.ClearColor(Color.FromArgb(0, 255, 0));
GL.Ortho(0, width, height, 0, -1, 1);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Title = ClientSize.Width + "x" + ClientSize.Height + (ClientSize.Width == width && ClientSize.Height == height ? " (original)" : "");
GL.Viewport(ClientSize);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (blinkcounter == 6)
{
GL.ClearColor(blink ? Color.FromArgb(255, 0, 0) : Color.FromArgb(0, 255, 0));
blink = !blink;
blinkcounter = 0;
}
blinkcounter++;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.Begin(PrimitiveType.Points);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
GL.Color4(pixels[x, y]);
GL.Vertex2(x, y);
}
GL.End();
SwapBuffers();
}
}
}
我将描述您的问题的解决方案以及我认为您遇到问题的原因。
首先,我认为您遇到问题的原因: 点的光栅化很奇怪并且依赖于硬件。这个问题看起来是点的光栅化阶段浮点精度的错误。投影点在2个像素之间选择的边界上,由于FP限制选择错误。
解决方法: 不推荐使用点栅格化图像。这不是点栅格化的用途。相反,光栅化一个全屏四边形,给四边形的每个顶点一个纹理坐标,然后在片段着色器中使用插值纹理坐标从存储要渲染的图像的纹理中获取。这避免了您在使用 GL_POINTS 时遇到的问题,因为它确保每个像素都被绘制一次。