【问题标题】:OpenGL rendering full screen image [duplicate]OpenGL渲染全屏图像[重复]
【发布时间】:2016-09-02 00:25:12
【问题描述】:

我正在尝试创建一个应用程序,它所做的只是全屏显示图像,然后快速(144hz)快速闪过一系列图像。我刚刚开始研究 OpenGL,已经完成了一些教程,但无法弄清楚我在这里做错了什么。我被卡住的部分实际上是将图像渲染到显示器上,因为它只显示为一个白色方块。我已经为此解决了其他堆栈溢出问题,但没有一个建议对我有用。

我在 Visual Studio 2015 中执行此操作,使用的是 win32 应用程序并安装了 NupenGL 包。出于测试目的,我使用的是 256x256 位图图像,并通过我构建并静态链接的 SOIL 库加载它。

我最初认为我没有正确构建/链接 SOIL 库,因此尝试加载图像时发生了一些奇怪的事情。我创建了一个不起作用的自定义 BMP 加载器,我还尝试了其他人的 BMP 加载器堆栈溢出但无济于事。我现在相信这不是纹理的加载,而是我在实际尝试渲染它时搞砸了一些东西。同样在我下面的代码中,如果纹理无效但它总是返回良好,我会输出。

输出(全屏):

输出(窗口):

我的代码:

#include <gl/freeglut.h>
#include <stdio.h>
#include <iostream>
#include "SOIL.h"

void init();
void display(void);
void keyPressed(unsigned char key, int x, int y);
void resize(int heightY, int widthX);


//  define the window position on screen
int window_x;
int window_y;

//  variables representing the window size
int window_width = 480;
int window_height = 480;

//  variable representing the window title
char *window_title = "Resolution Enhancement via Display Vibrations";

bool fullscreen = false;

//-------------------------------------------------------------------------
//  Program Main method.
//-------------------------------------------------------------------------
void main(int argc, char **argv)
{
    //  Connect to the windowing system + create a window
    //  with the specified dimensions and position
    //  + set the display mode + specify the window title.
    glutInit(&argc, argv);
    glutInitWindowSize(window_width, window_height);
    glutInitWindowPosition(window_x, window_y);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutCreateWindow(window_title);

    glutFullScreen();

    // Setup keyPressed
    glutKeyboardFunc(keyPressed);

    // Handler for when the screen resizes
    glutReshapeFunc(resize);

    //  Set OpenGL program initial state.
    init();

    // Set the callback functions
    glutDisplayFunc(display);

    //  Start GLUT event processing loop
    glutMainLoop();
}

//-------------------------------------------------------------------------
//  Set OpenGL program initial state.
//-------------------------------------------------------------------------
void init()
{
    //  Set the frame buffer clear color to black. 
    glClearColor(0.0, 0.0, 0.0, 0.0);
}

//-------------------------------------------------------------------------
//  This function is passed to glutDisplayFunc in order to display 
//  OpenGL contents on the window.
//-------------------------------------------------------------------------
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    GLuint texture = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
    (
        "C:/Users/joeja/Desktop/Grass.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
    );

    if (texture == 0) {
        std::cout << "Texture not found!\n" << std::endl;
    }
    else
    {
        std::cout << "Texture is good\n" << std::endl;
    }

    glBindTexture(GL_TEXTURE_2D, texture);

    glBegin(GL_QUADS);  // front face
    glTexCoord2f(0.0f, 0.0f); glVertex3f(0.5f, -0.5f, 0.5f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.5f, 0.5f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5f, 0.5f, 0.5f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -0.5f, 0.5f);
    glEnd();

    glutSwapBuffers();
}

void resize(int heightY,int widthX) {
    const float ar = (float)widthX / (float)heightY;
    glViewport(0, 20, widthX, heightY);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void keyPressed(unsigned char key, int x, int y) {
    switch (key) {
    case 27:
    case 70:
    case 102: /* Fullscreen mode (Additional) : f/F */
        fullscreen = !fullscreen;
        if (fullscreen)
        {
            glutFullScreen();                /* Go to full screen */
        }
        else
        {
            glutReshapeWindow(800, 600);        /* Restore us */
            glutPositionWindow(0, 0);
        }
        break;
    }
}

【问题讨论】:

  • -ar + 1, ar - 1 在我看来是错误的。当 widthX 和 heightY 相等时,ar == 1 并且这两个值都是 0。不应该只是 -ar, ar 吗?以及为什么你使用 20 作为 glViewport 的 y 值(这在纵横比中也不被尊重?
  • 哇!您从文件每帧加载图像。
  • 使用SOIL_FLAG_MIPMAPS 或将GL_TEXTURE_MIN_FILTER 设置为非MIPMAP 变体。
  • @doug65536:你会惊讶于这些天你能获得的那种性能。我有一个程序可以跨两个独立的主机进行延迟着色,其中一个未优化的数据路径涉及将 G-Buffer 转储到磁盘并将其作为网络共享获取。如果这可以在高分辨率下维持 60+ FPS,这将是一个越来越频繁的错误。从技术上讲,这甚至不会停止渲染管道,旧的(重复的)数据不会中断,因此大多数驱动程序会在每一帧上制作单独的副本,这主要取决于磁盘吞吐量/可能的图像解码。
  • @AndonM.Coleman 当您编写汇编程序将每个像素插入内存时,我正在做图形编程,并且您珍惜每个周期。每帧磁盘 I/O 的恐怖对我来说有点过分了!

标签: opengl visual-studio-2015 soil


【解决方案1】:

不要每帧都从文件中加载图像。

在您的init 中,您应该:

  • 像你现在一样用 SOIL 加载图像,将 ID 存储为texture

你应该在display

  • glBindTexture(GL_TEXTURE_2D, texture);
  • glEnable(GL_TEXTURE_2D)
  • 画东西
  • glDisable(GL_TEXTURE_2D);
  • glBindTexture(GL_TEXTURE_2D, 0);

您可能会注意到,您可以通过启用纹理 2D 并将其保持打开来跳过一些启用/禁用。我给出的伪代码试图始终工作,跳过冗余状态更改是与问题无关的优化。

【讨论】:

  • SOIL_load_OGL_texture 已经调用了glGenTexturesglTexImage2D
  • @BDL 好的,但是他的代码是向后的,它加载它然后绑定一些其他纹理。并且每个display 从文件中加载是完全荒谬的。
  • @BDL 啊我现在明白你的意思了。 SOIL 上传并返回生成的 ID。正在更新答案...
猜你喜欢
  • 1970-01-01
  • 2023-03-30
  • 2018-06-11
  • 2011-04-20
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 2012-05-14
相关资源
最近更新 更多