From 1dce5a251d2c3763c237dfecbc3641845beb9739 Mon Sep 17 00:00:00 2001 From: Anselme Date: Mon, 22 Jun 2015 01:57:02 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + camera.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++ camera.h | 46 ++++++++++++++++++ glassert.h | 24 ++++++++++ main.cpp | 11 +++++ mainwindow.cpp | 14 ++++++ mainwindow.h | 22 +++++++++ mainwindow.ui | 59 +++++++++++++++++++++++ material.cpp | 12 +++++ material.h | 12 +++++ mesh.cpp | 23 +++++++++ mesh.h | 27 +++++++++++ myglwidget.cpp | 63 +++++++++++++++++++++++++ myglwidget.h | 28 +++++++++++ phong.frag | 37 +++++++++++++++ phong.vert | 31 ++++++++++++ scene.cpp | 47 +++++++++++++++++++ scene.h | 39 +++++++++++++++ shader.cpp | 95 +++++++++++++++++++++++++++++++++++++ shader.h | 21 +++++++++ sparrowRenderer.pro | 44 +++++++++++++++++ sparrowrenderer.cpp | 35 ++++++++++++++ sparrowrenderer.h | 22 +++++++++ 23 files changed, 826 insertions(+) create mode 100644 .gitignore create mode 100644 camera.cpp create mode 100644 camera.h create mode 100644 glassert.h create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 material.cpp create mode 100644 material.h create mode 100644 mesh.cpp create mode 100644 mesh.h create mode 100644 myglwidget.cpp create mode 100644 myglwidget.h create mode 100644 phong.frag create mode 100644 phong.vert create mode 100644 scene.cpp create mode 100644 scene.h create mode 100644 shader.cpp create mode 100644 shader.h create mode 100644 sparrowRenderer.pro create mode 100644 sparrowrenderer.cpp create mode 100644 sparrowrenderer.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b81d87c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +*.user \ No newline at end of file diff --git a/camera.cpp b/camera.cpp new file mode 100644 index 0000000..da3f486 --- /dev/null +++ b/camera.cpp @@ -0,0 +1,112 @@ +#include "camera.h" + +#include +#include + +#define _USE_MATH_DEFINES + +Camera::Camera(int width, int height, float fov_y, float near, float far, glm::vec3 pos) : + m_projectionHasChanged(true), + m_viewHasChanged(true), + m_fov(fov_y), + m_width(width), + m_height(height), + m_near(near), + m_far(far), + m_position(pos), + m_rotation(glm::vec2()) +{ + computeProjectionMatrix(); + computeViewMatrix(); +} + +void Camera::computeProjectionMatrix() +{ + m_projectionMatrix = glm::perspectiveFov(m_fov, (float)m_width, (float)m_height, m_near, m_far); + m_projectionHasChanged = false; +} + +void Camera::computeViewMatrix() +{ + m_viewMatrix = glm::rotate(glm::mat4(), m_rotation.y, glm::vec3(0, 1, 0)); + m_viewMatrix = glm::rotate(m_viewMatrix, m_rotation.x, glm::vec3(1, 0, 0)); + m_viewMatrix = glm::translate(m_viewMatrix, -m_position); + m_viewHasChanged = false; +} + +void Camera::translate(glm::vec3 vector) +{ + m_viewHasChanged = true; + m_position += vector; +} + +void Camera::rotate(glm::vec2 rad_vector) +{ + m_viewHasChanged = true; + m_rotation += rad_vector; + if(m_rotation.y > M_PI/2) + m_rotation.y = M_PI/2; + if(m_rotation.y < -M_PI/2) + m_rotation.y = -M_PI/2; +} + +void Camera::zoom(float new_fov_y) +{ + m_projectionHasChanged = true; + m_fov = new_fov_y; +} + +void Camera::resize(int width, int height) +{ + m_projectionHasChanged = true; + m_width = width; + m_height = height; +} + +void Camera::setNear(float near) +{ + m_projectionHasChanged = true; + m_near = near; +} + +void Camera::setFar(float far) +{ + m_projectionHasChanged = true; + m_far = far; +} + +void Camera::moveTo(glm::vec3 position) +{ + m_viewHasChanged = true; + m_position = position; +} + +void Camera::lookAt(glm::vec3 position) +{ + m_viewHasChanged = true; + glm::vec3 delta = position - m_position; + glm::normalize(delta); + m_rotation.y = std::asin(delta.y); + m_rotation.x = std::acos(delta.z/std::acos(delta.y)); + if(delta.z < 0) m_rotation.x += M_PI; +} + +void Camera::lookAt(glm::vec2 rotation) +{ + m_viewHasChanged = true; + m_rotation = rotation; +} + +glm::mat4 Camera::getProjectionMatrix() +{ + if(m_projectionHasChanged) + computeProjectionMatrix(); + return m_projectionMatrix; +} + +glm::mat4 Camera::getViewMatrix() +{ + if(m_viewHasChanged) + computeViewMatrix(); + return m_viewMatrix; +} diff --git a/camera.h b/camera.h new file mode 100644 index 0000000..41567cf --- /dev/null +++ b/camera.h @@ -0,0 +1,46 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include +#include +#include + +class Camera +{ + bool m_projectionHasChanged; + bool m_viewHasChanged; + glm::mat4 m_projectionMatrix; + glm::mat4 m_viewMatrix; + float m_fov; + int m_width; + int m_height; + float m_near; + float m_far; + glm::vec3 m_position; + glm::vec2 m_rotation; + + void computeProjectionMatrix(); + void computeViewMatrix(); +public: + //constructor + Camera(int width = 800, int height = 600, float fov_y = 45, float near = 0.1f, float far = 20, glm::vec3 pos = glm::vec3()); + + // setters + // relative: + void translate(glm::vec3 vector); + void rotate(glm::vec2 rad_vector); + // absolute: + void zoom(float new_fov_y); + void resize(int width, int height); + void setNear(float near); + void setFar(float far); + void moveTo(glm::vec3 position); + void lookAt(glm::vec3 position); + void lookAt(glm::vec2 rotation); + + // getters + glm::mat4 getProjectionMatrix(); + glm::mat4 getViewMatrix(); +}; + +#endif // CAMERA_H diff --git a/glassert.h b/glassert.h new file mode 100644 index 0000000..645ee32 --- /dev/null +++ b/glassert.h @@ -0,0 +1,24 @@ +#ifndef GLASSERT +#define GLASSERT + +/** + * + * OpenGL error management class. + * + */ + +#include +#include + +#define STR(x) #x +#define glAssert(code) \ + code; \ +{\ + GLuint err = glGetError(); \ + if (err != GL_NO_ERROR) { \ + std::cerr<<"erreur OpenGL ("<<__FILE__<<":"<<__LINE__<<", "< + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..49d64fc --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,14 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() +{ + delete ui; +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..a3948a9 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,22 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..26e6eaa --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,59 @@ + + + MainWindow + + + + 0 + 0 + 483 + 369 + + + + MainWindow + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + 0 + 483 + 20 + + + + + + + + MyGLWidget + QOpenGLWidget +
myglwidget.h
+
+
+ + +
diff --git a/material.cpp b/material.cpp new file mode 100644 index 0000000..5590df4 --- /dev/null +++ b/material.cpp @@ -0,0 +1,12 @@ +#include "material.h" + +Material::Material() +{ + +} + +Material::~Material() +{ + +} + diff --git a/material.h b/material.h new file mode 100644 index 0000000..bdcbd63 --- /dev/null +++ b/material.h @@ -0,0 +1,12 @@ +#ifndef MATERIAL_H +#define MATERIAL_H + + +class Material +{ +public: + Material(); + ~Material(); +}; + +#endif // MATERIAL_H diff --git a/mesh.cpp b/mesh.cpp new file mode 100644 index 0000000..efd837c --- /dev/null +++ b/mesh.cpp @@ -0,0 +1,23 @@ +#include "mesh.h" + +Mesh::Mesh() +{ + +} + +void Mesh::addVertex(Vertex& v) +{ + vertices.push_back(v); +} + +void Mesh::addFace(int i1, int i2, int i3) +{ + indices.push_back(i1); + indices.push_back(i2); + indices.push_back(i3); +} + +void Mesh::draw() +{ + +} diff --git a/mesh.h b/mesh.h new file mode 100644 index 0000000..cfd79c7 --- /dev/null +++ b/mesh.h @@ -0,0 +1,27 @@ +#ifndef MESH_H +#define MESH_H + +#include +#include + +class Mesh +{ +public: + typedef struct + { + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texCoord; + } Vertex; + + Mesh(); + void addVertex(Vertex& v); + void addFace(int i1, int i2, int i3); + void draw(); + +private: + std::vector vertices; + std::vector indices; +}; + +#endif // MESH_H diff --git a/myglwidget.cpp b/myglwidget.cpp new file mode 100644 index 0000000..49f8af0 --- /dev/null +++ b/myglwidget.cpp @@ -0,0 +1,63 @@ +#include +#include "myglwidget.h" +#include "sparrowrenderer.h" +#include "glassert.h" +#include +#include + +MyGLWidget::MyGLWidget(QWidget *parent) : + QGLWidget(parent), + renderer(NULL) +{ + +} + +MyGLWidget::~MyGLWidget() +{ + if(renderer != NULL) + delete(renderer); +} + +void MyGLWidget::initializeGL() +{ + makeCurrent(); + + GLenum err = glewInit(); // init and check glew + if (GLEW_OK != err) + { + std::cerr << "Warning: glewInit failed!" << std::endl; + } + if (!GLEW_ARB_vertex_program || + !GLEW_ARB_fragment_program || + !GLEW_ARB_texture_float || + !GLEW_ARB_draw_buffers || + !GLEW_ARB_framebuffer_object) + { + std::cerr << "Warning: Shaders not supported!" << std::endl; + } + + std::cout << "OpenGL version " << glGetString(GL_VERSION) << std::endl; + std::cout << "GLSL version " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + std::cout.flush(); + + glAssert(glEnable(GL_DEPTH_TEST)); + glAssert(glEnable(GL_CULL_FACE)); + glAssert(glEnable(GL_TEXTURE_2D)); + glAssert(glViewport(0, 0, width(), height())); + + renderer = new SparrowRenderer(width(), height()); +} + +void MyGLWidget::resizeGL(int width, int height) +{ + glAssert(glViewport(0, 0, width, height)); + renderer->resize(width, height); + updateGL(); +} + +void MyGLWidget::paintGL() +{ + glAssert(glClearColor(0.60, 0.65, 0.75, 1.0)); + glAssert(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); + renderer->render(); +} diff --git a/myglwidget.h b/myglwidget.h new file mode 100644 index 0000000..f19e731 --- /dev/null +++ b/myglwidget.h @@ -0,0 +1,28 @@ +#ifndef MYGLWIDGET_H +#define MYGLWIDGET_H + +#include + +class SparrowRenderer; + +namespace Ui { +class MyGLWidget; +} + +class MyGLWidget : public QGLWidget +{ + Q_OBJECT + + SparrowRenderer* renderer; + +public: + explicit MyGLWidget(QWidget *parent = 0); + ~MyGLWidget(); + +protected: + void initializeGL(); + void resizeGL(int width, int height); + void paintGL(); +}; + +#endif // MYGLWIDGET_H diff --git a/phong.frag b/phong.frag new file mode 100644 index 0000000..4808286 --- /dev/null +++ b/phong.frag @@ -0,0 +1,37 @@ +#version 330 + +// material +uniform vec3 materialKd; +uniform vec3 materialKs; +uniform float materialNs; + +// texture +uniform sampler2D baseTexture; + +// fragment +in vec3 varNormal; +in vec2 varTexCoord; + +// resultat +layout(location = 0)out vec4 outColor; + +// -------------------- + +vec3 computeLight(in vec3 kd, in vec3 ks, in float ns, in vec3 color, in vec3 normal, in vec3 lightDir, in vec3 halfVec){ + float diffuse = 0; + float specular = 0; + + diffuse = dot(normal, lightDir); + diffuse = diffuse < 0 ? 0 : diffuse; + specular = dot(halfVec, normal); + specular = specular < 0 ? 0 : specular; + + return color*diffuse*(kd+ks*pow(specular, ns)); +} + +void main(void) { + vec3 kd = vec3(texture2D(baseTexture, varTexCoord)); + + outColor = vec4(kd, 1); +} + diff --git a/phong.vert b/phong.vert new file mode 100644 index 0000000..d56a930 --- /dev/null +++ b/phong.vert @@ -0,0 +1,31 @@ +#version 330 + +// Matrices +uniform mat4 modelViewMatrix; +uniform mat4 MVP; +uniform mat4 normalMatrix; +uniform mat4 viewMatrix; + +layout(location = 0)in vec3 inPosition; +layout(location = 1)in vec3 inNormal; +layout(location = 2)in vec4 inTexCoord; + +out vec3 varNormal; +out vec2 varTexCoord; + +/*void computeLightingVectorsInView(in vec3 posInView, in vec3 lightPosition, out vec3 lightDir, out vec3 halfVec){ + lightDir = vec3(viewMatrix*vec4(lightPosition, 1.0)) - posInView; + halfVec = normalize(lightDir - posInView); + lightDir = normalize(lightDir); +}*/ + +void main(void) { + // normales corrigées (en fonction de la vue) + varNormal = normalize(vec3(normalMatrix*vec4(inNormal,0))); + + // coordonnées de texture + varTexCoord = inTexCoord.xy; + + // position du vertex + gl_Position = MVP*vec4(inPosition, 1.0); +} diff --git a/scene.cpp b/scene.cpp new file mode 100644 index 0000000..0ac2228 --- /dev/null +++ b/scene.cpp @@ -0,0 +1,47 @@ +#include "scene.h" +#include "glassert.h" +#include +#include +#include "camera.h" + +Scene::Scene() +{ + +} + +Scene::~Scene() +{ + for(Entity* e : entities) + delete(e); +} + +void Scene::addEntity(Mesh& mesh, Material& mat) +{ + entities.push_back(new Entity(NULL, mesh, mat)); +} + +void Scene::addEntity(Mesh& mesh) +{ + Material default_material = Material(); + entities.push_back(new Entity(NULL, mesh, default_material)); +} + +void Scene::drawEntities(GLuint programId) +{ + glm::mat4 viewMatrix = camera->getViewMatrix(); + glm::mat4 projectionMatrix = camera->getProjectionMatrix(); + glAssert(GLuint viewMatrixUniform = glGetUniformLocation(programId, "viewMatrix")); + glAssert(glUniformMatrix4fv(viewMatrixUniform, 1, GL_FALSE, glm::value_ptr(viewMatrix))); + for(Entity* e : entities) + e->mesh.draw(); +} + +void Scene::setCamera(Camera* myCamera) +{ + camera = myCamera; +} + +Camera* Scene::getCamera() +{ + return camera; +} diff --git a/scene.h b/scene.h new file mode 100644 index 0000000..34b04e1 --- /dev/null +++ b/scene.h @@ -0,0 +1,39 @@ +#ifndef SCENE_H +#define SCENE_H + +#include "mesh.h" +#include "material.h" +#include + +class Camera; + +class Scene +{ + typedef struct s_entity + { + Material mat; + Mesh mesh; + s_entity* parent; + glm::mat4 modelMatrix; + s_entity(s_entity* myParent, Mesh &myMesh, Material &myMat) + { + parent = myParent; + mesh = myMesh; + mat = myMat; + } + } Entity; + + // lights + std::vector entities; + Camera* camera; +public: + Scene(); + ~Scene(); + void addEntity(Mesh& mesh, Material& mat); + void addEntity(Mesh& mesh); + void drawEntities(GLuint programId); + void setCamera(Camera* myCamera); + Camera* getCamera(); +}; + +#endif // SCENE_H diff --git a/shader.cpp b/shader.cpp new file mode 100644 index 0000000..d27bbb6 --- /dev/null +++ b/shader.cpp @@ -0,0 +1,95 @@ +#include "shader.h" +#include +#include +#include +#include +#include "glassert.h" + +Shader::Shader(const QString &vertFilename, const QString &fragFilename) +{ + program = glAssert(glCreateProgram()); + + GLuint vertexShaderId = createShader(vertFilename, GL_VERTEX_SHADER); + GLuint fragmentShaderId = createShader(fragFilename, GL_FRAGMENT_SHADER); + + glAssert(glAttachShader(program, vertexShaderId)); + glAssert(glAttachShader(program, fragmentShaderId)); + + glAssert(glBindAttribLocation(program, 0, "inPosition")); + glAssert(glBindAttribLocation(program, 1, "inNormal")); + glAssert(glBindAttribLocation(program, 2, "inTexCoord")); + + glAssert(glLinkProgram(program)); + + // check errors + GLint linked; + glAssert(glGetProgramiv(program, GL_LINK_STATUS, &linked)); + if (!linked) { + std::cerr << "Program not linked" << std::endl; + printProgramInfoLog(program); + program = 0; + } +} + +QString Shader::fileToString(QString filename) +{ + QFile f(filename); + if(!f.open(QFile::ReadOnly | QFile::Text)) + return NULL; + QTextStream in(&f); + return in.readAll(); +} + +GLuint Shader::createShader(QString filename, GLenum shaderType) +{ + QString source = fileToString(filename); + glAssert(GLuint shaderId = glCreateShader(shaderType)); + const GLchar *data = (const GLchar *)source.constData(); + glAssert(glShaderSource(shaderId, 1, &data, NULL)); + + glAssert(glCompileShader(shaderId)); + + // check errors + GLint compiled; + glAssert(glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compiled)); + if (!compiled) { + std::cerr << "[" << filename.toStdString() << "] Vertex shader not compiled : " << std::endl; + printShaderInfoLog(shaderId); + return 0; + } + else + return shaderId; +} + +void Shader::printShaderInfoLog(GLuint shaderId) +{ + int infoLogLen = 0; + int charsWritten = 0; + GLchar *infoLog; + glAssert(glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLen)); + if (infoLogLen > 0) { + infoLog = new GLchar[infoLogLen]; + glAssert(glGetShaderInfoLog(shaderId, infoLogLen, &charsWritten, infoLog)); + std::cerr << "InfoLog:" << std::endl << infoLog << std::endl; + delete [] infoLog; + } +} + +void Shader::printProgramInfoLog(GLuint programId) +{ + int infoLogLen = 0; + int charsWritten = 0; + GLchar *infoLog; + glAssert(glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLen)); + if (infoLogLen > 0) { + infoLog = new GLchar[infoLogLen]; + glAssert(glGetProgramInfoLog(programId, infoLogLen, &charsWritten, infoLog)); + std::cerr << "InfoLog:" << std::endl << infoLog << std::endl; + delete [] infoLog; + } +} + +GLuint Shader::getProgramId() +{ + return program; +} diff --git a/shader.h b/shader.h new file mode 100644 index 0000000..84cc34f --- /dev/null +++ b/shader.h @@ -0,0 +1,21 @@ +#ifndef SHADER_H +#define SHADER_H + +#include + +class QString; + +class Shader +{ + GLuint program; + QString fileToString(QString filename); + GLuint createShader(QString filename, GLenum shaderType); + void printShaderInfoLog(GLuint shaderId); + void printProgramInfoLog(GLuint programId); + +public: + Shader(const QString &vertFilename, const QString &fragFilename); + GLuint getProgramId(); +}; + +#endif // SHADER_H diff --git a/sparrowRenderer.pro b/sparrowRenderer.pro new file mode 100644 index 0000000..17b2b75 --- /dev/null +++ b/sparrowRenderer.pro @@ -0,0 +1,44 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-06-16T15:37:51 +# +#------------------------------------------------- + +QT += core gui opengl + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = sparrowRenderer +TEMPLATE = app +CONFIG += c++11 + +INCLUDEPATH += ../cpp_dependencies/include +win32 { + LIBS += -L../../cpp_dependencies/lib/win32 +} + +LIBS += -lglew32 + +SOURCES += main.cpp\ + mainwindow.cpp \ + myglwidget.cpp \ + shader.cpp \ + mesh.cpp \ + camera.cpp \ + sparrowrenderer.cpp \ + scene.cpp \ + material.cpp + +HEADERS += mainwindow.h \ + myglwidget.h \ + shader.h \ + mesh.h \ + camera.h \ + sparrowrenderer.h \ + glassert.h \ + scene.h \ + material.h + +FORMS += mainwindow.ui + +OTHER_FILES += *.frag *.vert *.glsl diff --git a/sparrowrenderer.cpp b/sparrowrenderer.cpp new file mode 100644 index 0000000..006fc51 --- /dev/null +++ b/sparrowrenderer.cpp @@ -0,0 +1,35 @@ +#include "sparrowrenderer.h" +#include "shader.h" +#include "camera.h" +#include "scene.h" +#include "glassert.h" +#include +#include + +SparrowRenderer::SparrowRenderer(int width, int height) +{ + shader = new Shader(QString("../phong.vert"), QString("../phong.frag")); + scene = new Scene(); + scene->setCamera(new Camera(width, height)); +} + +SparrowRenderer::~SparrowRenderer() +{ + delete(scene->getCamera()); + delete(shader); + delete(scene); +} + +void SparrowRenderer::resize(int width, int height) +{ + scene->getCamera()->resize(width, height); +} + +void SparrowRenderer::render() +{ + // bind shader + GLuint programId = shader->getProgramId(); + glAssert(glUseProgram(programId)); + // draw geometry + scene->drawEntities(programId); +} diff --git a/sparrowrenderer.h b/sparrowrenderer.h new file mode 100644 index 0000000..80a1999 --- /dev/null +++ b/sparrowrenderer.h @@ -0,0 +1,22 @@ +#ifndef SPARROWRENDERER_H +#define SPARROWRENDERER_H + +class Camera; +class Shader; +class Scene; + +class SparrowRenderer +{ + Shader* shader; + Scene* scene; +public: + SparrowRenderer(int width, int height); + ~SparrowRenderer(); + + void resize(int width, int height); + + // Sparrow renderer's rendering pipeline + void render(); +}; + +#endif // SPARROWRENDERER_H