OpenGL比例单像素线 [英] OpenGL Scale Single Pixel Line

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

问题描述

我想制作一个内部尺寸为320x240的游戏,但要以此数字的整数倍(640x480、960,720等)渲染到屏幕上.我要使用复古的2D像素图形.

I would like to make a game that is internally 320x240, but renders to the screen at whole number multiples of this (640x480, 960,720, etc). I am going for retro 2D pixel graphics.

我已经通过glOrtho()设置内部分辨率来实现了这一点:

I have achieved this by setting the internal resolution via glOrtho():

glOrtho(0, 320, 240, 0, 0, 1);

然后我将输出分辨率放大3倍,像这样:

And then I scale up the output resolution by a factor of 3, like this:

glViewport(0,0,960,720);
window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 720, SDL_WINDOW_OPENGL);

我这样绘制矩形:

glBegin(GL_LINE_LOOP);
glVertex2f(rect_x, rect_y);
glVertex2f(rect_x + rect_w, rect_y);
glVertex2f(rect_x + dst_w, dst_y + dst_h);
glVertex2f(rect_x, rect_y + rect_h);
glEnd();

它可以在320x240(不缩放)下完美运行:

It works perfectly at 320x240 (not scaled):

当我放大到960x720时,像素渲染一切正常!但是,似乎GL_Line_Loop不是在320x240画布上绘制并按比例放大,而是在最终的960x720画布上绘制.结果是在3px的世界中有1px的线:(

When I scale up to 960x720, the pixel rendering all works just fine! However it seems the GL_Line_Loop is not drawn on a 320x240 canvas and scaled up, but drawn on the final 960x720 canvas. The result is 1px lines in a 3px world :(

如何在320x240 glOrtho画布上绘制线条,而不是在960x720输出画布上绘制线条?

How do I draw lines to the 320x240 glOrtho canvas, instead of the 960x720 output canvas?

推荐答案

正如我在评论中提到的那样, Intel OpenGL 驱动程序在直接渲染到纹理方面存在问题,我不知道有任何解决方法.在职的.在这种情况下,解决此问题的唯一方法是使用glReadPixels将屏幕内容复制到 CPU 内存中,然后将其作为纹理复制回 GPU .粗糙的则比直接渲染到纹理要慢得多.所以这是交易:

As I mentioned in my comment Intel OpenGL drivers has problems with direct rendering to texture and I do not know of any workaround that is working. In such case the only way around this is use glReadPixels to copy screen content into CPU memory and then copy it back to GPU as texture. Of coarse that is much much slower then direct rendering to texture. So here is the deal:

  1. 设置低分辨率视图

请勿仅更改glViewport值来更改窗口的分辨率.然后以低分辨率(仅在屏幕空间的一小部分)渲染场景

do not change resolution of your window just the glViewport values. Then render your scene in the low res (in just a fraction of screen space)

将渲染的屏幕复制到纹理中

渲染纹理

不要忘记使用GL_NEAREST过滤器.最重要的是,您仅在此之后才交换缓冲区!否则你会忽悠.

do not forget to use GL_NEAREST filter. The most important thing is that you swap buffers only after this not before !!! otherwise you would have flickering.

此处是C ++源代码:

void gl_draw()
    {
    // render resolution and multiplier
    const int xs=320,ys=200,m=2;

    // [low res render pass]
    glViewport(0,0,xs,ys);
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    // 50 random lines
    RandSeed=0x12345678;
    glColor3f(1.0,1.0,1.0);
    glBegin(GL_LINES);
    for (int i=0;i<100;i++)
     glVertex2f(2.0*Random()-1.0,2.0*Random()-1.0);
    glEnd();

    // [multiply resiolution render pass]
    static bool _init=true;
    GLuint  txrid=0;        // texture id
    BYTE map[xs*ys*3];      // RGB
    // init texture
    if (_init)              // you should also delte the texture on exit of app ...
        {
        // create texture
        _init=false;
        glGenTextures(1,&txrid);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,txrid);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);   // must be nearest !!!
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COPY);
        glDisable(GL_TEXTURE_2D);
        }
    // copy low res screen to CPU memory
    glReadPixels(0,0,xs,ys,GL_RGB,GL_UNSIGNED_BYTE,map);
    // and then to GPU texture
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,txrid);         
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xs, ys, 0, GL_RGB, GL_UNSIGNED_BYTE, map);
    // set multiplied resolution view
    glViewport(0,0,m*xs,m*ys);
    glClear(GL_COLOR_BUFFER_BIT);
    // render low res screen as texture
    glBegin(GL_QUADS);
    glTexCoord2f(0.0,0.0); glVertex2f(-1.0,-1.0);
    glTexCoord2f(0.0,1.0); glVertex2f(-1.0,+1.0);
    glTexCoord2f(1.0,1.0); glVertex2f(+1.0,+1.0);
    glTexCoord2f(1.0,0.0); glVertex2f(+1.0,-1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);

    glFlush();
    SwapBuffers(hdc);   // swap buffers only here !!!
    }

并预览:

我在一些可用的 Intel HD 图形(上帝知道哪个版本)上对此进行了测试,并且可以工作(而没有标准的渲染纹理方法).

I tested this on some Intel HD graphics (god knows which version) I got at my disposal and it works (while standard render to texture approaches are not).

这篇关于OpenGL比例单像素线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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