diff --git a/.gitignore b/.gitignore
index 9491a2f..45b0c8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -360,4 +360,5 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
-FodyWeavers.xsd
\ No newline at end of file
+FodyWeavers.xsd
+/FinalProject/temp/shaders
diff --git a/FinalProject/FinalProject.vcxproj.filters b/FinalProject/FinalProject.vcxproj.filters
index 77dd024..20d5f67 100644
--- a/FinalProject/FinalProject.vcxproj.filters
+++ b/FinalProject/FinalProject.vcxproj.filters
@@ -157,10 +157,10 @@
-
+
Resource Files
-
+
Resource Files
diff --git a/FinalProject/ebo.cpp b/FinalProject/ebo.cpp
index a76f2ec..68bb938 100644
--- a/FinalProject/ebo.cpp
+++ b/FinalProject/ebo.cpp
@@ -1,33 +1,35 @@
#pragma once
#include "ebo.h"
+#include "logger.h"
ElementBufferObject::ElementBufferObject() {
- OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+ _id = 0;
}
-ElementBufferObject::ElementBufferObject(const std::vector& indices) :
- _indices(indices) {
+ElementBufferObject::ElementBufferObject(const std::vector& indices) {
OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _id);
OPENGL_EXTRA_FUNCTIONS->glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
- _indices.size() * sizeof(unsigned int),
- _indices.data(),
+ indices.size() * sizeof(unsigned int),
+ indices.data(),
GL_STATIC_DRAW
);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
-ElementBufferObject::ElementBufferObject(std::vector&& indices) :
- _indices(std::move(indices)) {
- OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+void ElementBufferObject::setBuffer(const std::vector& indices) {
+ if (_id == 0) {
+ Logger::error("Try to bind buffer to an uninitialized element buffer object");
+ return;
+ }
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _id);
OPENGL_EXTRA_FUNCTIONS->glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
- _indices.size() * sizeof(unsigned int),
- _indices.data(),
+ indices.size() * sizeof(unsigned int),
+ indices.data(),
GL_STATIC_DRAW
);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-}
+}
\ No newline at end of file
diff --git a/FinalProject/ebo.h b/FinalProject/ebo.h
index 677ad9e..dbbc4c4 100644
--- a/FinalProject/ebo.h
+++ b/FinalProject/ebo.h
@@ -6,21 +6,49 @@
class ElementBufferObject
{
+public:
+ static ElementBufferObject empty() {
+ return ElementBufferObject();
+ }
+
private:
unsigned int _id = 0;
- std::vector _indices;
+
+private:
+ ElementBufferObject();
public:
- ElementBufferObject();
ElementBufferObject(const std::vector& indices);
- ElementBufferObject(std::vector&& indices);
inline unsigned int id() const { return _id; }
- inline std::vector indices() const { return _indices; }
- inline void dispose() const;
+ inline void bind() const;
+ inline void unbind() const;
+ inline void dispose();
+ inline void ensureInitialized();
+
+ void setBuffer(const std::vector& indices);
};
-inline void ElementBufferObject::dispose() const {
+inline void ElementBufferObject::bind() const {
+ if (_id == 0) {
+ Logger::error("Binding an invalid ElementBufferObject");
+ return;
+ }
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _id);
+}
+
+inline void ElementBufferObject::unbind() const {
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}
+
+inline void ElementBufferObject::dispose() {
OPENGL_EXTRA_FUNCTIONS->glDeleteBuffers(1, &_id);
+ _id = 0;
+}
+
+inline void ElementBufferObject::ensureInitialized() {
+ if (_id == 0) {
+ OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+ }
}
\ No newline at end of file
diff --git a/FinalProject/logger.cpp b/FinalProject/logger.cpp
index 3cac4f2..56618a4 100644
--- a/FinalProject/logger.cpp
+++ b/FinalProject/logger.cpp
@@ -1,6 +1,6 @@
#pragma once
-#include "qdebug.h"
+#include
#include "logger.h"
diff --git a/FinalProject/mainwindow.qrc b/FinalProject/mainwindow.qrc
index 68043e7..89c5a99 100644
--- a/FinalProject/mainwindow.qrc
+++ b/FinalProject/mainwindow.qrc
@@ -1,4 +1,6 @@
-
+
+ fragmentshader.fs
+ vertexshader.vs
diff --git a/FinalProject/sceneviewer.cpp b/FinalProject/sceneviewer.cpp
index 598c1f2..2b123f6 100644
--- a/FinalProject/sceneviewer.cpp
+++ b/FinalProject/sceneviewer.cpp
@@ -2,6 +2,9 @@
#include
#include
+#include
+#include
+#include
#include "vbo.h"
#include "vao.h"
@@ -18,6 +21,16 @@ SceneViewer::SceneViewer(QWidget* parent)
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(4, 3);
setFormat(format);
+
+ // Create a folder
+ QDir dir("./temp/shaders");
+ if (!dir.exists()) {
+ dir.mkpath(".");
+ }
+
+ // Copy the shaders to the folder
+ QFile::copy(":/shaders/vertexshader.vs", "./temp/shaders/vertexshader.vs");
+ QFile::copy(":/shaders/fragmentshader.fs", "./temp/shaders/fragmentshader.fs");
}
SceneViewer::~SceneViewer() {
@@ -31,6 +44,17 @@ void SceneViewer::initializeGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Logger::info("Currently running on OpenGL version: " + std::string((const char*)glGetString(GL_VERSION)));
+
+ _vao.ensureInitialized();
+ Logger::info("Vertex Array Object initialized");
+
+ _shaderProgram.ensureInitialized();
+ Logger::info("Shader Program initialized");
+
+ VertexShader vertexShader("./temp/shaders/vertexshader.vs");
+ FragmentShader fragmentShader("./temp/shaders/fragmentshader.fs");
+ _shaderProgram.attachShader(vertexShader);
+
}
void SceneViewer::resizeGL(int w, int h) {
diff --git a/FinalProject/sceneviewer.h b/FinalProject/sceneviewer.h
index ebf604d..223fb9c 100644
--- a/FinalProject/sceneviewer.h
+++ b/FinalProject/sceneviewer.h
@@ -6,6 +6,7 @@
#include
+#include "shader.h"
#include "renderable.h"
#include "vao.h"
#include "utils.h"
@@ -16,6 +17,8 @@ class SceneViewer : public QOpenGLWidget, protected QOpenGLFunctions
private:
std::vector _objects;
+ ShaderProgram _shaderProgram = ShaderProgram::empty();
+ VertexArrayObject _vao = VertexArrayObject::empty();
public:
SceneViewer(QWidget* parent = 0);
diff --git a/FinalProject/shader.cpp b/FinalProject/shader.cpp
index 268e76a..5a1873d 100644
--- a/FinalProject/shader.cpp
+++ b/FinalProject/shader.cpp
@@ -102,7 +102,7 @@ void GeometryShader::compile(const std::string& source) {
}
ShaderProgram::ShaderProgram() {
- _programId = OPENGL_EXTRA_FUNCTIONS->glCreateProgram();
+ _programId = 0;
}
ShaderProgram::ShaderProgram(VertexShader vertexShader) {
diff --git a/FinalProject/shader.h b/FinalProject/shader.h
index 1e75a34..fbe9233 100644
--- a/FinalProject/shader.h
+++ b/FinalProject/shader.h
@@ -8,7 +8,7 @@
class Shader {
protected:
- unsigned int _shaderId = -1;
+ unsigned int _shaderId = 0;
public:
Shader() {}
@@ -27,7 +27,6 @@ inline void Shader::dispose() {
class VertexShader : public Shader {
public:
- VertexShader() {}
VertexShader(const std::string& sourceFilePath);
protected:
@@ -36,7 +35,6 @@ protected:
class FragmentShader : public Shader {
public:
- FragmentShader() {}
FragmentShader(const std::string& sourceFilePath);
protected:
@@ -45,7 +43,6 @@ protected:
class GeometryShader : public Shader {
public:
- GeometryShader() {}
GeometryShader(const std::string& sourceFilePath);
protected:
@@ -53,11 +50,18 @@ protected:
};
class ShaderProgram {
+public:
+ static ShaderProgram empty() {
+ return ShaderProgram();
+ }
+
private:
unsigned int _programId = 0;
-public:
+private:
ShaderProgram();
+
+public:
ShaderProgram(VertexShader vertexShader);
ShaderProgram(FragmentShader fragmentShader);
ShaderProgram(GeometryShader geometryShader);
@@ -67,19 +71,33 @@ public:
ShaderProgram(VertexShader vertexShader, FragmentShader fragmentShader, GeometryShader geometryShader);
public:
- inline void setActive();
- inline void setInactive();
-
inline unsigned int programId() const { return _programId; }
+ inline void attachShader(const Shader& shader) const;
+
+ inline void bind() const;
+ inline void unbind() const;
inline void dispose();
+ inline void ensureInitialized();
};
-inline void ShaderProgram::setActive() {
+inline void ShaderProgram::attachShader(const Shader& shader) const {
+ if (_programId == 0) {
+ Logger::error("Attaching a shader to an invalid ShaderProgram");
+ return;
+ }
+ OPENGL_EXTRA_FUNCTIONS->glAttachShader(_programId, shader.shaderId());
+}
+
+inline void ShaderProgram::bind() const {
+ if (_programId == 0) {
+ Logger::error("Binding an invalid ShaderProgram");
+ return;
+ }
OPENGL_EXTRA_FUNCTIONS->glUseProgram(_programId);
}
-inline void ShaderProgram::setInactive() {
+inline void ShaderProgram::unbind() const {
OPENGL_EXTRA_FUNCTIONS->glUseProgram(0);
}
@@ -87,3 +105,9 @@ inline void ShaderProgram::dispose() {
OPENGL_EXTRA_FUNCTIONS->glDeleteProgram(_programId);
_programId = 0;
}
+
+inline void ShaderProgram::ensureInitialized() {
+ if (_programId == 0) {
+ _programId = OPENGL_EXTRA_FUNCTIONS->glCreateProgram();
+ }
+}
diff --git a/FinalProject/vao.cpp b/FinalProject/vao.cpp
index 429a143..acb4e51 100644
--- a/FinalProject/vao.cpp
+++ b/FinalProject/vao.cpp
@@ -3,39 +3,20 @@
#include "vao.h"
VertexArrayObject::VertexArrayObject() {
- OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
+ _id = 0;
}
-VertexArrayObject::VertexArrayObject(const VertexBufferObject& vbo) :
- _vbo(vbo) {
+VertexArrayObject::VertexArrayObject(const VertexBufferObject& vbo) {
OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, vbo.id());
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
}
-VertexArrayObject::VertexArrayObject(VertexBufferObject&& vbo) :
- _vbo(std::move(vbo)) {
+VertexArrayObject::VertexArrayObject(const VertexBufferObject& vbo, const ElementBufferObject& ebo) {
OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
-}
-
-VertexArrayObject::VertexArrayObject(const VertexBufferObject& vbo, const ElementBufferObject& ebo) :
- _vbo(vbo), _ebo(ebo) {
- OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
-}
-
-VertexArrayObject::VertexArrayObject(VertexBufferObject&& vbo, ElementBufferObject&& ebo) :
- _vbo(std::move(vbo)), _ebo(std::move(ebo)) {
- OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo.id());
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, vbo.id());
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo.id());
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
}
\ No newline at end of file
diff --git a/FinalProject/vao.h b/FinalProject/vao.h
index dd0d8f8..33d19e3 100644
--- a/FinalProject/vao.h
+++ b/FinalProject/vao.h
@@ -8,27 +8,30 @@
#include "logger.h"
class VertexArrayObject {
+public:
+ static VertexArrayObject empty() {
+ return VertexArrayObject();
+ }
+
private:
unsigned int _id = 0;
- VertexBufferObject _vbo;
- ElementBufferObject _ebo;
+
+private:
+ VertexArrayObject();
public:
- VertexArrayObject();
VertexArrayObject(const VertexBufferObject& vbo);
- VertexArrayObject(VertexBufferObject&& vbo);
VertexArrayObject(const VertexBufferObject& vbo, const ElementBufferObject& ebo);
- VertexArrayObject(VertexBufferObject&& vbo, ElementBufferObject&& ebo);
inline unsigned int id() const { return _id; }
-
+
inline void bind() const;
inline void unbind() const;
+ inline void dispose();
+ inline void ensureInitialized();
inline void bindVertexBufferObject(const VertexBufferObject& vbo);
- inline void bindVertexBufferObject(VertexBufferObject&& vbo);
inline void bindElementBufferObject(const ElementBufferObject& ebo);
- inline void bindElementBufferObject(ElementBufferObject&& ebo);
inline void setVertexAttributePointer(unsigned int index, int size, unsigned int type, bool normalized, unsigned int stride, const void* pointer) const;
inline void enableVertexAttribute(unsigned int index) const;
@@ -37,7 +40,7 @@ public:
inline void VertexArrayObject::bind() const {
// Check is id is valid
- if (_id == -1) {
+ if (_id == 0) {
Logger::error("Binding an invalid VertexArrayObject");
return;
}
@@ -48,31 +51,26 @@ inline void VertexArrayObject::unbind() const {
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
}
-inline void VertexArrayObject::bindVertexBufferObject(const VertexBufferObject& vbo) {
- _vbo = vbo;
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
+inline void VertexArrayObject::dispose() {
+ OPENGL_EXTRA_FUNCTIONS->glDeleteVertexArrays(1, &_id);
+ _id = 0;
}
-inline void VertexArrayObject::bindVertexBufferObject(VertexBufferObject&& vbo) {
- _vbo = std::move(vbo);
+inline void VertexArrayObject::ensureInitialized() {
+ if (_id == 0) {
+ OPENGL_EXTRA_FUNCTIONS->glGenVertexArrays(1, &_id);
+ }
+}
+
+inline void VertexArrayObject::bindVertexBufferObject(const VertexBufferObject& vbo) {
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _vbo.id());
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, vbo.id());
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
}
inline void VertexArrayObject::bindElementBufferObject(const ElementBufferObject& ebo) {
- _ebo = ebo;
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo.id());
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
-}
-
-inline void VertexArrayObject::bindElementBufferObject(ElementBufferObject&& ebo) {
- _ebo = std::move(ebo);
- OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(_id);
- OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo.id());
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo.id());
OPENGL_EXTRA_FUNCTIONS->glBindVertexArray(0);
}
diff --git a/FinalProject/vbo.cpp b/FinalProject/vbo.cpp
index 9f24404..e3b990f 100644
--- a/FinalProject/vbo.cpp
+++ b/FinalProject/vbo.cpp
@@ -1,33 +1,35 @@
#pragma once
#include "vbo.h"
+#include "logger.h"
VertexBufferObject::VertexBufferObject() {
- OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+ _id = 0;
}
-VertexBufferObject::VertexBufferObject(const std::vector& vertices) :
- _vertices(vertices) {
+VertexBufferObject::VertexBufferObject(const std::vector& vertices) {
OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _id);
OPENGL_EXTRA_FUNCTIONS->glBufferData(
GL_ARRAY_BUFFER,
- _vertices.size() * sizeof(Vertex),
- _vertices.data(),
+ vertices.size() * sizeof(Vertex),
+ vertices.data(),
GL_STATIC_DRAW
);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, 0);
}
-VertexBufferObject::VertexBufferObject(std::vector&& vertices) :
- _vertices(std::move(vertices)) {
- OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+void VertexBufferObject::setBuffer(const std::vector& vertices) {
+ if (id == 0) {
+ Logger::error("Try to bind buffer to an uninitialized vertex buffer object");
+ return;
+ }
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _id);
OPENGL_EXTRA_FUNCTIONS->glBufferData(
GL_ARRAY_BUFFER,
- _vertices.size() * sizeof(Vertex),
- _vertices.data(),
+ vertices.size() * sizeof(Vertex),
+ vertices.data(),
GL_STATIC_DRAW
);
OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
+}
\ No newline at end of file
diff --git a/FinalProject/vbo.h b/FinalProject/vbo.h
index 75daad2..5ec7082 100644
--- a/FinalProject/vbo.h
+++ b/FinalProject/vbo.h
@@ -6,21 +6,49 @@
#include "utils.h"
class VertexBufferObject {
+public:
+ static VertexBufferObject empty() {
+ return VertexBufferObject();
+ }
+
private:
unsigned int _id = 0;
- std::vector _vertices;
-public:
+private:
VertexBufferObject();
+
+public:
VertexBufferObject(const std::vector& vertices);
- VertexBufferObject(std::vector&& vertices);
inline unsigned int id() const { return _id; }
- inline std::vector vertices() const { return _vertices; }
- inline void dispose() const;
+ inline void bind() const;
+ inline void unbind() const;
+ inline void dispose();
+ inline void ensureInitialized();
+
+ void setBuffer(const std::vector& vertices);
};
-inline void VertexBufferObject::dispose() const {
+inline void VertexBufferObject::bind() const {
+ if (_id == 0) {
+ Logger::error("Binding an invalid VertexBufferObject");
+ return;
+ }
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, _id);
+}
+
+inline void VertexBufferObject::unbind() const {
+ OPENGL_EXTRA_FUNCTIONS->glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+inline void VertexBufferObject::dispose() {
OPENGL_EXTRA_FUNCTIONS->glDeleteBuffers(1, &_id);
+ _id = 0;
+}
+
+inline void VertexBufferObject::ensureInitialized() {
+ if (_id == 0) {
+ OPENGL_EXTRA_FUNCTIONS->glGenBuffers(1, &_id);
+ }
}
\ No newline at end of file
diff --git a/Models/backpack/ao.jpg b/Models/backpack/ao.jpg
new file mode 100644
index 0000000..11a2aee
Binary files /dev/null and b/Models/backpack/ao.jpg differ
diff --git a/Models/backpack/backpack.mtl b/Models/backpack/backpack.mtl
new file mode 100644
index 0000000..f8b974c
--- /dev/null
+++ b/Models/backpack/backpack.mtl
@@ -0,0 +1,16 @@
+# Blender MTL File: 'None'
+# Material Count: 1
+
+newmtl Scene_-_Root
+Ns 225.000000
+Ka 1.000000 1.000000 1.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.500000 0.500000 0.500000
+Ke 0.0 0.0 0.0
+Ni 1.450000
+d 1.000000
+illum 2
+map_Kd diffuse.jpg
+map_Bump normal.png
+map_Ks specular.jpg
+
diff --git a/Models/backpack/diffuse.jpg b/Models/backpack/diffuse.jpg
new file mode 100644
index 0000000..e971a33
Binary files /dev/null and b/Models/backpack/diffuse.jpg differ
diff --git a/Models/backpack/normal.png b/Models/backpack/normal.png
new file mode 100644
index 0000000..3a8a103
Binary files /dev/null and b/Models/backpack/normal.png differ
diff --git a/Models/backpack/roughness.jpg b/Models/backpack/roughness.jpg
new file mode 100644
index 0000000..9f50e67
Binary files /dev/null and b/Models/backpack/roughness.jpg differ
diff --git a/Models/backpack/source_attribution.txt b/Models/backpack/source_attribution.txt
new file mode 100644
index 0000000..a704b4a
--- /dev/null
+++ b/Models/backpack/source_attribution.txt
@@ -0,0 +1,3 @@
+Model by Berk Gedik, from: https://sketchfab.com/3d-models/survival-guitar-backpack-low-poly-799f8c4511f84fab8c3f12887f7e6b36
+
+Modified material assignment (Joey de Vries) for easier load in OpenGL model loading chapter, and renamed albedo to diffuse and metallic to specular to match non-PBR lighting setup.
\ No newline at end of file
diff --git a/Models/backpack/specular.jpg b/Models/backpack/specular.jpg
new file mode 100644
index 0000000..1fd675a
Binary files /dev/null and b/Models/backpack/specular.jpg differ