commit 1dce5a251d2c3763c237dfecbc3641845beb9739 Author: Anselme Date: Mon Jun 22 01:57:02 2015 +0200 initial commit 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