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.h
和 cleanup.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 上出现奇怪的渲染错误的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 php 和 mysql 使用纬度和经度进行几何搜索
Cocoa - 为啥使用 NSInteger 和 CGFloat 而不是使用 int 和 float,或者总是使用 NSNumber?