简体   繁体   English

SLD2:使用SDL2_gfx和AntTweakBar在OS X上出现奇怪的渲染错误

[英]SLD2: strange rendering error on OS X using SDL2_gfx and AntTweakBar

I am trying to render 3 things: 我正在尝试渲染3件事:

  • geometric shapes (in this example a circle) using gfxPrimitives 使用gfxPrimitives的几何形状(在此示例中为圆形)
  • images/textures (optional) 图像/纹理(可选)
  • a GUI with AntTewakBar (compiled for SDL2 on OS X from here ) 与AntTewakBar一个GUI(从编译SDL2在OS X 在这里

Each of those works fine by its own, but combining them somehow breaks the AntTweakBar, depending on the combination: 每种方法都可以正常工作,但是将它们组合起来可能会破坏AntTweakBar,具体取决于组合:

  1. Only AntTweakBar : renders everything fine 只有AntTweakBar :呈现一切正常 正常工作,没有圆圈和纹理
  2. AntTweakBar + Texture : everything but the text disappeared in the TestBar. AntTweakBar + Texture :除文本外,所有内容均在TestBar中消失。 The mouse is in the same position as before, but 'width' is not highlighted and all "icons" are missing. 鼠标与以前的位置相同,但是“宽度”未突出显示,并且所有“图标”都丢失了。 Somehow, the 'Help & Shortcuts'-bars background survived. 不知何故,“帮助和快捷方式”栏背景仍然存在。 Removing the texture again won't change anything. 再次删除纹理不会改变任何内容。 Adding the circle will lead to case 3 添加圆圈将导致情况3 但是他妈的
  3. AntTweakBar + Circle (+Texture) :everything but the text gets rendered and the text turned into boxes. AntTweakBar +圆(+ Texture) :所有内容都可以渲染,但是文本变成了方框。 Adding the texture or removing the circle again won't change anything, but removing the circle first and then adding the texture will lead to case 2 . 添加纹理或再次删除圆并不会改变任何东西,但是先删除圆再添加纹理将导致情况2 然后

Here is the (messy) source code for this test application. 这是此测试应用程序的(混乱)源代码。 res_path.h and cleanup.h can be found here and here (but should not matter). 可以在此处此处找到res_path.hcleanup.h (但不要紧)。

#include <iostream>
#include <SDL2/SDL.h>
#include "res_path.h"
#include "cleanup.h"
#include "SDL2/SDL2_gfxPrimitives.h"
#include <AntTweakBar.h>

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

bool quit = false;
bool tex = false;
bool circ = false;

//-----------------------------------------------------------------------

/**
 * Log an SDL error with some error message to the output stream of our choice
 * @param os The output stream to write the message to
 * @param msg The error message to write, format will be msg error: SDL_GetError()
 */
void logSDLError(std::ostream &os, const std::string &msg)
{
    os << msg << " error: " << SDL_GetError() << std::endl;
}

/**
 * Loads a BMP image into a texture on the rendering device
 * @param file The BMP image file to load
 * @param ren The renderer to load the texture onto
 * @return the loaded texture, or nullptr if something went wrong.
 */
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
{
    //Initialize to nullptr to avoid dangling pointer issues
    SDL_Texture *texture = nullptr;
    //Load the image
    SDL_Surface *loadedImage = SDL_LoadBMP(file.c_str());
    //If the loading went ok, convert to texture and return the texture
    if (loadedImage != nullptr){
        texture = SDL_CreateTextureFromSurface(ren, loadedImage);
        SDL_FreeSurface(loadedImage);
        //Make sure converting went ok too
        if (texture == nullptr){
            logSDLError(std::cout, "CreateTextureFromSurface");
        }
    }
    else {
        logSDLError(std::cout, "LoadBMP");
    }
    return texture;
}


/**
 * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
 * the texture's width and height
 * @param tex The source texture we want to draw
 * @param ren The renderer we want to draw to
 * @param x The x coordinate to draw to
 * @param y The y coordinate to draw to
 */
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y)
{
    //Setup the destination rectangle to be at the position we want
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    //Query the texture to get its width and height to use
    SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
    SDL_RenderCopy(ren, tex, NULL, &dst);
}

void TW_CALL RunCA(void * /*clientData*/)
{
    std::cout << "button 1 clicked" << std::endl;
    tex = !tex;
}
void TW_CALL RunCB(void * /*clientData*/)
{
    std::cout << "button 2 clicked" << std::endl;
    circ = !circ;
}

//---------------------------------------

int main()
{

    int size=10;
    int alpha=100;

    std::cout << "Resource path is: " << getResourcePath() << std::endl;

    if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
        logSDLError(std::cout, "SDL_Init");
        return 1;
    }

    SDL_Window *window = SDL_CreateWindow("Lesson 2", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (window == nullptr){
        logSDLError(std::cout, "CreateWindow");
        SDL_Quit();
        return 1;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (renderer == nullptr){
        logSDLError(std::cout, "CreateRenderer");
        cleanup(window);
        SDL_Quit();
        return 1;
    }


    const std::string resPath = getResourcePath();
    SDL_Texture *image = loadTexture(resPath + "image.bmp", renderer);
    if (image == nullptr){
        cleanup(image, renderer, window);
        SDL_Quit();
        return 1;
    }


    TwInit(TW_OPENGL, NULL);
    TwWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);

    TwBar *myBar;
    myBar = TwNewBar("TestBar");
    TwDefine(" GLOBAL help='example help' "); // Message added to the help bar.

    TwAddButton(myBar, "Switch Texture", RunCA, NULL, " label='texture' ");
    TwAddButton(myBar, "Switch Circle", RunCB, NULL, " label='circle' ");

    TwAddVarRW(myBar, "width", TW_TYPE_INT32, &size, " keyIncr=w, keyDecr=s ");
    TwAddVarRW(myBar, "alpha", TW_TYPE_INT32, &alpha, " ");
    // Add 'quit' to 'bar': this is a modifiable (RW) variable of type TW_TYPE_BOOL32
    // (a boolean stored in a 32 bits integer). Its shortcut is [ESC].
    TwAddVarRW(myBar, "Quit", TW_TYPE_BOOL32, &quit,
        " label='Quit?' true='+' false='-' key='ESC' help='Quit program.' ");

    // main loop
    while( !quit )
    {
        SDL_Event event;
        int handled=1;

        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderClear(renderer);

        if(tex)
        renderTexture(image, renderer, 50, 50);

        if(circ)
        filledCircleRGBA(renderer,
                100, 100,
                size,
                0, 255, 0, alpha);


        TwDraw();  // draw the tweak bar(s)


        SDL_RenderPresent(renderer);

        while(SDL_PollEvent(&event))
        {
            handled = TwEventSDL(&event, SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
            if( !handled )
            {
                //If user closes the window
                if (event.type == SDL_QUIT){
                    std::cout << "window closed" << std::endl;
                    quit = true;
                }
                //If user presses any key
                if (event.type == SDL_KEYDOWN){
                    std::cout << "key down" << std::endl;
                }
                //If user clicks the mouse
                if (event.type == SDL_MOUSEBUTTONDOWN){
                    std::cout << "mouse clicked" << std::endl;
                }
            }    
        }

    //      SDL_Delay(10);


    } // end of main loop


//cleanup
cleanup(image, renderer, window);
// Terminate AntTweakBar
TwTerminate();
SDL_Quit();
return 0;
}

Does anybody know what is going on and how this could be fixed or avoided? 有人知道发生了什么,如何解决或避免这种情况? If not, maybe somebody could recommend a different approach for rendering simple geometric shapes and a GUI (to configure some parameters) in SDL2/C++ without too much effort. 如果不是这样,也许有人会建议使用另一种方法来渲染简单的几何形状,并在SDL2 / C ++中无需过多的工作就可以创建GUI(以配置一些参数)。

I got around it by changing my development environment from OSX (10.11.1) to Linux (Ubuntu 14.04-3). 通过将开发环境从OSX(10.11.1)更改为Linux(Ubuntu 14.04-3),可以解决此问题。 Of course this is no "REAL" solution, but maybe this information can still help somebody. 当然,这不是“真正的”解决方案,但是也许这些信息仍然可以对某些人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM