Last active
November 1, 2018 17:15
-
-
Save ankitpriyarup/e7d7c8077f34fb9c73b2e1ce5b9c83a8 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> | |
//To get data from cpu to gpu attribute is passed through buffer however there is another way to do so by uniform | |
//Attributes are per vertex used whereas uniforms are used per draw calls | |
#define ASSERT(x) if (!(x)) __debugbreak(); | |
#define GLCall(x) GLClearError();\ | |
x;\ | |
ASSERT(GLLogCall(#x, __FILE__, __LINE__)) | |
static void GLClearError() | |
{ | |
while (glGetError() != GL_NO_ERROR); | |
} | |
static bool GLLogCall(const char* function, const char* program, int line) | |
{ | |
while (GLenum error = glGetError()) | |
{ | |
std::cout << "[OpenGL Error] (" << error << ") : " << program << " : " << line << std::endl; | |
return false; | |
} | |
return true; | |
} | |
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); | |
int result; | |
glGetShaderiv(id, GL_COMPILE_STATUS, &result); | |
if (result == GL_FALSE) | |
{ | |
int length; | |
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); | |
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); | |
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); | |
glfwSwapInterval(1); | |
if (glewInit() != GLEW_OK) | |
std::cout << "Error!" << std::endl; | |
std::cout << glGetString(GL_VERSION) << std::endl; | |
float positions[] = | |
{ | |
-0.5f, -0.5, | |
0.5f, -0.5f, | |
0.5f, 0.5f, | |
-0.5f, 0.5f | |
}; | |
unsigned int indices[] = | |
{ | |
0, 1, 2, | |
2, 3, 0 | |
}; | |
unsigned int buffer; | |
GLCall(glGenBuffers(1, &buffer)); | |
GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer)); | |
GLCall(glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), &positions, GL_STATIC_DRAW)); | |
GLCall(glEnableVertexAttribArray(0)); | |
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0)); | |
unsigned int ibo; | |
GLCall(glGenBuffers(1, &buffer)); | |
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer)); | |
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), &indices, GL_STATIC_DRAW)); | |
ShaderProgramSource source = ParseShader("res/shaders/Basic2.shader"); | |
unsigned int shader = CreateShader(source.VertexShader, source.FragmentShader); | |
GLCall(glUseProgram(shader)); | |
//location may return -1 if say shader is not using it then it will get strip so hence -1 will be returned | |
int location = glGetUniformLocation(shader, "u_Color"); | |
ASSERT(location != -1) | |
GLCall(glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f)); | |
float r = 0.8f; | |
float increment = 0.01f; | |
while (!glfwWindowShouldClose(window)) | |
{ | |
GLCall(glClear(GL_COLOR_BUFFER_BIT)); | |
GLCall(glUniform4f(location, r, 0.3f, 0.8f, 1.0f)); | |
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)); | |
r += increment; | |
if (r >= 1.0f || r <= 0.0f) | |
increment *= -1; | |
glfwSwapBuffers(window); | |
glfwPollEvents(); | |
} | |
GLCall(glDeleteProgram(shader)); | |
glfwTerminate(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment