I'm working on my custom game engine, and thus far everything is working fine.
Until I stumbled upon a weird error.
When I try to validate my shader program it returns GL_FALSE, to ensure good debugging I check the log info for error messages when something fails, but this error doesn't have a info log message, I checked whether it reads the files correctly and there's no error there... So I'm kinda stuck, I've looked all over the internet without any success, I hope someone on here can help me out with this one.
Thanks in advance!
In the main function I create a new shader program with 2 shader files, a vertex shader and a fragment shader, both compile without any errors.
GLuint shaderProgram = glCreateProgram();
std::string vertexFile = FileUtils::read_file("shaders/basic.vert");
std::string fragmentFile = FileUtils::read_file("shaders/basic.frag");
const char* vertexSource = vertexFile.c_str();
const char* fragmentSource = fragmentFile.c_str();
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vertexSource, NULL);
glCompileShader(vertex);
GLint result;
glGetShaderiv(vertex, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE)
{
GLint length;
glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetShaderInfoLog(vertex, length, &length, &error[0]);
std::cerr << "Failed to compile the vertex shader!" << std::endl;
std::cerr << &error[0] << std::endl;
glDeleteShader(vertex);
return -1;
}
glAttachShader(shaderProgram, vertex);
GLuint fragment = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(fragment, 1, &fragmentSource, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE)
{
GLint length;
glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetShaderInfoLog(fragment , length, &length, &error[0]);
std::cerr << "Failed to compile the fragment shader!" << std::endl;
std::cerr << &error[0] << std::endl;
glDeleteShader(fragment);
return -1;
}
glAttachShader(shaderProgram, fragment);
glValidateProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_VALIDATE_STATUS, &result);
if (result != GL_TRUE)
{
GLint length;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetProgramInfoLog(shaderProgram, length, &length, &error[0]);
std::cerr << "Failed to validate the shader program!" << std::endl;
std::cerr << &error[0] << std::endl;
glDeleteProgram(shaderProgram);
return -1;
}
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result);
if (result != GL_TRUE)
{
GLint length;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetProgramInfoLog(shaderProgram, length, &length, &error[0]);
std::cerr << "Failed to link the shader program!" << std::endl;
std::cerr << &error[0] << std::endl;
glDeleteProgram(shaderProgram);
return -1;
}
glUseProgram(shaderProgram);
Here's the read_file function from my FileUtils class:
std::string FileUtils::read_file(const char* filepath)
{
FILE* file = fopen(filepath, "rt");
fseek(file, 0, SEEK_END);
unsigned long length = ftell(file);
char data[length + 1];
memset(data, 0, length + 1);
fseek(file, 0, SEEK_SET);
fread(data, 1, length, file);
fclose(file);
std::string result(data);
return result;
}
I know it loads the files correctly because I made them print to the console to make sure the paths and files were correct, no errors there!
P.S.
If you see any errors in the code (such as "shader" as variable name) that is because I had to edit the original code to make it all fit in 1 code block for this.
glValidateProgram should be placed after glLinkProgram, but before glUseProgram.
A quote from here:
glValidateProgram checks to see whether the executables contained in
program can execute given the current OpenGL state
If the program is not linked yet, it cannot be executed.
Related
I am trying to get my C++ driven OpenGL working in a Cocoa app. In order to have everything in one place I need to load my shader and textures files in my C++. I'm doing that with std::ifstream, which fails to open files for some reason.
I have had a similar problem in the past when in order for XCode to open files you need to add them to the project and then do one of 3 things:
1) Copy them to Products Directory on the build phase
2) Change your Working directory in your scheme
3) Just use the full file path
However in my recent project neither have helped. The most interesting thing is in a very similar project(basically the project where I tried and tested everything it did work). I suppose I didn't move all the project settings over, but everything seems the same.
The only difference between them is that the one I'm working on now has more Objective-C in it.
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CVDisplayLink.h>
#import "Application.hpp"
#interface viewObj : NSOpenGLView {
CVDisplayLinkRef displayLink;
Application* appInstance;
}
#end
#implementation viewObj
-(void)awakeFromNib
{
appInstance = new Application();
// other GL initializing code
}
#end
Application.hpp
#include "appView.hpp"
class Application {
private:
appView viewInstance{};
public:
Application();
void update();
~ Application();
};
appView.hpp
class appView {
private:
bool graphical;
GLuint texture;
int screenWidth, screenHeight;
Shader shader{"full_path/core.vs", "full_path/core.frag"};
std::vector<GLfloat> vert;
}
Shader.hpp
class Shader {
public:
GLuint Program;
Shader(const std::string& vertexPath, const std::string& fragmentPath)
{
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions (std::ifstream::badbit);
fShaderFile.exceptions (std::ifstream::badbit);
try
{
vShaderFile.open(vertexPath.c_str(), std::ios::in);// Failing here
if (!vShaderFile.is_open()) {
throw std::runtime_error(std::string("Failed to open shader file: ") + std::string(vertexPath));
}
fShaderFile.open(fragmentPath.c_str(), std::ios::in);
if (!fShaderFile.is_open()) {
throw std::runtime_error(std::string("Failed to open shader file: ") + std::string(fragmentPath));
}
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
vShaderStream << "\0";
fShaderStream << fShaderFile.rdbuf();
fShaderStream << "\0";
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str( );
fragmentCode = fShaderStream.str( );
}
catch ( std::ifstream::failure e )
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar *vShaderCode = (const GLchar *)vertexCode.c_str();
const GLchar *fShaderCode = (const GLchar *)fragmentCode.c_str();
// Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader Program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Uses the current shader
void Use() const {
glUseProgram(this->Program);
}
};
Apparently the problem was with my app not having access to any files due to sandbox mode, which I disabled in .entitlements and that fixed the problem
I am trying to draw some text and while trying to create the shader program for the text I get an access violation executing location error from GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
start of main Function where problem is:
int main(int argc, char **argv) {
//GLTtext* text = gltCreateText();
//gltSetText(text, "ElectroCraft");
//GLFWwindow* window;
int width = 860, height = 490;
if (!glfwInit()) {
printf("failed to init glfw");
return -1;
}
glutInit(&argc, argv);
window = glfwCreateWindow(width, height, "ElectroCraft", NULL, NULL);
glfwMakeContextCurrent(window);
if (!window) {
printf("failed to start window");
glfwTerminate();
return -1;
}
/*if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}*/
//build and compile shader program
//-----------------------------------
//vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
//fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//check for liunking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
...
all Includes as this may be the problem as well:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <GL/freeglut.h>
#include <map>
#include <GL/GL.h>
#include <stdio.h>
#include <string>
#include <glm\glm.hpp>
#include <iostream>
#include <ft2build.h>
//#include <glad.h>
#include FT_FREETYPE_H
using namespace std;
I could be getting this problem as i might not of provided the correct arguments or something else.
You have include glew but you hadn't initialized it.
Before accessing any GL functions, insert this code:
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
...
}
std::cerr << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
Reference: GLEW Basics
I expect my program to draw me a simple red triangle. The vertex and fragment shaders are supposed to be loaded from external files via my loadShader() function, but for some weird reason my loadShader() function is reading non-ASCII characters, such that shader compile errors are getting generated.
Attempts to convert both of my shader files to an ASCII format following the instructions provided here (using Notepad++) failed, since the outcome is the same -- namely, the shader compiler error regarding the non-ASCII characters (see screenshots below) and a white instead of an expected red triangle (due to the shader not compiling).
Further Troubleshooting Attempts:
(Note: I additionally uploaded my source code to Pastebin for easy line number referencing.)
The critical code parts go from 14 to 44 -- my loadShader function.
The "tell file size" section starting at line 22 is working properly as evidenced in the screenshots below, since my debug output (line 25) has the same byte number as the file size provided by the Windows Explorer.
Furthermore, the buffer (in line 28) is corresponding exactly to the shader file sizes as evidenced in the debug output in line 41 (see screenshots).
Lastly, the syntaxes of my two shaders are correct, since I previously hard-coded them and the result was the desired red triangle rendering.
Screenshot:
Source Code:
// Expected result: Draws a simple red colored triangle to the screen
// Problem to debug: Why does my loadShader function read non-ASCII characters?
#include <glad/glad.h>
#define GLFW_DLL
#include <GLFW\glfw3.h>
#include <cstdio>
#include <iostream>
// TODO: Debug
/* Loads shader text files from a given file name (extension required)
* and returns the shader code as a null terminated string from that file.
*/
const char * loadShader(const char * shaderFileName) {
FILE * shaderFile{};
fopen_s(&shaderFile, shaderFileName, "r");
if (!shaderFile) {
std::cerr << "ERROR: Cannot open file" << std::endl;
return "\0";
}
// Tell file size
fseek(shaderFile, 0L, SEEK_END);
unsigned long shaderFileSize{};
shaderFileSize = ftell(shaderFile);
std::cout << "DEBUG: shaderFileSize: " << shaderFileSize << std::endl; // Debug output
rewind(shaderFile);
// Read from file
char * buffer = (char *)malloc(sizeof(char)*(shaderFileSize+1UL));
if (!buffer) {
std::cerr << "ERROR: Failed to allocate memory" << std::endl;
return "\0";
}
int c{};
int i = 0;
while ((c = fgetc(shaderFile))!= EOF) {
buffer[i++] = c;
}
// Put '\0' at the end of the buffer (required for OpenGL)
buffer[shaderFileSize] = '\0';
std::cout << "DEBUG: buffer: " << buffer << std::endl; // Debug output
std::cout << "DEBUG: strlen: " << strlen(buffer) << std::endl; // Debug output
fclose(shaderFile);
return buffer;
} // end of loadShader()
int main() {
// Initialize GLFW
if (!glfwInit()) {
std::cerr << "ERROR: Failed to initialize GLFW3" << std::endl;
return -1;
}
// Create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Game", nullptr, nullptr);
if (!window) {
std::cerr << "ERROR: Failed to create window with GLFW3" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Load all OpenGL function pointers.
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cerr << "ERROR: Failed to initialize GLAD" << std::endl;
return -1;
}
// Get info from renderer
const GLubyte* rendererName = glGetString(GL_RENDERER);
const GLubyte* OpenGLVersionSupported = glGetString(GL_VERSION);
std::cout << rendererName << std::endl << OpenGLVersionSupported << std::endl;
// Enable depth
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Define triangle
GLfloat points[] = { 0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f };
// Create buffer object
GLuint vertexBufferObject = 0;
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
// Create vertex attribute object
GLuint vertexAttributeObject = 0;
glGenVertexArrays(1, &vertexAttributeObject);
glBindVertexArray(vertexAttributeObject);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// Load shaders
const char * vertexShaderCode = loadShader("VertexShader.glsl");
const char * fragmentShaderCode = loadShader("FragmentShader.glsl");
// Compile shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderCode, nullptr);
glCompileShader(vertexShader);
// Check vertex shader for compile errors
int success = 0;
char message[512] = "";
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, nullptr, message);
std::cerr << "ERROR: Failed to compile vertex shader" << std::endl << message;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderCode, nullptr);
glCompileShader(fragmentShader);
// Check fragment shader for compile errors
success = 0;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, nullptr, message);
// TODO: Specify error type in message
std::cerr << "ERROR: Failed to compile fragment shader" << std::endl << message;
}
// Create shader program and link it
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetShaderInfoLog(shaderProgram, 512, nullptr, message);
// TODO: Specify error type in message
std::cerr << "ERROR: Failed to link shaders" << std::endl << message;
}
// Render loop
while (!glfwWindowShouldClose(window)) {
// Wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use shader program and vertex attribute object
glUseProgram(shaderProgram);
glBindVertexArray(vertexAttributeObject);
// Draw from the currently bound vertex attribute object
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwPollEvents();
glfwSwapBuffers(window);
}
// Exit program
glfwTerminate();
return 0;
} // end of main()
0xcd is a value used by MSVC CRT to fill uninitialized memory. What happens is that your file uses \r\n line endings but you open it in text mode and the CRT converts them to \n line endings. As a result you read into buffer less bytes than is the size returned by ftell, so that the last value of i is less than shaderFileSize, and, accordingly, you have some uninitialized bytes between the last value written to buffer[i] and the null-terminator.
Instead, replace your code with:
FILE * shaderFile{};
fopen_s(&shaderFile, shaderFileName, "rb"); // <-------- HERE !!!!
fseek(shaderFile, 0L, SEEK_END);
unsigned long shaderFileSize = ftell(shaderFile);
rewind(shaderFile);
char * buffer = (char *)malloc(shaderFileSize+1);
fread(buffer, shaderFileSize, 1, shaderFile);
buffer[shaderFileSize] = '\0';
I'm trying to make a function that can read and compile opengl vertex and fragment shader files, but I'm getting this error:
'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str': non-standard syntax; use '&' to create a pointer to member
I'm not quite sure how to fix it. Here is my code:
GLuint shader_load(const GLchar* vertex, const GLchar* fragment) {
std::string ver = file_read_all(vertex);
std::string frag = file_read_all(fragment);
const GLchar* verCode = ver.c_str;
const GLchar* fragCode = frag.c_str;
GLuint program;
GLuint verShader, fragShader;
GLint success;
GLchar log[512];
verShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(verShader, 1, &verCode, NULL);
glCompileShader(verShader);
glGetShaderiv(verShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(verShader, 512, NULL, log);
std::cout << "Failed to compile Vertex Shader\n" << log << std::endl;
return NULL;
}
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragCode, NULL);
glCompileShader(fragShader);
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragShader, 512, NULL, log);
std::cout << "Failed to compile Fragment Shader\n" << log << std::endl;
return NULL;
}
program = glCreateProgram();
glAttachShader(program, verShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(program, 512, NULL, log);
std::cout << "Failed to Link Shader\n" << log << std::endl;
}
glDeleteShader(verShader);
glDeleteShader(fragShader);
}
I'm using Visual Studio Community 2015 on Windows 10
std::string::c_str is a member function, if you want to call it, you should add ().
const GLchar* verCode = ver.c_str();
~~
I was working on my graphics program. I am trying to abstract features from the Shaders into a class. I tested the regular drawing Code and it works. The shaders run as well but as soon as I start using these OpenGL shader functions it stops working.
Shader::Shader(char c)
{
//program = int(0);
if (program!=0 || glIsProgram(program))
glDeleteProgram(program);
uniforms.clear();
program = glCreateProgram();
}
void Shader::compileProgram()
{
GLint Result = GL_FALSE;
int InfoLogLength;
glLinkProgram(program);
glValidateProgram( program);
glGetProgramiv(program, GL_LINK_STATUS, &Result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::string ProgramErrorMessage = std::string();
ProgramErrorMessage.resize( glm::max(InfoLogLength, int(1)));
glGetProgramInfoLog(program, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::cout << ProgramErrorMessage.c_str() << std::endl;
}
void Shader::addToProgram( std::string File, GLenum type)
{
std::cout << glGetError() << std::endl;
GLuint shader = glCreateShader(type);
std::cout << glewGetErrorString(glGetError()) << std::endl;
std::string ShaderCode;
std::ifstream ShaderStream(File, std::ios::in);
if(ShaderStream.is_open())
{
std::string Line = "";
while(getline(ShaderStream, Line))
ShaderCode += Line + "\n";
ShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
std::cout << "Compiling shader : " << File<< std::endl;
const char * SourcePointer = ShaderCode.c_str();
std::cout << SourcePointer << std::endl;
int length = ShaderCode.size();
glShaderSource(shader, 1, &SourcePointer , &length );
glCompileShader(shader);
// Check Vertex Shader
glGetShaderiv(shader, GL_COMPILE_STATUS, &Result);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(shader, InfoLogLength, NULL, &ShaderErrorMessage[0]);
printf("%s\n", &ShaderErrorMessage[0]);
glAttachShader(program, shader); //Invalid Operation, eighter Program or shader invalid
std::cout << glGetError() << std::endl;
}
So the Problem was that the Program was invalid.
What I did is this:
if(!glIsProgram(program))
program = glCreateProgram();
glAttachShaders(program, shader);
I did the same guard in the constructor. I am still wondering how that happened. I mean I checked the values in Debug and they all seemed valid.