【问题标题】:SDL2 does not draw image using textureSDL2 不使用纹理绘制图像
【发布时间】:2023-04-07 14:12:01
【问题描述】:

我一直在尝试构建一个简单的 SDL2 程序来显示图像然后退出。我有这个代码:

/* compile with `gcc -lSDL2 -o main main.c` */

#include <SDL2/SDL.h>
#include <SDL2/SDL_video.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_timer.h>

int main(void){
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window * w = SDL_CreateWindow("Hi", 0, 0, 640, 480, 0);
    SDL_Renderer * r = SDL_CreateRenderer(w, -1, 0);

    SDL_Surface * s = SDL_LoadBMP("../test.bmp");
    SDL_Texture * t = SDL_CreateTextureFromSurface(r, s);
    SDL_FreeSurface(s);

    SDL_RenderClear(r);
    SDL_RenderCopy(r, t, 0, 0);
    SDL_RenderPresent(r);

    SDL_Delay(2000);

    SDL_DestroyTexture(t);
    SDL_DestroyRenderer(r);
    SDL_DestroyWindow(w);

    SDL_Quit();
}

我知道我省略了每个函数是否成功的常规检查 - 它们都成功了,为了便于阅读,它们被删除了。我也知道我使用了 0 而不是空指针或正确的枚举值,这也不是问题的原因(因为当我正确构建程序时会出现同样的问题,这是一个快速测试用例,用于测试最简单的情况)

目的是出现一个窗口并显示图像(肯定在该目录中),等待几秒钟然后退出。然而,结果是窗口正确显示,但窗口被黑色填充。

一个额外的注释SDL_ShowSimpleMessageBox() 似乎可以正常工作。不过,我不知道这与框架的其余部分有何关系。

【问题讨论】:

  • 显示您使用的实际代码。为什么用 0 代替 NULL?
  • 此实际代码在编译和运行时演示了所描述的行为。这是在本网站上提问时通常要求的错误的小型自包含示例。实际程序的结构不是允许以这样一种易于理解的方式上传它。 0 在那里而不是 NULL,因为我运行它很快,并且没有费心返回导入 stdlib 以获取一个不重要的宏。

标签: c++ c image sdl sdl-2


【解决方案1】:

当使用SDL_RENDERER_SOFTWARE 作为渲染器标志时,这有效。它也在另一台机器上工作。猜猜我的配置一定有问题,尽管我不确定是什么,因为我仍然没有显示任何错误。嗯,标记为已解决。

【讨论】:

  • 我在 Ubuntu 虚拟机中使用 SDL 2.0.3(在所述虚拟机上从源代码构建 SDL)并且仅在 SDL_CreateRenderer 上使用此标志对我有用。
【解决方案2】:

由于这行代码,我相信这是(不是 100% 肯定,但相当肯定):

SDL_Renderer * r = SDL_CreateRenderer(w, -1, 0);

根据 SDL wiki 文章 SDL_CreateRenderer,您传入的参数所需的参数如下:

  • SDL_Window* 窗口
  • int 索引
  • Uint32 标志

您正确地传递了指向窗口的指针以及正确的索引,但是缺少标志向 SDL 表明 SDL 应该使用 默认渲染器。 大多数系统对于应该使用渲染器的应用程序都有一个默认设置,并且可以在应用程序的基础上对其进行修改。如果没有为特定应用程序提供默认设置,则渲染查找会立即检查默认渲染设置列表。 SDL wiki 通过备注部分底部的以下行简要引用此列表:

“请注意,不提供标志会优先考虑可用的 SDL_RENDERER_ACCELERATED 渲染器。”

这里没有在 wiki 中解释的是 wiki 所指的“渲染器”来自默认渲染器列表。

这让我相信您要么更改了计算机历史进程中某处的设置,要么更改了 Visual Studio 设置中的其他位置,导致找不到列表。因此,您必须根据您的机器设置明确告知 SDL 要使用哪个渲染器。否则使用 0 的参数应该可以正常工作。最后,这并没有什么坏处,因为最好在代码中显式而不是尽可能隐式。

(也就是说,我所有的推论都是基于这样一个事实,即我假设你所说的一切有效,有效。如果这不是真的,那么问题可能是因为由于缺乏错误检查,原因多种多样。)

【讨论】:

    【解决方案3】:

    我会澄清这一点,您想要制作纹理,直接进行以简化控制,另外这可以让您更好地控制图像,尝试使用此代码,经过全面测试,并且可以正常工作,您想要的只是显示图像并在 2 秒内关闭的窗口对吗?如果图片没有加载,那么它就是您的图片的位置。

    /* compile with `gcc -lSDL2 -o main main.c` */
    
    #include <SDL.h>
    #include <SDL_image.h>  
    #include <iostream> //I included it since I used cout
    
    
    int main(int argc, char* argv[]){
    bool off = false;
    int time;
    
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window * w = SDL_CreateWindow("Hi", 0, 0, 640, 480, SDL_WINDOW_SHOWN);
    SDL_Renderer * r = SDL_CreateRenderer(w, -1, SDL_RENDERER_ACCELERATED);
    
    SDL_Texture * s = NULL;
    s = IMG_LoadTexture(r, "../test.bmp"); // LOADS A TEXTURE DIRECTLY FROM THE IMAGE
    if (s == NULL)
    {
    cout << "FAILED TO FIND THE IMAGE" << endl; //we did this to check if IMG_LoadTexture found the image, if it showed this message in the cmd window (the black system-like one) then it means that the image can't be found
    }
    SDL_Rect s_rect; // CREATES THE IMAGE'S SPECS
    s_rect.x = 100;    // just like the window, the x and y values determine it's displacement from the origin which is the top left of your window
    s_rect.y = 100;
    s_rect.w = 640; //width of the texture
    s_rect.h = 480; // height of the texture
    
    time = SDL_GetTicks(); //Gets the current time
    
    while (time + 2000 < SDL_GetTicks()) //adds 2 seconds to the past time you got and waits for the present time to surpass that
    {
    SDL_RenderClear(r);
    SDL_RenderCopy(r, s, NULL, &s_rect); // THE NULL IS THE AREA YOU COULD USE TO CROP THE IMAGE
    SDL_RenderPresent(r);
    
    }
    
    SDL_DestroyTexture(s);
    SDL_DestroyRenderer(r);
    SDL_DestroyWindow(w);
    
    return 0;   //returns 0, closes the program.
    }
    

    如果你想在窗口上看到一个关闭按钮并希望它生效然后创建一个事件然后将它添加到 while 区域以检查它是否等于 SDL_Quit();,我没有包括它,因为你希望它在 2 秒内立即关闭,从而使关闭按钮无用。

    快乐编码:D

    【讨论】:

    • 在 99.9% 的此类问题中,图像位置不正确。常见的错误是程序员假设应用程序正在寻找一个位置,因此将图像放在那里,但实际上它是错误的位置。
    • 请注意,提问者使用的是SDL2
    猜你喜欢
    • 1970-01-01
    • 2018-02-19
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    • 2015-02-15
    相关资源
    最近更新 更多