GLuint Shaders::loadShaders(std::string vertexShader, std::string fragmentShader) { GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); std::string vertexShaderData; std::ifstream vertexShaderFile(vertexShader); if (!vertexShaderFile) { std::cout << "Can't open vertex shader" << std::endl; return 0; } std::string line; while (std::getline(vertexShaderFile, line)) { vertexShaderData += "\n" + line; } vertexShaderFile.close(); std::string fragmentShaderData; std::ifstream fragmentShaderFile(fragmentShader); if (!fragmentShaderFile) { std::cout << "Can't open fragment shader" << std::endl; return 0; } std::string line2; while (std::getline(fragmentShaderFile, line2)) { fragmentShaderData += "\n" + line2; } fragmentShaderFile.close(); const char * vertexPtr = vertexShaderData.c_str(); const char * fragmentPtr = fragmentShaderData.c_str(); glShaderSource(vertexShaderId, 1, &vertexPtr, NULL); glShaderSource(fragmentShaderId, 1, &fragmentPtr, NULL); glCompileShader(vertexShaderId); glCompileShader(fragmentShaderId); GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShaderId); glAttachShader(shaderProgram, fragmentShaderId); glLinkProgram(shaderProgram); glDeleteShader(vertexShaderId); glDeleteShader(fragmentShaderId); return shaderProgram; }
Shader ResourceManager::loadShaderFromFile(const GLchar* vShaderFile, const GLchar* fShaderFile, const GLchar* gShaderFile) { // Define variables std::string vertexCode; std::string fragmentCode; std::string geometryCode; try { // Vertex std::ifstream vertexShaderFile(vShaderFile); std::stringstream vShaderStream; vShaderStream << vertexShaderFile.rdbuf(); vertexShaderFile.close(); vertexCode = vShaderStream.str(); // Fragment std::ifstream fragmentShaderFile(fShaderFile); std::stringstream fShaderStream; fShaderStream << fragmentShaderFile.rdbuf(); fragmentShaderFile.close(); fragmentCode = fShaderStream.str(); // Geometry if (gShaderFile != nullptr) { std::ifstream geometryShaderFile(gShaderFile); std::stringstream gShaderStream; gShaderStream << geometryShaderFile.rdbuf(); geometryShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; } Shader shader; shader.Compile(vertexCode.c_str(), fragmentCode.c_str(), gShaderFile != nullptr ? geometryCode.c_str() : nullptr); return shader; }
Shader::Shader(string filename, GLenum shader_type) { name = filename; type = shader_type; // load the fragment shader. fstream fragmentShaderFile(filename, std::ios::in); string fragmentShaderSource; if (fragmentShaderFile.is_open()) { stringstream buffer; buffer << fragmentShaderFile.rdbuf(); fragmentShaderSource = buffer.str(); } else { fragmentShaderFile.close(); ShaderHandle = 0; cerr << "could not find " << filename << endl; return; } fragmentShaderFile.close(); ShaderHandle = glCreateShader( type ); const char *g = fragmentShaderSource.c_str(); glShaderSource( ShaderHandle, 1, &g, NULL ); glCompileShader( ShaderHandle ); //Error checking. int isCompiled; glGetShaderiv( ShaderHandle, GL_COMPILE_STATUS, &isCompiled ); if( !isCompiled ) { GLint maxLength = 0; glGetShaderiv( ShaderHandle, GL_INFO_LOG_LENGTH, &maxLength ); //The maxLength includes the NULL character std::vector<char> errorLog( maxLength ); glGetShaderInfoLog( ShaderHandle, maxLength, &maxLength, errorLog.data() ); // &errorLog[0] cerr << "error in file " << filename << endl; cerr << errorLog.data() << endl; glDeleteShader( ShaderHandle ); //Don't leak the shader. return; } }
Shader resourceManagerClass::loadShaderFromFile(const GLchar *vShaderFile, const GLchar *fShaderFile, const GLchar *gShaderFile) { // 1. Retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; try { // Open files std::ifstream vertexShaderFile(vShaderFile); std::ifstream fragmentShaderFile(fShaderFile); std::stringstream vShaderStream, fShaderStream; // Read file's buffer contents into streams vShaderStream << vertexShaderFile.rdbuf(); fShaderStream << fragmentShaderFile.rdbuf(); // close file handlers vertexShaderFile.close(); fragmentShaderFile.close(); // Convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // If geometry shader path is present, also load a geometry shader if (gShaderFile != nullptr) { std::ifstream geometryShaderFile(gShaderFile); std::stringstream gShaderStream; gShaderStream << geometryShaderFile.rdbuf(); geometryShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::exception e) { std::cout << "ERROR::SHADER: Failed to read shader files" << std::endl; } const GLchar *vShaderCode = vertexCode.c_str(); const GLchar *fShaderCode = fragmentCode.c_str(); const GLchar *gShaderCode = geometryCode.c_str(); // 2. Now create shader object from source code Shader shader; shader.Compile(vShaderCode, fShaderCode, gShaderFile != nullptr ? gShaderCode : nullptr); return shader; }
Shader ResourceManager::loadShaderFromFile(const GLchar* vShaderFile, const GLchar* fShaderFile, const GLchar* gShaderFile) { std::string vertexCode, fragmentCode, geometryCode; try { // open the files std::ifstream vertexShaderFile(vShaderFile); std::ifstream fragmentShaderFile(fShaderFile); std::stringstream vShaderStream, fShaderStream; // read file's buffer contents into streams vShaderStream << vertexShaderFile.rdbuf(); fShaderStream << fragmentShaderFile.rdbuf(); vertexShaderFile.close(); fragmentShaderFile.close(); // convert stream to string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // if geometry path was passed in, load the geometry shader if (gShaderFile != nullptr) { std::ifstream geoShaderFile(gShaderFile); std::stringstream gShaderStream; gShaderStream << geoShaderFile.rdbuf(); geoShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::exception e) { std::cout << "ERROR::SHADER: Failed to read shader files" << std::endl; } const GLchar* vShaderCode = vertexCode.c_str(); const GLchar* fShaderCode = fragmentCode.c_str(); const GLchar* gShaderCode = geometryCode.c_str(); // create the shader object from source code Shader shader; shader.compile(vShaderCode, fShaderCode, gShaderFile != nullptr ? gShaderCode : nullptr); return shader; }
int main(int argc, char * argv[]) { // Load GLFW and Create a Window glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); auto mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGL", nullptr, nullptr); // Check for Valid Context if (mWindow == nullptr) { fprintf(stderr, "Failed to Create OpenGL Context"); return EXIT_FAILURE; } // Create Context and Load OpenGL Functions glfwMakeContextCurrent(mWindow); gladLoadGL(); fprintf(stderr, "OpenGL %s\n", glGetString(GL_VERSION)); glfwSetErrorCallback(&errorCallback); float vertices[] = { 0.0f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, }; // Create Vertex Array Object GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Create a Vertex Buffer Object and copy the vertex data to it GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); std::ifstream vertexShaderFile(PROJECT_SOURCE_DIR "/Glitter/Shaders/main.vert"); std::string vertexShaderStr((std::istreambuf_iterator<char>(vertexShaderFile)), std::istreambuf_iterator<char>()); auto vertexSource = vertexShaderStr.c_str(); // Create and compile the vertex shader GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexSource, NULL); glCompileShader(vertexShader); assertShaderCompile(vertexShader); std::ifstream fragmentShaderFile(PROJECT_SOURCE_DIR "/Glitter/Shaders/main.frag"); std::string fragmentShaderStr((std::istreambuf_iterator<char>(fragmentShaderFile)), std::istreambuf_iterator<char>()); auto fragmentSource = fragmentShaderStr.c_str(); // Create and compile the fragment shader GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentSource, NULL); glCompileShader(fragmentShader); assertShaderCompile(fragmentShader); // Link the vertex and fragment shader into a shader program GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glBindFragDataLocation(shaderProgram, 0, "outColor"); glLinkProgram(shaderProgram); std::cout << glGetError() << std::endl; glUseProgram(shaderProgram); std::cout << glGetError() << std::endl; std::cout << glGetError() << std::endl; // Specify the layout of the vertex data GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); glEnableVertexAttribArray(posAttrib); glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); std::cout << glGetError() << std::endl; // Rendering Loop while (glfwWindowShouldClose(mWindow) == false) { if (glfwGetKey(mWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(mWindow, true); // Background Fill Color glClearColor(0.25f, 0.25f, 0.25f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Draw a triangle from the 3 vertices glDrawArrays(GL_TRIANGLES, 0, 3); // Flip Buffers and Draw glfwSwapBuffers(mWindow); glfwPollEvents(); } glfwTerminate(); glDeleteProgram(shaderProgram); glDeleteShader(fragmentShader); glDeleteShader(vertexShader); glDeleteBuffers(1, &vbo); glDeleteVertexArrays(1, &vao); return EXIT_SUCCESS; }
Shader* ShaderManager::LoadShader(const string& aVertexShader, const string& aFragmentShader, vector<string> aAttributes) { //Safety check the filenames if(aVertexShader.length() == 0 || aFragmentShader.length() == 0) { Error(false, "Failed to load the shader, either the Vertex shader or fragment shader length is 0"); return nullptr; } //If the asserts are hit either the vertex shader or the fragment shader files have no length assert(aVertexShader.length() > 0); assert(aFragmentShader.length() > 0); //Check to see if they v and f are the same string key = aVertexShader == aFragmentShader ? aVertexShader : aVertexShader + aFragmentShader; //Get the pair from the texture map Shader* shader = m_ShaderMap[key]; //Is the shader pointer null? if(shader == nullptr) { //Determine if GLSL version 140 is supported by this context. //We'll use this info to generate a GLSL shader source string //with the proper version preprocessor string prepended float glLanguageVersion; if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "OpenGL ES GLSL ES %f", &glLanguageVersion); } else { sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "%f", &glLanguageVersion); } //GL_SHADING_LANGUAGE_VERSION returns the version standard version form //with decimals, but the GLSL version preprocessor directive simply //uses integers (thus 1.10 should 110 and 1.40 should be 140, etc.) //We multiply the floating point number by 100 to get a proper //number for the GLSL preprocessor directive GLuint version = (GLuint)(100 * glLanguageVersion); //Get the size of the version preprocessor string info so we know //how much memory to allocate for our sourceString GLsizei versionStringSize = sizeof("#version 123\n"); // if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { versionStringSize = sizeof("#version 123 es\n"); } //Was .vsh appended to the filename? If it was, remove it string vertexShader = string(aVertexShader); size_t found = vertexShader.find(".vsh"); if(found != std::string::npos) { vertexShader.erase(found, 4); } //Which directory do we load? bool appendVersion = true; string directory = "Shaders"; if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS && version < 300) { directory = "Shaders/ES2"; appendVersion = false; } //Get the path for the vertex shader file string vertexPath = ServiceLocator::GetPlatformLayer()->GetPathForResourceInDirectory(vertexShader.c_str(), "vsh", directory.c_str()); //Load the vertex shader File vertexShaderFile(vertexPath); //Safety check the vertex shader if(vertexShaderFile.GetBufferSize() == 0) { Error(false, "Failed to load the vertex shader"); return nullptr; } //Allocate memory for the source string including the version preprocessor information GLchar* vertexSource = nullptr; //Do we append a version to the vertex source? if(appendVersion == true) { vertexSource = (GLchar*)malloc(vertexShaderFile.GetBufferSize() + versionStringSize); //Prepend our vertex shader source string with the supported GLSL version so //the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sprintf(vertexSource, "#version %d es\n%s", version, vertexShaderFile.GetBuffer()); } else { sprintf(vertexSource, "#version %d\n%s", version, vertexShaderFile.GetBuffer()); } } else { vertexSource = (GLchar*)malloc(vertexShaderFile.GetBufferSize()); sprintf(vertexSource, "%s", vertexShaderFile.GetBuffer()); } //Was .fsh appended to the filename? If it was, remove it string fragmentShader = string(aFragmentShader); found = fragmentShader.find(".fsh"); if(found != std::string::npos) { fragmentShader.erase(found, 4); } //Get the path for the fragment shader file string fragmentPath = ServiceLocator::GetPlatformLayer()->GetPathForResourceInDirectory(fragmentShader.c_str(), "fsh", directory.c_str()); //Load the fragment shader File fragmentShaderFile(fragmentPath); //Safety check the fragment shader if(fragmentShaderFile.GetBufferSize() == 0) { Error(false, "Failed to load the fragment shader"); return nullptr; } //Allocate memory for the source string including the version preprocessor information GLchar* fragmentSource = nullptr; //Do we append a version to the fragment source? if(appendVersion == true) { fragmentSource = (GLchar*)malloc(fragmentShaderFile.GetBufferSize() + versionStringSize); //Prepend our fragment shader source string with the supported GLSL version so //the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sprintf(fragmentSource, "#version %d es\n%s", version, fragmentShaderFile.GetBuffer()); } else { sprintf(fragmentSource, "#version %d\n%s", version, fragmentShaderFile.GetBuffer()); } } else { fragmentSource = (GLchar*)malloc(fragmentShaderFile.GetBufferSize()); sprintf(fragmentSource, "%s", fragmentShaderFile.GetBuffer()); } //Create a new shader with the vertex and fragment shaders Shader* shader = new Shader(vertexSource, fragmentSource); shader->SetKey(key); //Cycle through the attributes and add them to the shader for(unsigned int i = 0; i < aAttributes.size(); i++) { shader->AddAttribute(aAttributes.at(i).c_str()); } //Link the shader shader->Link(); //Set the shader map pair for the filename key m_ShaderMap[key] = shader; //Free the memory for the vertex and fragment sources free(vertexSource); free(fragmentSource); } //Return the shader object return shader; }