OpenGL像素完美的2D绘图 [英] Opengl pixel perfect 2D drawing

查看:253
本文介绍了OpenGL像素完美的2D绘图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用2D引擎.它已经可以很好地工作了,但是我仍然遇到像素错误.

I'm working on a 2d engine. It already works quite good, but I keep getting pixel-errors.

例如,我的窗口是960x540像素,我画了一条从(0,0)到(959,0)的线.我希望扫描线0上的每个像素都将设置为一种颜色,但不会:不会绘制最右边的像素.当我垂直绘制到像素539时,同样的问题.我确实需要绘制到(960,0)或(0,540)才能绘制它.

For example, my window is 960x540 pixels, I draw a line from (0, 0) to (959, 0). I would expect that every pixel on scan-line 0 will be set to a color, but no: the right-most pixel is not drawn. Same problem when I draw vertically to pixel 539. I really need to draw to (960, 0) or (0, 540) to have it drawn.

当我出生于像素时代时,我坚信这不是正确的结果.当屏幕为320x200像素大时,我可以从0绘制到319,从0绘制到199,这样我的屏幕就满了.现在,我得到一个没有绘制右/下像素的屏幕.

As I was born in the pixel-era, I am convinced that this is not the correct result. When my screen was 320x200 pixels big, I could draw from 0 to 319 and from 0 to 199, and my screen would be full. Now I end up with a screen with a right/bottom pixel not drawn.

这可能是由于不同的原因: 我希望opengl线图元是从一个像素绘制到一个像素(包括一个像素)的,最后一个像素实际上是唯一的?是吗 我的投影矩阵不正确? 我有一个错误的假设:当我有960x540的后缓冲时,实际上还有一个像素吗? 还有吗?

This can be due to different things: where I expect the opengl line primitive is drawn from a pixel to a pixel inclusive, that last pixel just is actually exclusive? Is that it? my projection matrix is incorrect? I am under a false assumption that when I have a backbuffer of 960x540, that is actually has one pixel more? Something else?

有人可以帮我吗?我一直在研究这个问题很长时间了,每当我认为还可以的时候,一段时间后我就发现实际上不是.

Can someone please help me? I have been looking into this problem for a long time now, and every time when I thought it was ok, I saw after a while that it actually wasn't.

这是我的一些代码,我尝试将其尽可能地简化.当我调用线函数时,每个坐标都添加了0.375、0.375,以使其在ATI和nvidia适配器上均正确.

Here is some of my code, I tried to strip it down as much as possible. When I call my line-function, every coordinate is added with 0.375, 0.375 to make it correct on both ATI and nvidia adapters.

int width = resX();
int height = resY();

for (int i = 0; i < height; i += 2)
    rm->line(0, i, width - 1, i, vec4f(1, 0, 0, 1));
for (int i = 1; i < height; i += 2)
    rm->line(0, i, width - 1, i, vec4f(0, 1, 0, 1));

// when I do this, one pixel to the right remains undrawn

void rendermachine::line(int x1, int y1, int x2, int y2, const vec4f &color)
{
    ... some code to decide what std::vector the coordinates should be pushed into
    // m_z is a z-coordinate, I use z-buffering to preserve correct drawing orders
    // vec2f(0, 0) is a texture-coordinate, the line is drawn without texturing
    target->push_back(vertex(vec3f((float)x1 + 0.375f, (float)y1 + 0.375f, m_z), color, vec2f(0, 0)));
    target->push_back(vertex(vec3f((float)x2 + 0.375f, (float)y2 + 0.375f, m_z), color, vec2f(0, 0)));
}

void rendermachine::update(...)
{
    ... render target object is queried for width and height, in my test it is just the back buffer so the window client resolution is returned
    mat4f mP;
    mP.setOrthographic(0, (float)width, (float)height, 0, 0, 8000000);

    ... all vertices are copied to video memory

    ... drawing
    if (there are lines to draw)
        glDrawArrays(GL_LINES, (int)offset, (int)lines.size());

    ...
}

// And the (very simple) shader to draw these lines

// Vertex shader
    #version 120
    attribute vec3 aVertexPosition;
    attribute vec4 aVertexColor;
    uniform mat4 mP;
    varying vec4 vColor;
    void main(void) {
        gl_Position = mP * vec4(aVertexPosition, 1.0);
        vColor = aVertexColor;
    }

// Fragment shader
    #version 120
    #ifdef GL_ES
    precision highp float;
    #endif
    varying vec4 vColor;
    void main(void) {
        gl_FragColor = vColor.rgb;
    }

推荐答案

在OpenGL中,使用"Diamond Exit"规则对线进行栅格化.这几乎等于说结束坐标是排他的,但不是完全一样.

In OpenGL, lines are rasterized using the "Diamond Exit" rule. This is almost the same as saying that the end coordinate is exclusive, but not quite...

这是OpenGL规范必须说的: http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html

This is what the OpenGL spec has to say: http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html

还可以查看OpenGL常见问题解答, http://www.opengl.org/archives/resources/faq/technical/rasterization.htm ,项目"14.090如何获得线条的精确像素化?".它说:"OpenGL规范支持广泛的线渲染硬件,因此可能根本无法实现精确的像素化."

Also have a look at the OpenGL FAQ, http://www.opengl.org/archives/resources/faq/technical/rasterization.htm, item "14.090 How do I obtain exact pixelization of lines?". It says "The OpenGL specification allows for a wide range of line rendering hardware, so exact pixelization may not be possible at all."

许多人会争辩说,您根本不应该在OpenGL中使用行.它们的行为基于古老的SGI硬件的工作方式,而不是基于有意义的行为. (而且宽度> 1的线几乎不可能以看起来不错的方式使用!)

Many will argue that you should not use lines in OpenGL at all. Their behaviour is based on how ancient SGI hardware worked, not on what makes sense. (And lines with widths >1 are nearly impossible to use in a way that looks good!)

这篇关于OpenGL像素完美的2D绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆