How do I make an OpenGL SuperBible 6 application portable? - c++

I'm developing an OpenGL application using the sb6::application framework provided by SuperBible v6, and although it always works fine on my computer (even when I run the executable outside of my DE), no one else who I send it to can get it to run. It can't be an issue with OpenGL versions, since my friend has v4.2. (I have v4.3, but it's an extremely rudimentary program so I highly doubt I've done anything exclusive to v4.3) It might have to do with a missing file since the window just closes instantly when he starts it, but I can't figure out what file. It might be a .dll or something (I've assumed that I can just put any needed .dlls in the same folder as the executable) but I haven't been able to find out which one. I got my friend to run DependencyWalker and I specifically tracked down and sent him the ones that DependencyWalker said he was missing, and there was still no improvement.
SuperBible has absolutely no documentation on the sb6::application class and doesn't give any information about how to set up a project to be portable. Or if it does I haven't been able to find it even after days of searching.
Not sure which parts of the code are relevant to post, but here are the init() and startup() functions from the sb6::application class.
void init()
{
// Redirect output to this file.
//freopen("myoutput.txt", "w", stdout);
ready = false;
static const char title[] = "Forkits";
sb6::application::init();
memcpy(info.title, title, sizeof(title));
}
void save_viewport_size()
{
// Get the size of the window
glGetIntegerv(GL_VIEWPORT, m_viewport);
std::cout << m_viewport[0] << " " << m_viewport[1] << " " << m_viewport[2] << " " << m_viewport[3] << std::endl;
}
void startup(void)
{
// Check version
GLint version = 0;
//glGetFloatv(GL_VERSION, &version);
//glGetIntegerv(GL_VERSION, &version);
//std::cout << "Version number " << glGetString(GL_VERSION) << std::endl;
//printf("%s %s\n", glGetString(GL_RENDERER), glGetString(GL_VERSION));
// Save the size of the initial viewport
glGetIntegerv(GL_VIEWPORT, m_viewport);
std::cout << m_viewport[0] << " " << m_viewport[1] << " " << m_viewport[2] << " " << m_viewport[3] << std::endl;
program = glCreateProgram();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
print_shader_log(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
print_shader_log(fs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
print_linker_log(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Set parameters
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// Set up alpha blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ready = true;
flag_running = true;
int init_success = Forkits::init(&sprites);
logic = new std::thread(old_main);
}

You're right, you should just be able to put the .dlls in the same directory as the executable and it'll work. It's possible that sb6 is reliant on other .dlls that you have but your friend doesn't. Or more likely, your friend's .dlls are out of date. That is one route of investigation. It is interesting that the window opens up successfully, and then closes. To me, that points to a problem setting up your OpenGL context. Can you post the code that you call to set up OpenGL?
Another, and in my opinion, better route to take would be to remove sb6 from your application entirely and switch to another, more portable application framework. Sb6 is only intended for practice, if you want a more robust framework I would switch. Since you've only done a small project using sb6, now is also an excellent time to change over because the code changes would be minimal and (relatively :)) painless. Here are a few libraries I suggest:
SDL - My personal favorite. It'll do everything from setting up a window, handling input, networking, playing sounds, and even threading. And it (claims) to be completely portable. Be warned, however. They just went through a major update (1.2 to 2.0) and the documentation hasn't completely caught up yet.
GLFW - If you're making a dedicated OpenGL application, this might be a better option. Since it's built from the ground up to work with OpenGL (unlike SDL, which first and foremost is a windowing framework and doesn't care what you put in the windows) it's faster to set up to work with OpenGL.
SFML - Appears to be a varient of SDL. To be honest, I haven't used this one before, but if you like it, tell me how it is!
There are others out there as well, but these are the big three I've heard of. Let me know if you have any questions about running them.

Related

How to add path an included library in kernel?

I found many example, how to add this in host on C, but syntax C++ differ than C. I want to add external library in my kernel file.
It's part of my code:
std::ifstream sourceFile(name);
std::string sourceCode(
std::istreambuf_iterator<char>(sourceFile),
(std::istreambuf_iterator<char>()));
Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length() + 1));
// Make program of the source code in the context
Program program = Program(context, source);
// Build program for these specific devices
errcode = program.build(devices);
if (errcode != CL_SUCCESS)
{
cout << "There were error during build kernel code. Please, check program code. Errcode = " << errcode << "\n";
cout << "BUILD LOG: " + program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) + "\n";
getchar();
return;
}
// Make kernel
Kernel kernel(program, "vector_add");
How to add path of external library in this code?
In the next step i think, that need to add the second source in Program::Sources. Has anyone written this?
Based on OpenCL 1.2 specification (also the same for 2.0),
-I dir
Add the directory dir to the list of directories to be searched for header files.
You cannot include any ".cl" into another ".cl", but you can #include "Header.h" as much as you want where you can havesome functions or #define, etc.
Note that the code in those header must be in OpenCL C similar to your kernel (except if using OpenCL 2.2, where you can use OpenCL C++).
And lastly, except if you use OpenCL 2.0 and greater, you can't call kernel function inside a kernel, so they must be ordinary function void foo().
So in your case, you could do this:
Program program = Program(context, source);
errcode = program.build(devices, "-I C:\Path\To\My\Include\Header);
And to answer your second question
In the next step i think, that need to add the second source in Program::Sources. Has anyone written this?
You can push_back sources.push_back({ kernelSource.c_str(), kernelSource.length() + 1 }); as much kernel source code as you want into a single sources vector that you provide to the program. But at the end, you can make multiple kernels with this program, since you need to provide a single kernel name per cl::Kernel such as:
Kernel kernel_add(program, "vector_add");
Kernel kernel_sub(program, "vector_sub");
So that mean kernel_add and kernel_sub are build in same time, but they are two different kernels at the end.

glewInit and building dll

I am developing hobby opengl3 engine and I decided to make a new .dll build of it. It uses GLEW to get opengl3 functions from GPU. I've successfully builded it about 5 months ago, but now I've changed a lot and it doesn't want to get working.
So the .dll builds perfectly (windows7, mingw).
I've made a simple program and it crashes on first call to glCreateProgram which is runned by code from mylib.dll.
in pseudocode:
#include "mylib.hpp"
int main(){
std::cout << (void*)glCreateProgram << "\n";
// displays 0 as glCreateProgram haven't been loaded yet
myspace::Window* = new SDL2BasedWindow(...);
//this constructor is from my .dll and calls glewInit() which returns GLEW_OK
std::cout << (void*)glCreateProgram << "\n";
//this displays proper address
int testGLEW= glCreateProgram();
std::cout << "glCreateProgram from main: " << testGLEW<< "\n";
//this displays 1 which means valid call to glCreateProgram
window->runApplication(new Application(...));
//Application is user-defined class, it further creates myspace::ShaderProgram
//which is imported from my .dll (part of my engine) which then calls
//glCreateProgram in it's initialisation
//(it is first call to any function which should be initialized by GLEW if we count only code imported from mylib.dll)
}
//in ShaderProgram constructor:
std::cout << "trying to call glCreateProgram, address: ";
std::cout << (void*)glCreateProgram << "\n"; //this displays 0 (!)
int id = glCreateProgram(); //this ends execution with SIGSEGV
printf("created program: %d\n", id); //so this one is never called
So my question is, why GLEW works only in code which is not imported from my .dll and how can I fix it?
Btw I've checked nm mylib.dll ant it contains glCreateProgram and other glew dependent functions, I also use #define GLEW_STATIC both in .dll and program that uses this .dll
Thanks for your help!
#define GLEW_STATIC is used to build a static library or executable.
To build a .dll use #define GLEW_BUILD instead.

std::cout re-printing everything currently in the console, each time it is used

For some reason, every time I use std::cout, the entire content (sort of, difficult to explain) of the console is re-printed, unless I << endl;. To provide some context, I am using glfw to back my Window class, which has higher level std::function callbacks. My compiler is MinGW 3.21, using what pieces of C++11 MinGW 3.21 actually implements. What is going on?
void Window::setTextCallback(std::function<void(char text)> callback) {
textCallback = callback;
auto onText = [](GLFWwindow* window, unsigned int text, int mods) {
Window* win = reinterpret_cast<Window*>(glfwGetWindowUserPointer(window));
win->textCallback(static_cast<char>(text));
};
glfwSetCharModsCallback(window, onText);
}
And then in main.cpp...
Window w;
w.setTextCallback([](char text){
cout << text;
}
When the window is open, lets say I type "asdf". The output is "aasasdasdf". In slow motion, it goes: "a", "aas", "aasasd", aasasdasdf".
However, if I change main.cpp to:
Window w;
w.setTextCallback([](char text){
cout << text << endl;
}
The output is:
"a
s
d
f"
As expected.
No other threads are using cout and I know that because I don't have any other threads. This behavior does not happen elsewhere.
cout is a buffer. So each time you << to it, you're just adding text and it's holding on. endl is a way to flush the buffer. If you want to print only the last bit of text you push into it, you need to start with it empty. Try this post and then I'm sure your googling can finish any questions you might have about this.

SDL2 library fails to initialize

I'm currently working with SDL2 and GLFW3 to create some OpenGL game. Initializing and using GLFW3 is no problem; I'm using GLFW3 for creating the OpenGL context, window, key input etc. and SDL2 for loading images to SDLSurfaces and then converting them to OpenGL textures, but, unlike GLFW3, SDL2 fails to initialize. My initialization code looks like this:
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
It always returns -1 and quits the main function. Does anyone know why this could happen?
The problem
The problem is not with SDL. SDL actually initializes completely fine. The problem is how you check if the initialization succeeded. Take a look at the documentation for SDL_Init()
Returns 0 on success or a negative error code on failure; call
SDL_GetError() for more information.
In your code code
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
In the if, the SDL_Init(SDL_INIT_EVERYTHING) part will return 0, which evaluates to false but it still means that SDL was successfully initialized. The ! in front, means the entire if will evaluate to true, and -1 will be returned.
Solution
A better soltion is to check if it's equal to 0 and if it does fail, used SDL_GetError() to print the error.
if ( SDL_Init(SDL_INIT_EVERYTHING) != 0 )
{
std::cout << "Error : " << SDL_GetError() << std::endl;
return -1;
}

GLEW functions can't be found

I am on Ubuntu, writing an application using OpenGL, GLEW and GLFW. I am using Eclipse as my IDE, and am having problems when trying to use functions such as glGenRenderbuffer. I have a very similar structure set up under Windows but can't get it to work on Linux.
I am linking to the libraries glfw and GLEW. I am able to compile and run parts of my application and can initialize both GLFW and GLEW. From these test runs I learn the following:
OpenGL version: 4.2.0 NVIDIA 304.64
Using GLEW 1.6.0
However, I can't get the function glGenRenderbuffer (or other framebuffer functions) to compile. I have tried adding both EXT and ARB to the name, as well as playing around with glex.h without any luck. As far as I know, the purpose of GLEW is to handle all extension issues, right?
The source file (VolumeRenderer.cpp) includes are done like this:
#include <glm/gtc/matrix_transform.hpp>
#include <VolumeRenderer.h>
#include <GL/glew.h>
#include <GL/glfw.h>
Further down, I am trying to use the function like this (only partially complete function, of course):
bool VolumeRenderer::InitFramebuffers()
{
glGenRenderbuffers(1, &renderBufferObject_);
return true;
}
All I get is "function 'glGenRenderBuffers' could not be resolved".
Looking in the GL/glew.h header I am including, I found the following lines among others:
#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT)
But the compiler still can't find the function. Is there anything I have forgotten, or maybe some tests and checks I can run to see what is happening?
Alright, so I got it to work by basically copying my Eclipse project file by file into a new, empty project. However, I did some other things before that. First, I moved around the includes as suggested in the helpful comments. I also removed things like glm. No success! Then I made a simple project in Eclipse with one single .cpp file, and linked to glfw and GLEW:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#include <cstdlib>
int main()
{
if (glfwInit() != GL_TRUE) {
std::cout << "glfwInit() failed\n";
exit(1);
}
if (!glfwOpenWindow(800, 600, 8 , 8, 8, 8, 8, 8, GLFW_WINDOW)) {
std::cout << "glfwOpenWindow() failed\n";
exit(1);
}
char *glVersion = (char*)glGetString(GL_VERSION);
if (glVersion) {
std::cout << "OpenGL version: " << glVersion << "\n";
}
GLenum err = glewInit();
if (err != GLEW_OK) {
std::cout << "GLEW init failed: " << glewGetErrorString(err) << "\n";
exit(1);
} else {
std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << "\n";
}
GLuint buf;
glGenRenderbuffers(1, &buf);
exit(0);
}
That worked like a charm. I then tried to recreate my old problem by making another project with a similar file and include structure, and it seemed to work fine too. I then started a third, empty project where I simply made exact copies of the files that were originally giving me trouble. Now I have an exact copy of the original project (that now had the include order changed) with the exact same libraries linked to it, and it works. I still don't know what happened but I suspect that my project in Eclipse got messed up somehow, and never recovered even though I made some changes.