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

Posted

技术标签:

【中文标题】SLD2:使用 SDL2_gfx 和 AntTweakBar 在 OS X 上出现奇怪的渲染错误【英文标题】:SLD2: strange rendering error on OS X using SDL2_gfx and AntTweakBar 【发布时间】:2015-11-10 16:12:17 【问题描述】:

我正在尝试渲染 3 件事:

使用 gfxPrimitives 的几何形状(在本例中为圆形) 图像/纹理(可选) 带有 AntTewakBar 的 GUI(从 here 为 OS X 上的 SDL2 编译)

这些中的每一个都可以单独工作,但是将它们组合起来会以某种方式破坏 AntTweakBar,具体取决于组合:

    仅 AntTweakBar:一切正常 AntTweakBar + Texture:TestBar 中除了文本之外的所有内容都消失了。鼠标与之前的位置相同,但“宽度”没有突出显示,并且所有“图标”都丢失了。不知何故,“帮助和快捷方式”栏背景幸存下来。再次删除纹理不会改变任何东西。添加圆圈将导致案例3 AntTweakBar + Circle (+Texture):除了文本被渲染并且文本变成方框之外的一切。添加纹理或再次删除圆圈不会改变任何内容,但是先删除圆圈然后添加纹理会导致案例2

这是此测试应用程序的(杂乱)源代码。 res_path.hcleanup.h 可以找到 here 和 here(但应该不重要)。

#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;


有人知道发生了什么以及如何解决或避免这种情况吗?如果没有,也许有人可以推荐一种不同的方法来在 SDL2/C++ 中渲染简单的几何形状和 GUI(配置一些参数),而不需要太多的努力。

【问题讨论】:

看起来像 opengl 状态流血......您的操作不会重置 opengl 状态,因此它会从一个原语流血到另一个原语。通常将 vao 绑定到 0 并将缓冲区绑定到 0 将解决问题。 Shader use() 也会导致这个问题... 由于我是 OpenGL 新手,您能否详细说明在给定示例的上下文中这样做的良好做法? 【参考方案1】:

我通过将我的开发环境从 OSX (10.11.1) 更改为 Linux (Ubuntu 14.04-3) 来解决这个问题。当然,这不是“真正”的解决方案,但也许这些信息仍然可以帮助某人。

【讨论】:

以上是关于SLD2:使用 SDL2_gfx 和 AntTweakBar 在 OS X 上出现奇怪的渲染错误的主要内容,如果未能解决你的问题,请参考以下文章

在 linux 上找不到 SDL2_gfx 库

移植SDL最新版本(转)

使用java加密和解密密码使用啥API和算法

如何使用 php 和 mysql 使用纬度和经度进行几何搜索

Cocoa - 为啥使用 NSInteger 和 CGFloat 而不是使用 int 和 float,或者总是使用 NSNumber?

HTTPS和SSH方式的区别和使用