My openGL shaders will not link outside of eclipse? - windows

So I am trying to build a simple spirograph generator for school and everything went fine while in eclipse CDT for windows 7. My program assigns a default shader to each spirograph generated (5 max). There are also 3 other shader programs the user can assign by choice to any spirograph. Inside eclipse it works exactly as it should, but when being ran outside eclipse the shaders fail to link. The program uses GLUT and GLEW and I have included the necessary .dll's in the executable's directory. I've been trying to fix this for a good 4 hours and have no idea what would cause a failure to link outside of eclipse that wouldn't fail all the time.
Im not going to include all of the shaders but here are the first 2 that fail to link and cause the application to terminate
#version 330
layout (location = 0) in vec4 vPosition;
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
out vec4 color;
void main()
{
gl_Position = proj * view * model * vPosition;
color = vec4(
(4 - vPosition.z) * (4 - vPosition.z) / 16.0,
(2.0 - abs( 2.0 - vPosition.z )) / 2.0,
vPosition.z * vPosition.z / 16.0,
1.0
);
}
and fragment shader
#version 330
in vec4 color;
void main()
{
gl_FragColor = color;
}
and printlog
Vertex shader was successfully compiled to run on hardware.
Fragment shader was successfully compiled to run on hardware.
Fragment shader(s) failed to link, vertex shader(s) failed to link.
ERROR: error(#280) Not all shaders have valid object code
ERROR: error(#280) Not all shaders have valid object code
The InitShader() function that I use to compile and link the shaders has worked for the applications I have done in the past. The only thing I am doing different is I am using it to produce a few different shader programs and assign them to programs[] rather than just compile 1 and run it for the whole application.
program[0] = InitShader("shaders/vshader.glsl", "shaders/fshader.glsl");
program[1] = InitShader("shaders/vshader2.glsl", "shaders/fshader.glsl");
program[2] = InitShader("shaders/vshader3.glsl", "shaders/fshader.glsl");
program[3] = InitShader("shaders/vshaderw.glsl", "shaders/fshader.glsl");
But either way, here is the code for InitShader().
GLuint InitShader(const char* source, GLenum type)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, (const GLchar**) &source, NULL );
glCompileShader(shader);
printLog( shader );
return shader;
}
GLuint InitShader(const char* vfile, const char *ffile) {
GLuint program = glCreateProgram();
GLuint shader;
// stringify and attach vshader
std::ifstream vertstream(vfile);
std::string vert((std::istreambuf_iterator<char>(vertstream)), std::istreambuf_iterator<char>());
shader = InitShader(vert.c_str(), GL_VERTEX_SHADER);
glAttachShader( program, shader );
// stringify and attach fshader
std::ifstream fragstream(ffile);
std::string frag((std::istreambuf_iterator<char>(fragstream)), std::istreambuf_iterator<char>());
shader = InitShader(frag.c_str(), GL_FRAGMENT_SHADER);
glAttachShader( program, shader );
// link program
glLinkProgram(program);
printLog(program);
// link and error check
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
fprintf(stderr, "Shaders failed to link!\n");
exit( EXIT_FAILURE );
}
// use program object
glUseProgram(program);
return program;
}
Its 4am here so my grey cells are about spent haha. And fyi its not really homework help, the executable is not required to run outside of eclipse for the class, I just want to know how to create stand alone programs for myself.

The cause of your problem lies here:
program[0] = InitShader("shaders/vshader.glsl", "shaders/fshader.glsl");
The paths to the shader source files are relative. Chances are, that Eclipse runs your program from a different working directory (probably your project root) than what's the working directory when executing the program directly.
Solution: Either
make sure the working directory on program startup matches the relative paths used internally (very unreliable)
use absolute paths within the program (very unflexible)
or, what I suggest
determine the location of the shader files at runtime (command line option, location of the executable binary, etc) and adjust the paths accordingly at runtime.

Related

How to use Cmake for OpenGL + Qt 5.8 in OS X Sierra?

I just tried to setup CMake for a project using Qt 5.8 to do OpenGL stuff in OS X Sierra. Here you can see my main CMakeLists
cmake_minimum_required (VERSION 3.8)
set (PROJECT_NAME "FluidEngine")
project (${PROJECT_NAME})
set (CMAKE_PREFIX_PATH "/Users/BRabbit27/Qt/5.8/clang_64")
set (CMAKE_AUTOMOC ON)
find_package (Qt5Widgets)
find_package (Qt5Gui)
find_package (Qt5OpenGL)
set (CPP_SOURCES "")
set (HPP_SOURCES "")
set (INCLUDE_PATHS "")
add_subdirectory (src)
include_directories (${INCLUDE_PATHS} ${OPENGL_INCLUDE_DIRS})
add_executable (${PROJECT_NAME} ${CPP_SOURCES} ${HPP_SOURCES})
target_link_libraries (${PROJECT_NAME} Qt5::Widgets Qt5::Gui Qt5::OpenGL )
It perfectly configures the xcode project, no errors.
Then my code for rendering a basic triangle looks like:
GLWindow::GLWindow(QWidget* parent) : QOpenGLWidget(parent)
{}
void GLWindow::initializeGL()
{
initializeOpenGLFunctions();
GLfloat verts[] =
{
0.f, 1.f,
-1.f, -1.f,
1.f, -1.f
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID);
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
void GLWindow::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void GLWindow::paintGL()
{
glDrawArrays(GL_TRIANGLES, 0, 3);
}
And what I get is a black window. I got this code from this video tutorial
Am I missing something in my cmake file or something subtle in OS X to use OpenGL? Since OS X is now promoting Metal, perhaps something must be enabled but I do not know what.
I already tried setting the version of OpenGL used in the main function
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setVersion(4, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
GLWindow glwindow;
glwindow.show();
return app.exec();
}
Any idea?
UPDATE
Added project to github, you can clone it here to test in your machine.
The way I build the project is just cmake -GXcode .. assuming i'm in /path/to/project/build_xcode directory.
Hope this can help you reproduce and perhaps give me a clue on what I could be doing wrong.
I checked all the error messages and from there make my way to found the solution. Fortunately someone already replied in SO with a related problem and had a solution to the problem. You can find the complete answer here OpenGL: INVALID_OPERATION following glEnableVertexAttribArray
For short
You're seeing this error on OS X because it only supports the OpenGL
Core Profile if you're using OpenGL 3.x or higher. Your code is not
Core Profile compliant. You were most likely using the Compatibility
Profile on Windows.
Specifically, the Core Profile requires a Vertex Array Object (VAO) to
be bound for all vertex related calls. So before calling
glEnableVertexAttribArray(), or other similar functions, you will
need to create and bind a VAO.

glMapBufferRange crashing on Android GLES app

I am trying to morph some vertices on a GLES application on android and glMapBufferRange keeps crashing with the following error:
SIGSEGV (signal SIGSEGV: address access protected (fault address: 0xef13d664))
I more or less followed the example of this web-site:
http://www.songho.ca/opengl/gl_vbo.html#update
but not sure if I am missing something.
I created my VBOs at initialization time and I can draw the object with no issues. The code of creation goes:
void SubObject3D::CreateVBO(VBOInfo &vboInfoIn) {
// m_vboIds[0] - used to store vertex attribute data
// m_vboIds[l] - used to store element indices
glGenBuffers(2, vboInfoIn.vboIds);
// Let the buffer all dynamic for morphing
glBindBuffer(GL_ARRAY_BUFFER, vboInfoIn.vboIds[0]);
glBufferData(GL_ARRAY_BUFFER,
(GLsizeiptr) (vboInfoIn.vertexStride * vboInfoIn.verticesCount),
vboInfoIn.pVertices, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboInfoIn.vboIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(GLsizeiptr) (sizeof(GLushort) * vboInfoIn.indicesCount),
vboInfoIn.pIndices, GL_STATIC_DRAW);
}
struct VBOInfo {
VBOInfo() {
memset(this, 0x00, sizeof(VBOInfo));
vboIds[0] = 0xdeadbeef;
vboIds[1] = 0xdeadbeef;
}
// VertexBufferObject Ids
GLuint vboIds[2];
// Points to the source data
GLfloat *pVertices; // Pointer of original data
GLuint verticesCount;
GLushort *pIndices; // Pointer of original data
GLuint indicesCount;
GLint vertexStride;
};
then later in the Rendering loop I tried to get the hold of my vertex pointer as such:
// I stored the information at creation time here:
VBOInfo mVBOGeometryInfo;
//later I call here to get the pointer
GLfloat *SubObject3D::MapVBO() {
GLfloat *pVertices = nullptr;
glBindBuffer(GL_ARRAY_BUFFER, mVBOGeometryInfo.vboIds[0]);
GLsizeiptr length = (GLsizeiptr) (mVBOGeometryInfo.vertexStride *
mVBOGeometryInfo.verticesCount);
pVertices = (GLfloat *) glMapBufferRange(
GL_ARRAY_BUFFER, 0,
length,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT
);
if (pVertices == nullptr) {
LOGE ("Could not map VBO");
}
return pVertices;
}
but it crashed right at glMapBufferRange.
This is an android application that uses NDK. The hardware is a Samsung S6 phone.
thx!
This was quite painful to resolve this issue, but there is no problem with the code above per se. It was basically the include. My code was based off the google sample "more teapots" located here:
https://github.com/googlesamples/android-ndk/tree/master/teapots
I had to follow their pattern and change my include to GLES from:
#include <GLES3/gl3.h>
to use their stubs:
#include "gl3stub.h"
why? I don't know, but likely causing the linker to link incorrect code.

Mali offline compiled shaders using in OpenGLES2.0 Application

I am using Mali-400 GPU.
I want to use the Mali off-line shader compiler, to compile the Vertex shader and Fragment shaders.
I have compiled my Vertex shader and Fragment shader using ARM Mali off-line compiler with below step
malisc.exe --vertex -c Mali-400 -r r1p1 -d Mali-400_r5p0-01rel0 Vertex_shader.glsl -o vshader.out
malisc.exe --fragment -c Mali-400 -r r1p1 -d Mali-400_r5p0-01rel0 Fragm_shader.glsl -o fragment.out
I am using below like code,
my application compiles successfully, but application not running on my target.
copied the shader binaries content into a static array and usign that with glShaderBinary.
my code snippet:
char VertexShaderArray[] = {<initialized using shader binary data>};
char fragShaderArray[] = {<initialized using shader binary data>};
GLuint v, f, program;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderBinary(1, &v, MALI_PROGRAM_BINARY_ARM, (void*)&VertexShaderArray, sizeof(char)*sizeof(VertexShaderArray));
glShaderBinary(1, &f, MALI_PROGRAM_BINARY_ARM, (void*)&fragShaderArray, sizeof(char)*sizeof(fragShaderArray));
program = glCreateProgram();
glAttachShader(program, v);
glAttachShader(program, f);
glLinkProgram(program);
glUseProgram(program);
I am getting a message on my target while running this application:
info: L0101 All attached shaders must be compiled prior to linking
Can some one please post the example code for using off-line compiled shaders in a OpenGLES2.0 application.

GLEW crashing in XCode

I'm trying to run a simple OpenGL program using GLFW (version 3.0.2) and GLEW (version 1.10.0) in XCode (version 4.6.3) on OS X 10.8.4. The entire code is shown below.
#include <GLFW/glfw3.h>
#include <OpenGL/OpenGL.h>
#include <iostream>
using namespace std;
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void InitGL()
{
glClearColor(1, 0, 0, 1);
}
void ErrorFunc(int code, const char *msg)
{
cerr << "Error " << code << ": " << msg << endl;
}
int main(void)
{
GLFWwindow* window;
/* Report errors */
glfwSetErrorCallback(ErrorFunc);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Window hints */
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Initialize OpenGL */
InitGL();
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
RenderScene();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Most of this came straight from GLFW's documentation; only the rendering function and GLEW initialization are mine. I have added frameworks for OpenGL, Cocoa and IOKit and linked against libGLEW.a and libglfw3.a. The program compiles successfully but appears to crash when attempting to execute functions GLEW was supposed to take care of. Here, the program crashes on glClearBufferfv. If I comment that out, I get a window with a black background. My guess is GLEW is secretly not working, since it reports no errors but doesn't seem to be doing its job at all.
The exact error message XCode throws at me is error: address doesn't contain a section that points to a section in a object file with an error code of EXC_BAD_ACCESS. If I replace glClearBufferfv with glClearColor the program doesn't crash, but still has a black background when it should actually be red. When queried, OpenGL returns the version string 2.1 NVIDIA-8.12.47 310.40.00.05f01, which explains why calls to newer functions aren't working, but shouldn't GLEW have set up the correct OpenGL context? Moreover, GLFW's documentation says that they've been creating OpenGL 3+ contexts since GLFW 2.7.2. I really don't know what to do.
glClearBuffer (...) is an OpenGL 3.0 function, it is not implemented in all versions of OS X (some only implement OpenGL 2.1). Because OS X does not use runtime extensions, GLEW is not going to fix this problem for you.
You will have to resort to the traditional method for clearing buffers in older versions of OS X (10.6 or older). This means setting the "clear color" and then clearing the color buffer as a two-step process. Instead of a single function call that can clear a specific buffer to a specific value, use this:
#define USE_GL3 // This code requires OpenGL 3.0, comment out if unavailable
void RenderScene()
{
GLfloat color[] = {1.0f, 0.0f, 0.0f};
#ifdef USE_GL3 // Any system that implements OpenGL 3.0+
glClearBufferfv (GL_COLOR, 0, color);
#else // Any other system
glClearColor (color [0], color [1], color [2]);
glClear (GL_COLOR_BUFFER_BIT);
#endif
}
This is not ideal, however. There is no point in setting the clear color multiple times. You should set the clear color one time when you initialize the application and replace the ! USE_GL3 branch of the code with glClear (GL_COLOR_BUFFER_BIT);
Now, because you mentioned you are using Mac OS X 10.8, you can ignore a lot of what I wrote above. OS X 10.8 actually implements OpenGL 3.2 if you do things correctly.
You need two things for glClearBuffer (...) to work on OS X:
Mac OS X 10.7+ (which you have)
Tell glfw to create an OpenGL 3.2 core context
Before you create your window in glfw, add the following code:
glfwWindowHint (GLFW_OPENGL_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_OPENGL_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Once you have an OpenGL 3.2 core context, you can also eliminate the whole ! USE_GL3 pre-processor branch from your code. This was a provision to allow your code to work on OS X implementations that do not support OpenGL 3.2.
GLEW doesn't really work on mac unless you enable the experimental option. Enable it after setting all your stuff in GLFW.
glewExperimental = GL_TRUE;
Edit:
And you also set to use OpenGL Core with
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
Slightly different from yours.

Xcode executable cannot find glsl files

This is the first time I try to learn OpenGL, I'm following the examples of a book. I'm doing it under OS X 10.8 with Xcode. The code is the following:
#include "Angel.h"
const int numPoints = 5000;
typedef vec2 point2;
void init(){
point2 points[numPoints];
point2 vertices[3] = {
point2(-1.0, -1.0), point2(0.0, 1.0), point2(1.0, -1.0)
};
points[0] = point2(0.25, 0.5);
for (int k = 1; k < numPoints; k++) {
int j = rand()%3;
points[k] = (points[k-1]+vertices[j])/2.0;
}
GLuint program = InitShader("vertex.glsl", "fragment.glsl");
glUseProgram(program);
GLuint abuffer;
glGenVertexArraysAPPLE(1, &abuffer);
glBindVertexArrayAPPLE(abuffer);
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
GLuint location = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(location);
glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void display(){
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, numPoints);
glFlush();
}
int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(640, 480);
glutCreateWindow("Sierpinski Gasket");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
It compiles. But when I try to execute it the window does not appear. The problem arises when I call the init() function. Without it the window appears but with a black background. With it, there's no window. The code can be found here.
UPDATE
Apparently the program is exiting in the line GLuint program = InitShader("vertex.glsl", "fragment.glsl"); because it's not finding the shader-files. How can I tell the program to use the files? I mean I have the .glsl files in the same folder as the .h and .cpp but when Xcode builds the project the executable is not in the same place as the .glsl files. How to solve this within Xcode?
The GLSL files are loaded at the runtime of the program. So it's not XCode that doesn't find the files, but your program. The most likely cause is, that you used a relative path for the files (like in the code snippet you provided), but started your program with a working path that doesn't match up with the hardcoded file locations. Usually your program binary is built into a dedicated build directory.
A quick fix is copying the GLSL files into the same directory as the binary. The proper solution would be to place the filed in a well known location. In MacOS X you can use Application bundles for this. See in the MacOS X developer docs how to place application resources into the Application bundle and how to access them. XCode also provides tools to automatically copy files into the generated bundle.
Follow Below Step:
Select the project on the left panel.
Select the target and then select Build Phases
There you should fin a button called Add Build Phase
There will appear a box where you have to select the files (there's a little +sign). And be sure you selected Destination: Products directory
Build the project, run it and now it should work !!
If Xcode isn't importing the files, then check if it's adding it to the resource folder by going to Your project Name in the file chooser, build phases, Copy Bundle Resources and make sure your 2 files are in there.

Resources