void Shader::Init(const char* vertexShaderPath, const char* fragmentShaderPath) { _vertexProgram = glCreateShader(GL_VERTEX_SHADER); _fragmentProgram = glCreateShader(GL_FRAGMENT_SHADER); std::string vertexShaderText; std::string fragmentShaderText; if (!ReadShader(vertexShaderPath, vertexShaderText) || !ReadShader(fragmentShaderPath, fragmentShaderText)) { std::cerr << "Either vertex shader or fragment shader file not found." << std::endl; return; } const char* constVST = vertexShaderText.c_str(); const char* constFST = fragmentShaderText.c_str(); glShaderSource(_vertexProgram, 1, &constVST, 0); glShaderSource(_fragmentProgram, 1, &constFST, 0); glCompileShader(_vertexProgram); ValidateShader(_vertexProgram, vertexShaderPath); glCompileShader(_fragmentProgram); ValidateShader(_fragmentProgram, fragmentShaderPath); _id = glCreateProgram(); glAttachShader(_id, _vertexProgram); glAttachShader(_id, _fragmentProgram); glLinkProgram(_id); ValidateProgram(_id); }
void Shader::Compile() { Preprocessor p(m_ShaderSource, m_VsEntry, m_PsEntry, m_Defines); p.Process(m_ShaderFileName, m_ShaderPath); std::string vsCode = p.GetVSCode(); std::string psCode = p.GetPSCode(); m_VSObject = glCreateShader(GL_VERTEX_SHADER); m_FSObject = glCreateShader(GL_FRAGMENT_SHADER); GLchar const* filesVS[]{ vsCode.c_str() }; GLchar const* filesFS[]{ psCode.c_str() }; glShaderSource(m_VSObject, 1, filesVS, 0); glShaderSource(m_FSObject, 1, filesFS, 0); glCompileShader(m_VSObject); ValidateShader(m_VSObject); glCompileShader(m_FSObject); ValidateShader(m_FSObject); m_ShaderObject = glCreateProgram(); glAttachShader(m_ShaderObject, m_VSObject); glAttachShader(m_ShaderObject, m_FSObject); glLinkProgram(m_ShaderObject); ValidateProgram(m_ShaderObject); m_Compiled = true; }
// Same as above but for not-separated build GLuint GSShaderOGL::CompileShader(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel) { ASSERT(glsl_h_code != NULL); GLuint shader = 0; // Note it is better to separate header and source file to have the good line number // in the glsl compiler report const int shader_nb = 3; const char* sources[shader_nb]; std::string header = GenGlslHeader(entry, type, macro_sel); sources[0] = header.c_str(); sources[1] = common_header_glsl; sources[2] = glsl_h_code; shader = glCreateShader(type); glShaderSource(shader, shader_nb, sources, NULL); glCompileShader(shader); bool status = ValidateShader(shader); if (!status) { // print extra info fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), shader); fprintf(stderr, "\n%s", macro_sel.c_str()); fprintf(stderr, "\n"); } m_shad_to_delete.push_back(shader); return shader; }
GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel) { ASSERT(glsl_h_code != NULL); GLuint program = 0; #ifndef ENABLE_GLES if (type == GL_GEOMETRY_SHADER && !GLLoader::found_geometry_shader) { return program; } #endif // Note it is better to separate header and source file to have the good line number // in the glsl compiler report const char* sources[2]; std::string header = GenGlslHeader(entry, type, macro_sel); int shader_nb = 1; #if 1 sources[0] = header.c_str(); sources[1] = glsl_h_code; shader_nb++; #else sources[0] = header.append(glsl_h_code).c_str(); #endif if (GLLoader::found_GL_ARB_separate_shader_objects) { #ifndef ENABLE_GLES program = gl_CreateShaderProgramv(type, shader_nb, sources); #endif } else { program = gl_CreateShader(type); gl_ShaderSource(program, shader_nb, sources, NULL); gl_CompileShader(program); } bool status; if (GLLoader::found_GL_ARB_separate_shader_objects) status = ValidateProgram(program); else status = ValidateShader(program); if (!status) { // print extra info fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), program); fprintf(stderr, "\n%s", macro_sel.c_str()); fprintf(stderr, "\n"); } return program; }
//Since we're precompiling the shaders, we dont need all the extra parameters //Assume this is a function within the renderer thus we have access to private render members Shader* CreateShader( const std::string& name, const std::string& vsFile, const std::string& psFile, const std::string& gsFile = "") { Shader newShader = new Shader(name); ID3D11ShaderReflection *vsReflect(nullptr); ID3D11ShaderReflection *psReflect(nullptr); ID3D11ShaderReflection *gsReflect(nullptr); if(!vsFile.empty()) { auto vsFileRes = new WhaleFile(vsFile); if(!vsFileRes) { log_sxerror("Shader", "Error opening VS file %s. Cannot continue", vsFile.c_str()); delete newShader; return nullptr; } auto vsFilePtr = vsFileRes->GetMem(); HRESULT result = device->CreateVertexShader(vsFilePtr, vsFileRes.Size(), NULL, &newShader->vertexShader); if(FAILED(result)) { log_sxerror("Shader", "Could not create Vertex shader from %s. Cannot continue!", vsFile.c_str()); //Clean up after ourselves before returning delete vsFileRes; delete newShader; return nullptr; } //Grab the input signature from the vertex shader result = D3DGetInputSignatureBlob(vsFilePtr, vsFileRes.Size(), &newShader->inputSignature); if(FAILED(result)) { log_sxerror("Shader", "Could not get Input signature from %s. Cannot continue!", vsFile.c_str()); delete vsFileRes; delete newShader; return nullptr; } result = D3DReflect(vsFilePtr, vsFileRes.Size(), IID_ID3D11ShaderReflection, (void **)&vsReflect); if(FAILED(result)) { log_sxerror("Shader", "Could not get Reflection Interface from %s. Cannot continue!", vsFile.c_str()); delete vsFileRes; delete newShader; return nullptr; } delete vsFileRes; } if(!psFile.empty()) { auto psFileRes = new WhaleFile(psFile); if(!psFileRes) { log_sxerror("Shader", "Error opening PS file %s. Cannot continue!", psFile.c_str()); delete newShader; SAFE_RELEASE(vsReflect); return nullptr; } auto psFilePtr = psFileRes->GetMem(); HRESULT result = device->CreatePixelShader(psFilePtr, psFileRes.Size(), NULL, &newShader->pixelShader); if(FAILED(result)) { log_sxerror("Shader", "Could not create Pixel shader from %s. Cannot continue!", psFile.c_str()); delete psFileRes; SAFE_RELEASE(vsReflect); delete newShader; return nullptr; } result = D3DReflect(psFilePtr, psFileRes.Size(), IID_ID3D11ShaderReflection, (void **)&psReflect); if(FAILED(result)) { log_sxerror("Shader", "Could not get Reflection Interface from %s. Cannot continue!", psFile.c_str()); delete psFileRes; SAFE_RELEASE(vsReflect); delete newShader; return nullptr; } delete psFileRes; } if(!gsFile.empty()) { auto gsFileRes = new WhaleFile(gsFile); if(!gsFileRes) { log_sxerror("Shader", "Error opening PS file %s. Cannot continue!", gsFile.c_str()); delete newShader; SAFE_RELEASE(vsReflect); return nullptr; } auto gsFilePtr = gsFileRes->GetMem(); HRESULT result = device->CreatePixelShader(gsFilePtr, gsFileRes.Size(), NULL, &newShader->geometryShader); if(FAILED(result)) { log_sxerror("Shader", "Could not create Pixel shader from %s. Cannot continue!", gsFile.c_str()); delete gsFileRes; SAFE_RELEASE(vsReflect); SAFE_RELEASE(psReflect); delete newShader; return nullptr; } result = D3DReflect(gsFilePtr, gsFileRes.Size(), IID_ID3D11ShaderReflection, (void **)&gsReflect); if(FAILED(result)) { log_sxerror("Shader", "Could not get Reflection Interface from %s. Cannot continue!", gsFile.c_str()); delete gsFileRes; SAFE_RELEASE(psReflect); SAFE_RELEASE(vsReflect); delete newShader; return nullptr; } delete gsFileRes; } bool res = GenerateShaderConstants(newShader, vsReflect, psReflect, gsReflect); if(!res) { log_sxerror("Shader", "Error Generating shader constants for shader %s.", name.c_str()); SAFE_RELEASE(vsReflect); SAFE_RELEASE(psReflect); SAFE_RELEASE(gsReflect); delete newShader; return nullptr; } res = GenerateShaderSamplers(newShader, vsReflect, psReflect, gsReflect); if(!res) { log_sxerror("Shader", "Error Generating shader samplers for shader %s.", name.c_str()); SAFE_RELEASE(vsReflect); SAFE_RELEASE(psReflect); SAFE_RELEASE(gsReflect); delete newShader; return nullptr; } res = ValidateShader(newShader, vsReflect, psReflect, gsReflect); if(!res) { log_sxerror("Shader", "Error validating shader %s", name.c_str()); delete newShader; newShader = nullptr; } SAFE_RELEASE(vsReflect); SAFE_RELEASE(psReflect); SAFE_RELEASE(gsReflect); return newShader; }
int main() { try { // Camera settings Camera camera; glm::vec3 vrp(0.0f, 0.0f, 10.0f); glm::vec3 vpn(0.0f, 0.0f, 1.0f); glm::vec3 vup(0.0f, 1.0f, 0.0f); glm::vec3 prp(0.0f, 0.0f, 100.0f); float F = 10.0f; float B = -80.0f; glm::vec2 lower_left(-20.0f, -20.0f); glm::vec2 upper_right(20.0f, 20.0f); camera = Camera(vrp, vpn, vup, prp, lower_left, upper_right, F, B); // Examples int curves = 4; // Amount of examples BezierRow G[curves]; G[0] = BezierRow(glm::vec3(-15.0f, -15.0f, 0.0f), glm::vec3(-10.0f, 25.0f, 0.0f), glm::vec3(10.0f, 25.0f, 0.0f), glm::vec3(15.0f, -15.0f, 0.0f)); G[1] = BezierRow(glm::vec3(-20.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 55.0f, 0.0f), glm::vec3(1.0f, -55.0f, 0.0f), glm::vec3(20.0f, 0.0f, 0.0f)); G[2] = BezierRow(glm::vec3(-1.0f, -5.0f, 0.0f), glm::vec3(-60.0f, 5.0f, 0.0f), glm::vec3(60.0f, 5.0f, 0.0f), glm::vec3(1.0f, -5.0f, 0.0f)); G[3] = BezierRow(glm::vec3(-10.0f, -5.0f, 0.0f), glm::vec3(60.0f, 5.0f, 0.0f), glm::vec3(-60.0f, 5.0f, 0.0f), glm::vec3(10.0f, -5.0f, 0.0f)); int currentfigure = 3; // Set figure between 4 different examples // Decide whether to use sampling or subdivision int decider = 1; int Npoint = 0; std::vector<glm::vec3> points; // Sampling if(decider == 0){ float t = 0.0f; float step = 12.0f; sampling(G[currentfigure], t, step, points); Npoint = step*2; } // Subdivision else if(decider == 1){ DLB /= 8.0f; DRB /= 8.0f; int n = 3; // Amount of curves (smoothness) int npow = pow(2, n+1); // Amount of points subdivide(G[currentfigure], n, points); Npoint = npow; } else{ printf("No method chosen\n"); return 1; } glm::mat4x4 CTM = camera.CurrentTransformationMatrix(); std::cout << "CTM = " << std::endl << CTM << std::endl; // Initialize the graphics InitializeGLFW(); GLFWwindow* Window = CreateWindow(WindowWidth, WindowHeight, WindowTitle.c_str()); InitializeGLEW(); InitializeOpenGL(); glfwSwapBuffers(Window); // Read and Compile the vertex program vertextransform.vert GLuint vertexprogID = CreateGpuProgram("vertextransform.vert", GL_VERTEX_SHADER); // Read and Compile the fragment program linefragment.frag GLuint linefragmentprogID = CreateGpuProgram("linefragment.frag", GL_FRAGMENT_SHADER); // Create a lineshader program and Link it with the vertex and linefragment programs GLuint lineshaderID = CreateShaderProgram(vertexprogID, linefragmentprogID); // Now comes the OpenGL core part // This is where the curve is initialized // User data is in the global variable curveVertices, and the number of entries // is in Ncurvevertices // Make a VertexArrayObject - it is used by the VertexArrayBuffer, and it must be declared! GLuint CurveVertexArrayID; glGenVertexArrays(1, &CurveVertexArrayID); glBindVertexArray(CurveVertexArrayID); // Make a curvevertexbufferObject - it uses the previous VertexArrayBuffer! GLuint curvevertexbuffer; glGenBuffers(1, &curvevertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, curvevertexbuffer); // Give our vertices to OpenGL. glBufferData(GL_ARRAY_BUFFER, Npoint * 3 * sizeof(float), &points[0], GL_STATIC_DRAW); // Validate the shader program ValidateShader(lineshaderID, "Validating the lineshader"); // Get locations of Uniforms GLuint curvevertextransform = glGetUniformLocation(lineshaderID, "CTM"); GLuint curvefragmentcolor = glGetUniformLocation(lineshaderID, "Color"); // Initialize Attributes GLuint curvevertexattribute = glGetAttribLocation(lineshaderID, "VertexPosition"); glVertexAttribPointer(curvevertexattribute, 3, GL_FLOAT, GL_FALSE, 0, 0); // The main loop while (!glfwWindowShouldClose(Window)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(lineshaderID); glm::mat4x4 CTM = camera.CurrentTransformationMatrix(); glUniformMatrix4fv(curvevertextransform, 1, GL_FALSE, &CTM[0][0]); glUniform3f(curvefragmentcolor, 0.2f, 0.2f, 0.2f); glEnableVertexAttribArray(curvevertexattribute); glBindVertexArray(CurveVertexArrayID); // This is very important! There are two "binds"! glDrawArrays(GL_LINES, 0, Npoint); glDisableVertexAttribArray(curvevertexattribute); glUseProgram(0); glfwSwapBuffers(Window); std::stringstream errormessage; errormessage << "End of loop: " << "assignment5.cpp" << ": " << __LINE__ << ": "; ErrorCheck(errormessage.str()); glfwPollEvents(); } } catch (std::exception const& exception) { std::cerr << "Exception: " << exception.what() << std::endl; } glfwTerminate(); return 0; }
bool InitializeShader(Shader_T *s, const char *vsfile, const char *fsfile) { bool success = true; GLuint vertexShader; GLuint fragmentShader; GLint vShaderCompiled = GL_FALSE; GLint fShaderCompiled = GL_FALSE; GLint programSuccess = GL_TRUE; GLchar *txt; unsigned long len; //Generate program s->id = glCreateProgram(); s->vertex_attrib = -1; s->uv_attrib = -1; //Create vertex shader vertexShader = glCreateShader( GL_VERTEX_SHADER ); //Set vertex source LoadShaderSource(vsfile, &txt, &len); glShaderSource( vertexShader, 1, &txt, NULL ); //Compile vertex source glCompileShader( vertexShader ); ValidateShader(vertexShader, vsfile); UnloadShaderSource(&txt); //Check vertex shader for errors glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &vShaderCompiled ); if( vShaderCompiled != GL_TRUE ) { printf( "Unable to compile vertex shader %d!\n", vertexShader ); printShaderLog( vertexShader ); success = false; } else { //Attach vertex shader to program glAttachShader( s->id, vertexShader ); //Create fragment shader LoadShaderSource(fsfile, &txt, &len); fragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); //Set fragment source glShaderSource( fragmentShader, 1, &txt, NULL ); //Compile fragment source glCompileShader( fragmentShader ); ValidateShader(fragmentShader, fsfile); UnloadShaderSource(&txt); //Check fragment shader for errors glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled ); if( fShaderCompiled != GL_TRUE ) { printf( "Unable to compile fragment shader %d!\n", fragmentShader ); printShaderLog( fragmentShader ); success = false; } else { //Attach fragment shader to program glAttachShader( s->id, fragmentShader ); //Link program glLinkProgram( s->id ); //Check for errors glGetProgramiv( s->id, GL_LINK_STATUS, &programSuccess ); if( programSuccess != GL_TRUE ) { printf( "Error linking program %d!\n", s->id ); printProgramLog( s->id ); success = false; } else { //Get vertex attribute location s->uv_attrib = glGetAttribLocation( s->id, "vertexUV" ); s->vertex_attrib = glGetAttribLocation( s->id, "vertexPosition" ); if( s->vertex_attrib == -1 ) { printf( "vertexPosition is not a valid glsl program variable!\n" ); success = false; } if(s->uv_attrib == -1 ) { printf( "vertexTex is not a valid glsl program variable!\n" ); success = false; } } } } return success; }