Skip to content

Instantly share code, notes, and snippets.

@ryosuzuki
Last active December 1, 2016 20:04
Show Gist options
  • Save ryosuzuki/682a193a53abf3c8080c20447535b433 to your computer and use it in GitHub Desktop.
Save ryosuzuki/682a193a53abf3c8080c20447535b433 to your computer and use it in GitHub Desktop.
#include "opengl.h"
void OpenGL::initBuffers() {
glGenVertexArrays(1, &vaoMesh);
glBindVertexArray(vaoMesh);
glGenBuffers(1, &vboVertices);
glGenBuffers(1, &vboNormals);
glGenBuffers(1, &vboUVs);
glGenBuffers(1, &vboFaces);
glGenBuffers(1, &vboAmbient);
glGenBuffers(1, &vboDiffuse);
glGenBuffers(1, &vboSpecular);
}
void OpenGL::freeBuffers() {
glDeleteVertexArrays(1, &vaoMesh);
glDeleteBuffers(1, &vboVertices);
glDeleteBuffers(1, &vboNormals);
glDeleteBuffers(1, &vboUVs);
glDeleteBuffers(1, &vboFaces);
glDeleteBuffers(1, &vboAmbient);
glDeleteBuffers(1, &vboDiffuse);
glDeleteBuffers(1, &vboSpecular);
}
void OpenGL::setMesh(const Mesh &mesh) {
vertices = (mesh.vertices.transpose()).cast<float>();
normals = (mesh.normals.transpose()).cast<float>();
faces = (mesh.faces.transpose()).cast<unsigned>();
uvs = (mesh.uvs.transpose()).cast<float>();
ambient = (mesh.ambient.transpose()).cast<float>();
diffuse = (mesh.diffuse.transpose()).cast<float>();
specular = (mesh.specular.transpose()).cast<float>();
}
void OpenGL::bindMesh() {
glBindVertexArray(vaoMesh);
shaderMesh.bind();
shaderMesh.bindVertexAttribArray("position", vboVertices, vertices, true);
shaderMesh.bindVertexAttribArray("normal", vboNormals, normals, true);
shaderMesh.bindVertexAttribArray("Ka", vboAmbient, ambient, true);
shaderMesh.bindVertexAttribArray("Kd", vboDiffuse, diffuse, true);
shaderMesh.bindVertexAttribArray("Ks", vboSpecular, specular, true);
shaderMesh.bindVertexAttribArray("texcoord", vboUVs, uvs, true);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboFaces);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned)*faces.size(), faces.data(), GL_DYNAMIC_DRAW);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, vboTextures);
// glUniform1i(shaderMesh.uniform("tex"), 0);
}
void OpenGL::drawMesh(bool solid) {
glPolygonMode(GL_FRONT_AND_BACK, solid ? GL_FILL : GL_LINE);
if (solid) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
}
glDrawElements(GL_TRIANGLES, 3*faces.cols(), GL_UNSIGNED_INT, 0);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void OpenGL::init() {
std::string meshVertexShaderString =
"#version 150\n"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 proj;"
"in vec3 position;"
"in vec3 normal;"
"out vec3 position_eye;"
"out vec3 normal_eye;"
"in vec3 Ka;"
"in vec3 Kd;"
"in vec3 Ks;"
"in vec2 texcoord;"
"out vec2 texcoordi;"
"out vec3 Kai;"
"out vec3 Kdi;"
"out vec3 Ksi;"
"void main()"
"{"
" position_eye = vec3 (view * model * vec4 (position, 1.0));"
" normal_eye = vec3 (view * model * vec4 (normal, 0.0));"
" normal_eye = normalize(normal_eye);"
" gl_Position = proj * vec4 (position_eye, 1.0);" //proj * view * model * vec4(position, 1.0);"
" Kai = Ka;"
" Kdi = Kd;"
" Ksi = Ks;"
" texcoordi = texcoord;"
"}";
std::string meshFragmentShaderString =
"#version 150\n"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 proj;"
"uniform vec4 fixed_color;"
"in vec3 position_eye;"
"in vec3 normal_eye;"
"uniform vec3 light_position_world;"
"vec3 Ls = vec3 (1, 1, 1);"
"vec3 Ld = vec3 (1, 1, 1);"
"vec3 La = vec3 (1, 1, 1);"
"in vec3 Ksi;"
"in vec3 Kdi;"
"in vec3 Kai;"
"in vec2 texcoordi;"
"uniform sampler2D tex;"
"uniform float specular_exponent;"
"uniform float lighting_factor;"
"uniform float texture_factor;"
"out vec4 outColor;"
"void main()"
"{"
"vec3 Ia = La * Kai;" // ambient intensity
"vec3 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));"
"vec3 vector_to_light_eye = light_position_eye - position_eye;"
"vec3 direction_to_light_eye = normalize (vector_to_light_eye);"
"float dot_prod = dot (direction_to_light_eye, normal_eye);"
"float clamped_dot_prod = max (dot_prod, 0.0);"
"vec3 Id = Ld * Kdi * clamped_dot_prod;" // Diffuse intensity
"vec3 reflection_eye = reflect (-direction_to_light_eye, normal_eye);"
"vec3 surface_to_viewer_eye = normalize (-position_eye);"
"float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);"
"dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);"
"float specular_factor = pow (dot_prod_specular, specular_exponent);"
"vec3 Is = Ls * Ksi * specular_factor;" // specular intensity
"vec4 color = vec4(lighting_factor * (Is + Id) + Ia, 1.0) + vec4((1.0-lighting_factor) * Kdi,1.0);"
"outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;"
"if (fixed_color != vec4(0.0)) outColor = fixed_color;"
"}";
initBuffers();
shaderMesh.init(meshVertexShaderString, meshFragmentShaderString, "outColor");
}
void OpenGL::free() {
shaderMesh.free();
freeBuffers();
}
#pragma once
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include "mesh.h"
#include "shader.h"
class OpenGL {
public:
Shader shaderMesh;
GLuint vaoMesh;
GLuint vboVertices;
GLuint vboNormals;
GLuint vboUvs;
GLuint vboAmbient;
GLuint vboDiffuse;
GLuint vboSpecular;
GLuint vboFaces;
Eigen::MatrixXf vertices;
Eigen::MatrixXf normals;
Eigen::MatrixXf ambient;
Eigen::MatrixXf diffuse;
Eigen::MatrixXf specular;
Eigen::MatrixXf uvs;
Eigen::MatrixXi faces;
void init();
void initBuffers();
void setMesh(const Mesh &mesh);
void bindMesh();
void drawMesh(bool solid = true);
void free();
void freeBuffers();
};
#include "shader.h"
bool Shader::init(const std::string &vertexShaderString,
const std::string &fragmentShaderString,
const std::string &fragmentDataName,
const std::string &geometryShaderString,
int geometryShaderMaxVertices)
{
using namespace std;
vertexShader = createShaderHelper(GL_VERTEX_SHADER, vertexShaderString);
geometryShader = createShaderHelper(GL_GEOMETRY_SHADER, geometryShaderString);
fragmentShader = createShaderHelper(GL_FRAGMENT_SHADER, fragmentShaderString);
if (!vertexShader || !fragmentShader) {
return false;
}
programShader = glCreateProgram();
glAttachShader(programShader, vertexShader);
glAttachShader(programShader, fragmentShader);
if (geometryShader) {
glAttachShader(programShader, geometryShader);
/* This covers only basic cases and may need to be modified */
glProgramParameteri(programShader, GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES);
glProgramParameteri(programShader, GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLES);
glProgramParameteri(programShader, GL_GEOMETRY_VERTICES_OUT, geometryShaderMaxVertices);
}
glBindFragDataLocation(programShader, 0, fragmentDataName.c_str());
glLinkProgram(programShader);
GLint status;
glGetProgramiv(programShader, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
char buffer[512];
glGetProgramInfoLog(programShader, 512, NULL, buffer);
std::cerr << "Linker error: " << std::endl << buffer << std::endl;
programShader = 0;
return false;
}
return true;
}
void Shader::bind() {
glUseProgram(programShader);
}
GLint Shader::attrib(const std::string &name) const {
return glGetAttribLocation(programShader, name.c_str());
}
GLint Shader::uniform(const std::string &name) const {
return glGetUniformLocation(programShader, name.c_str());
}
GLint Shader::bindVertexAttribArray(const std::string &name, GLuint bufferID, const Eigen::MatrixXf &M, bool refresh) const {
GLint id = attrib(name);
if (id < 0) {
return id;
}
if (M.size() == 0) {
glDisableVertexAttribArray(id);
return id;
}
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
if (refresh) {
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*M.size(), M.data(), GL_DYNAMIC_DRAW);
}
glVertexAttribPointer(id, M.rows(), GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(id);
return id;
}
void Shader::free() {
if (programShader) {
glDeleteProgram(programShader);
programShader = 0;
}
if (vertexShader) {
glDeleteShader(vertexShader);
vertexShader = 0;
}
if (fragmentShader) {
glDeleteShader(fragmentShader);
fragmentShader = 0;
}
if (geometryShader) {
glDeleteShader(geometryShader);
geometryShader = 0;
}
}
GLuint Shader::createShaderHelper(GLint type, const std::string &shaderString) {
using namespace std;
if (shaderString.empty()) {
return (GLuint) 0;
}
GLuint id = glCreateShader(type);
const char *shaderStringConst = shaderString.c_str();
glShaderSource(id, 1, &shaderStringConst, NULL);
glCompileShader(id);
GLint status;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
char buffer[512];
if (type == GL_VERTEX_SHADER)
std::cerr << "Vertex shader:" << std::endl;
else if (type == GL_FRAGMENT_SHADER)
std::cerr << "Fragment shader:" << std::endl;
else if (type == GL_GEOMETRY_SHADER)
std::cerr << "Geometry shader:" << std::endl;
std::cerr << shaderString <<std::endl << std::endl;
glGetShaderInfoLog(id, 512, NULL, buffer);
std::cerr << "Error: " << std::endl << buffer << std::endl;
return (GLuint) 0;
}
return id;
}
#pragma once
#include <Eigen/Core>
#include <iostream>
#include <fstream>
#include <nanogui/glutil.h>
class Shader {
public:
GLuint vertexShader;
GLuint fragmentShader;
GLuint geometryShader;
GLuint programShader;
bool init(const std::string &vertexShaderString,
const std::string &fragmentShaderString,
const std::string &fragmentDataName,
const std::string &geometryShaderString = "",
int geometryShaderMaxVertices = 3);
void bind();
void free();
GLint attrib(const std::string &name) const;
GLint uniform(const std::string &name) const;
GLint bindVertexAttribArray(const std::string &name, GLuint bufferID, const Eigen::MatrixXf &M, bool refresh) const;
GLuint createShaderHelper(GLint type, const std::string &shaderString);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment