Last active
November 1, 2018 17:12
-
-
Save ankitpriyarup/9af42108d4485fa92bebb078ae92051c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <GL/glew.h> | |
#include <GLFW/glfw3.h> | |
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <sstream> | |
//We need a shader to see what's drawn | |
//Two major type of shader - Vertex shader & Frament or Pixel Shader other types also | |
//Vertex shader task is to specify positioning based on the rendering screen | |
//Our screen is like an array of pixels so we need to get which position we are using that is job of vertex shader | |
//then Fragment shader tells which pixel has which value like colour then finally rasterization step occurs which | |
//draws the pixel. | |
//If a shader draws a triangle which fills in like thouasnds of pixels so we are not supposed to have calculations which can | |
//be abstracted otherwise it will be unnecessarily gets repeated. Fragment shaders will be called thousand times then vertex shader | |
//however will be called three times here based on the vertices given. | |
//Data sent from cpu to shader (gpu) through vertex buffer in reverse through uniform | |
struct ShaderProgramSource | |
{ | |
std::string VertexShader; | |
std::string FragmentShader; | |
}; | |
static ShaderProgramSource ParseShader(const std::string &filepath) | |
{ | |
enum class ShaderType | |
{ | |
NONE = -1, VERTEX = 0, FRAGMENT = 1 | |
}; | |
std::ifstream stream(filepath); | |
std::stringstream ss[2]; | |
std::string line; | |
ShaderType type = ShaderType::NONE; | |
while (getline(stream, line)) | |
{ | |
if (line.find("#shader") != std::string::npos) | |
{ | |
if (line.find("vertex") != std::string::npos) | |
type = ShaderType::VERTEX; | |
else if (line.find("fragment") != std::string::npos) | |
type = ShaderType::FRAGMENT; | |
} | |
else | |
ss[(int)type] << line << "\n"; | |
} | |
return{ ss[0].str(), ss[1].str() }; | |
} | |
static unsigned int CompileShader(unsigned int type, const std::string &source) | |
{ | |
unsigned int id = glCreateShader(type); | |
const char* src = source.c_str(); | |
glShaderSource(id, 1, &src, nullptr); | |
glCompileShader(id); | |
//Error Handling | |
int result; | |
glGetShaderiv(id, GL_COMPILE_STATUS, &result); | |
if (result == GL_FALSE) | |
{ | |
int length; | |
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); | |
//char message[length]; | |
//gives an error because length is not constant so to avoid error and still allocate on stack | |
char* message = (char*)alloca(length * sizeof(char)); | |
glGetShaderInfoLog(id, length, &length, message); | |
std::cout << "Failed to compile " << | |
(type == GL_VERTEX_SHADER ? "vertex" : "fragment") << | |
std::endl; | |
std::cout << message << std::endl; | |
glDeleteShader(id); | |
return 0; | |
} | |
return id; | |
} | |
static unsigned int CreateShader(const std::string &vertexShader, const std::string &fragmentShader) | |
{ | |
unsigned int program = glCreateProgram(); | |
unsigned int vertShader = CompileShader(GL_VERTEX_SHADER, vertexShader); | |
unsigned int fragShader = CompileShader(GL_FRAGMENT_SHADER, fragmentShader); | |
glAttachShader(program, vertShader); | |
glAttachShader(program, fragShader); | |
glLinkProgram(program); | |
glValidateProgram(program); | |
glDeleteShader(vertShader); | |
glDeleteShader(fragShader); | |
//Detach function takes trivial amount of memory so not adviced | |
//But deleting shader won't allow to debug it | |
return program; | |
} | |
int main(void) | |
{ | |
GLFWwindow* window; | |
if (!glfwInit()) | |
return -1; | |
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); | |
if (!window) | |
{ | |
glfwTerminate(); | |
return -1; | |
} | |
glfwMakeContextCurrent(window); | |
if (glewInit() != GLEW_OK) | |
std::cout << "Error!" << std::endl; | |
std::cout << glGetString(GL_VERSION) << std::endl; | |
float positions[6] = | |
{ | |
-0.5f, -0.5, | |
0.0f, 0.5f, | |
0.5f, -0.5f | |
}; | |
unsigned int buffer; | |
glGenBuffers(1, &buffer); | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), &positions, GL_STATIC_DRAW); | |
glEnableVertexAttribArray(0); | |
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); | |
//In shaders | |
//location 0 is the id of the glVertexAttributePointer | |
//Here we are casting position to a vec4 instead of vec2 because gl_position takes in a vector4 and implicit casting will occur | |
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader"); | |
unsigned int shader = CreateShader(source.VertexShader, source.FragmentShader); | |
glUseProgram(shader); | |
while (!glfwWindowShouldClose(window)) | |
{ | |
glClear(GL_COLOR_BUFFER_BIT); | |
glDrawArrays(GL_TRIANGLES, 0, 3); | |
glfwSwapBuffers(window); | |
glfwPollEvents(); | |
} | |
glDeleteProgram(shader); | |
glfwTerminate(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment