skybox prototype working, shaders now take a source instead of a filename in constructor

This commit is contained in:
Anselme 2015-06-29 23:44:50 +02:00
parent 370a073dcb
commit 3ab2ba9dcd
27 changed files with 299 additions and 127 deletions

View File

@ -23,7 +23,7 @@ class Camera
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());
Camera(int width = 800, int height = 600, float fov_y = 45, float near = 0.1f, float far = 10.0f, glm::vec3 pos = glm::vec3());
// setters
// relative:

BIN
data/skybox_bk.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
data/skybox_dn.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
data/skybox_ft.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
data/skybox_lf.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
data/skybox_rt.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
data/skybox_up.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

18
entity.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "entity.h"
#include "shader.h"
#include <glm/glm.hpp>
#include "material.h"
#include "mesh.h"
void Entity::draw(const glm::mat4 viewMatrix, const glm::mat4 projectionMatrix)
{
glm::mat4 modelViewMatrix = viewMatrix * modelMatrix;
glm::mat4 mvp = projectionMatrix * modelViewMatrix;
Shader* shader = mat->getShader();
shader->bind();
mat->bindAttributes();
shader->bindMatrix(shader->getLocation("viewMatrix"), viewMatrix);
shader->bindMatrix(shader->getLocation("modelViewMatrix"), modelViewMatrix);
shader->bindMatrix(shader->getLocation("MVP"), mvp);
mesh->draw();
}

21
entity.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef ENTITY_H
#define ENTITY_H
#include "glm/mat4x4.hpp"
class Mesh;
class Material;
class Entity
{
protected:
Entity* parent;
Mesh* mesh;
Material* mat;
glm::mat4 modelMatrix;
public:
Entity(Entity* myParent, Mesh* myMesh, Material* myMat) : parent(myParent), mesh(myMesh), mat(myMat) {}
virtual void draw(const glm::mat4 viewMatrix, const glm::mat4 projectionMatrix);
};
#endif // ENTITY_H

View File

@ -66,10 +66,7 @@ void Mesh::destroyGL()
{
locked = false;
glAssert(glDeleteVertexArrays(1, &vao));
vao = 0;
glAssert(glDeleteBuffers(2, vbo));
vbo[0] = 0;
vbo[1] = 0;
}
}

View File

@ -5,6 +5,8 @@
#include "camera.h"
#include "sphere.h"
#include "phongmaterial.h"
#include "skybox.h"
#include "utils.h"
#include <iostream>
#include <glm/glm.hpp>
#include <QKeyEvent>
@ -61,8 +63,17 @@ void MyGLWidget::buildScene()
scene->setCamera(cam);
Mesh* myGrid = new Sphere(2);
myGrid->initGL();
Shader* shader = new Shader(QString("../phong.vert"), QString("../phong.frag"));
QString vertSource = Utils::fileToString("../phong.vert");
QString fragSource = Utils::fileToString("../phong.frag");
Shader* shader = new Shader(&vertSource, &fragSource);
Material* mat = new PhongMaterial(shader);
QString filenames[6] = {
"../data/skybox_lf", "../data/skybox_rt",
"../data/skybox_up", "../data/skybox_dn",
"../data/skybox_bk", "../data/skybox_ft"
};
SkyBox* skybox = new SkyBox(filenames);
scene->addEntity(skybox);
scene->addEntity(myGrid, mat);
}

View File

@ -1,4 +1,4 @@
#version 330
#version 330 core
// material
uniform vec3 materialKd;

View File

@ -1,4 +1,4 @@
#version 330
#version 330 core
// Matrices
uniform mat4 modelViewMatrix;
@ -27,5 +27,5 @@ void main(void) {
varTexCoord = inTexCoord.xy;
// position du vertex
gl_Position = MVP*vec4(inPosition, 1.0);
gl_Position = MVP * vec4(inPosition, 1.0);
}

View File

@ -3,11 +3,7 @@
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include "camera.h"
Scene::Scene()
{
}
#include "entity.h"
Scene::~Scene()
{
@ -15,27 +11,27 @@ Scene::~Scene()
delete(e);
}
void Scene::addEntity(Entity* parent, Mesh* mesh, Material* mat)
{
entities.push_back(new Entity(parent, mesh, mat));
}
void Scene::addEntity(Mesh* mesh, Material* mat)
{
entities.push_back(new Entity(NULL, mesh, mat));
}
void Scene::addEntity(Entity* entity)
{
entities.push_back(entity);
}
void Scene::drawEntities()
{
glm::mat4 viewMatrix = camera->getViewMatrix();
glm::mat4 projectionMatrix = camera->getProjectionMatrix();
for(Entity* e : entities)
{
glm::mat4 modelViewMatrix = viewMatrix * e->modelMatrix;
glm::mat4 mvp = projectionMatrix * modelViewMatrix;
Shader* shader = e->mat->getShader();
shader->bind();
e->mat->bindAttributes();
shader->bindMatrix(shader->getLocation("viewMatrix"), viewMatrix);
shader->bindMatrix(shader->getLocation("modelViewMatrix"), modelViewMatrix);
shader->bindMatrix(shader->getLocation("MVP"), mvp);
e->mesh->draw();
}
e->draw(viewMatrix, projectionMatrix);
}
void Scene::setCamera(Camera* myCamera)

19
scene.h
View File

@ -5,31 +5,20 @@
#include "material.h"
#include <glew/glew.h>
class Entity;
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<Entity*> entities;
Camera* camera;
public:
Scene();
Scene() : camera(NULL) {}
~Scene();
void addEntity(Entity* parent, Mesh* mesh, Material* mat);
void addEntity(Mesh* mesh, Material* mat);
void addEntity(Entity* entity);
void drawEntities();
void setCamera(Camera* myCamera);
Camera* getCamera();

View File

@ -17,7 +17,7 @@ void SceneController::mouseMove(int dx, int dy)
break;
case 2:
camera->translate(glm::vec3(dx*0.01f, dy*0.01f, 0));
camera->lookAt(glm::vec3(0, 0, 0));
//camera->lookAt(glm::vec3(0, 0, 0));
break;
default:
break;

View File

@ -1,7 +1,5 @@
#include "shader.h"
#include <glew/glew.h>
#include <QFile>
#include <QTextStream>
#include <iostream>
#include "glassert.h"
#include <glm/ext.hpp>
@ -9,14 +7,12 @@
const std::string Shader::DEFAULT_VERT = "#version 330\nlayout(location = 0)in vec3 inPosition;\nvoid main(){gl_Position = vec4(inPosition, 1.0);}";
const std::string Shader::DEFAULT_FRAG = "#version 330\nlayout(location = 0)out vec4 outColor;\nvoid main(){outColor = vec4(1, 0, 0, 1);}";
Shader::Shader(const QString &vertFilename, const QString &fragFilename)
Shader::Shader(const QString* vertexSource, const QString* fragmentSource)
{
program = glAssert(glCreateProgram());
vertexSource = fileToString(vertFilename);
fragmentSource = fileToString(fragFilename);
GLuint vertexShaderId = createShader(&vertexSource, GL_VERTEX_SHADER);
GLuint fragmentShaderId = createShader(&fragmentSource, GL_FRAGMENT_SHADER);
GLuint vertexShaderId = createShader(vertexSource, GL_VERTEX_SHADER);
GLuint fragmentShaderId = createShader(fragmentSource, GL_FRAGMENT_SHADER);
glAssert(glAttachShader(program, vertexShaderId));
glAssert(glAttachShader(program, fragmentShaderId));
@ -52,17 +48,7 @@ Shader::~Shader()
glAssert(glDeleteProgram(program));
}
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* source, GLenum shaderType)
GLuint Shader::createShader(const QString* source, GLenum shaderType)
{
glAssert(GLuint shaderId = glCreateShader(shaderType));
const GLchar *data = (const GLchar *)source->toStdString().c_str();

View File

@ -11,15 +11,12 @@ class Shader
static const std::string DEFAULT_VERT;
static const std::string DEFAULT_FRAG;
GLuint program;
QString vertexSource;
QString fragmentSource;
QString fileToString(QString filename);
GLuint createShader(QString* filename, GLenum shaderType);
GLuint createShader(const QString* filename, GLenum shaderType);
void printShaderInfoLog(GLuint shaderId);
void printProgramInfoLog(GLuint programId);
public:
Shader(const QString &vertFilename, const QString &fragFilename);
Shader(const QString* vertexSource, const QString* fragmentSource);
~Shader();
GLuint getLocation(std::string attribName);

107
skybox.cpp Normal file
View File

@ -0,0 +1,107 @@
#include "skybox.h"
#include "glassert.h"
#include "shader.h"
#include "material.h"
#include "skyboxmaterial.h"
#include "glm/glm.hpp"
SkyBox::SkyBox(const QString filename[6]) : Entity(NULL, NULL, NULL)
{
Shader* shader = new Shader(&vertSource, &fragSource);
mat = new SkyBoxMaterial(shader, filename);
// set up vao
glAssert(glGenVertexArrays(1, &vao));
glAssert(glBindVertexArray(vao));
glAssert(glGenBuffers(1, &vbo));
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo));
glAssert(glBufferData(GL_ARRAY_BUFFER, 108 * sizeof(GLfloat), skyboxVertices, GL_STATIC_DRAW));
glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, NULL));
glAssert(glEnableVertexAttribArray(0));
glAssert(glBindVertexArray(0));
}
SkyBox::~SkyBox()
{
glAssert(glDeleteVertexArrays(1, &vao));
glAssert(glDeleteBuffers(1, &vbo));
}
void SkyBox::draw(const glm::mat4 viewMatrix, const glm::mat4 projectionMatrix)
{
glm::mat4 mvp = glm::mat4(glm::mat3(projectionMatrix * viewMatrix));
Shader* shader = mat->getShader();
glAssert(glDepthMask(GL_FALSE));
shader->bind();
mat->bindAttributes();
shader->bindMatrix(shader->getLocation("MVP"), mvp);
glAssert(glBindVertexArray(vao));
glAssert(glDrawArrays(GL_TRIANGLES, 0, 36));
glAssert(glDepthMask(GL_TRUE));
}
const GLfloat SkyBox::skyboxVertices[] = {
// Positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
const QString SkyBox::vertSource =
"#version 330 core\n\
layout(location = 0)in vec3 inPosition;\n\
out vec3 varTexCoord;\n\
uniform mat4 MVP;\n\
void main()\n\
{\n\
gl_Position = MVP * vec4(inPosition, 1.0);\n\
varTexCoord = inPosition;\n\
}\n";
const QString SkyBox::fragSource =
"#version 330 core\n\
in vec3 varTexCoord;\n\
out vec4 outColor;\n\
uniform samplerCube skybox;\n\
void main()\n\
{\n\
outColor = texture(skybox, varTexCoord);\n\
}\n";

23
skybox.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef SKYBOX_H
#define SKYBOX_H
#include "entity.h"
#include <glew/glew.h>
class QString;
class SkyBox : public Entity
{
private:
static const GLfloat skyboxVertices[];
static const QString vertSource;
static const QString fragSource;
GLuint vao;
GLuint vbo;
public:
SkyBox(const QString filename[6]);
~SkyBox();
virtual void draw(const glm::mat4 viewMatrix, const glm::mat4 projectionMatrix);
};
#endif // SKYBOX_H

View File

@ -1,47 +1,12 @@
#include "skyboxmaterial.h"
#include "texture.h"
SkyBoxMaterial::SkyBoxMaterial(Shader* myShader, const QString filenames[6]) : Material(myShader)
{
skyboxTex = new Texture(filenames);
}
void SkyBoxMaterial::bindAttributes()
{
for(int i=0; i<NB_TEXTURES; ++i)
{
if(skyboxTex[i] != NULL)
{
skyboxTex[i]->bind(i);
shader->bindTexture(shader->getLocation("skybox_" + getDirName((DirEnum)i)), i);
}
}
}
void SkyBoxMaterial::setTexture(Texture* myTexture, DirEnum direction)
{
skyboxTex[direction] = myTexture;
}
std::string SkyBoxMaterial::getDirName(DirEnum direction)
{
switch(direction)
{
case TOP:
return "top";
break;
case BOTTOM:
return "bottom";
break;
case LEFT:
return "left";
break;
case RIGHT:
return "right";
break;
case FRONT:
return "front";
break;
case BACK:
return "back";
break;
default:
return "undefined";
break;
}
skyboxTex->bind(0);
}

View File

@ -8,15 +8,11 @@ class Texture;
class SkyBoxMaterial : public Material
{
public:
typedef enum {TOP, BOTTOM, LEFT, RIGHT, FRONT, BACK, NB_TEXTURES} DirEnum;
SkyBoxMaterial(Shader* myShader) : Material(myShader) {}
SkyBoxMaterial(Shader* myShader, const QString filenames[6]);
virtual void bindAttributes();
void setTexture(Texture* myTexture, DirEnum direction);
std::string getDirName(DirEnum direction);
private:
Texture* skyboxTex[NB_TEXTURES];
Texture* skyboxTex;
};
#endif // SKYBOXMATERIAL_H

View File

@ -31,7 +31,10 @@ SOURCES += main.cpp\
phongmaterial.cpp \
scenecontroller.cpp \
sphere.cpp \
skyboxmaterial.cpp
skyboxmaterial.cpp \
skybox.cpp \
entity.cpp \
utils.cpp
HEADERS += mainwindow.h \
myglwidget.h \
@ -46,7 +49,10 @@ HEADERS += mainwindow.h \
phongmaterial.h \
scenecontroller.h \
sphere.h \
skyboxmaterial.h
skyboxmaterial.h \
skybox.h \
entity.h \
utils.h
FORMS += mainwindow.ui

View File

@ -2,20 +2,28 @@
#include "glassert.h"
#include <QImage>
Texture::Texture(QString filename)
Texture::Texture(const QString filename) : type(GL_TEXTURE_2D)
{
img = new QImage(filename);
int bpp = (img->depth() == 32) ? GL_RGBA : GL_RGB;
int format = (img->depth() == 32) ? GL_BGRA : GL_BGR;
glAssert(glGenTextures(1, &texId));
glAssert(glBindTexture(GL_TEXTURE_2D, texId));
glAssert(glTexImage2D(GL_TEXTURE_2D, 0, bpp, img->width(), img->height(), 0, format, GL_UNSIGNED_BYTE, img->bits()));
glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
glAssert(glBindTexture(type, texId));
createTexture(filename, GL_TEXTURE_2D);
setWrap(GL_REPEAT);
setFiltering(GL_NEAREST);
}
Texture::Texture(const QString filename[6]) : type(GL_TEXTURE_CUBE_MAP)
{
glAssert(glActiveTexture(GL_TEXTURE0));
glAssert(glGenTextures(1, &texId));
glAssert(glBindTexture(type, texId));
for(int i=0; i<6; ++i)
{
createTexture(filename[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
setWrap(GL_CLAMP_TO_EDGE);
setFiltering(GL_LINEAR);
}
}
Texture::~Texture()
@ -23,10 +31,31 @@ Texture::~Texture()
glAssert(glDeleteTextures(1, &texId));
}
void Texture::createTexture(QString filename, GLenum textureSlot)
{
QImage img(filename);
int bpp = (img.depth() == 32) ? GL_RGBA : GL_RGB;
int format = (img.depth() == 32) ? GL_BGRA : GL_BGR;
glAssert(glTexImage2D(textureSlot, 0, bpp, img.width(), img.height(), 0, format, GL_UNSIGNED_BYTE, img.bits()));
}
void Texture::setWrap(GLint wrap)
{
glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_S, wrap));
glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_T, wrap));
glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_R, wrap));
}
void Texture::setFiltering(GLint filter)
{
glAssert(glTexParameteri(type, GL_TEXTURE_MIN_FILTER, filter));
glAssert(glTexParameteri(type, GL_TEXTURE_MAG_FILTER, filter));
}
void Texture::bind(int slot)
{
GLenum texSlot = GL_TEXTURE0+slot;
glAssert(glActiveTexture(texSlot));
glAssert(glBindTexture(GL_TEXTURE_2D, texId));
glAssert(glBindTexture(type, texId));
}

View File

@ -10,10 +10,17 @@ class Texture
{
private:
GLuint texId;
QImage* img;
GLenum type;
void createTexture(QString filename, GLenum type);
void setWrap(GLint wrap);
void setFiltering(GLint filter);
public:
Texture(QString filename);
// creates a standard texture from an image
Texture(const QString filename);
// creates a cubeMap from 6 images
Texture(const QString filename[6]);
~Texture();
void bind(int slot);
};

12
utils.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "utils.h"
#include <QFile>
#include <QTextStream>
QString Utils::fileToString(const QString &filename)
{
QFile f(filename);
if(!f.open(QFile::ReadOnly | QFile::Text))
return NULL;
QTextStream in(&f);
return in.readAll();
}

12
utils.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef UTILS_H
#define UTILS_H
class QString;
class Utils
{
public:
static QString fileToString(const QString &filename);
};
#endif // UTILS_H