Browse Source

level loading and reloading

master
alistair 3 years ago
parent
commit
2ef006445e
  1. 60
      data/levels/init.json
  2. 2
      src/CMakeLists.txt
  3. 1
      src/compile_commands.json
  4. 46
      src/defaultobjects/cubemap.cpp
  5. 11
      src/defaultobjects/cubemap.h
  6. 126
      src/drawing.cpp
  7. 73
      src/drawing.h
  8. 10
      src/entity.h
  9. 57
      src/glutil.cpp
  10. 15
      src/glutil.h
  11. 179
      src/level.cpp
  12. 62
      src/level.h
  13. 511
      src/main.cpp
  14. 10
      src/mesh.cpp
  15. 4
      src/mesh.h
  16. 8
      src/shaders.h

60
data/levels/init.json

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
{
"name": "init",
"staticmodels": {
"backpack": {
"object": "backpack.obj",
"textures": ["ao.jpg", "diffuse.jpg", "roughness.jpg", "normal.jpg", "specular.jpg"]
}
},
"shaders": [
["instanced.vert", "test.frag"]
],
"skyboxes": [
"skybox"
],
"lights": [
{
"type": "point",
"position": [0,5,0],
"direction": [1,0,1],
"ambient": [0.9,0.0,0.0],
"diffuse": [0.9,0.3,0.5],
"specular": [1,1,1],
"attenuate": true,
"attenuation": [0.9,0.09,0.032]
},
{
"type": "point",
"position": [0,-4,0],
"direction": [1,0,1],
"ambient": [0.0,0.0,0.0],
"diffuse": [0.9,0.9,0.9],
"specular": [1,1,1],
"attenuate": true,
"attenuation": [0.9,0.09,0.032]
}
],
"entities": [
{
"draw": {"model": "backpack"},
"physics": {
"position": [1,4,1],
"orientation": [0,2,0]
}
},
{
"draw": {"model": "backpack"},
"physics": {
"position": [1,1,1],
"orientation": [1,2,0]
}
},
{
"draw": {"model": "backpack"},
"physics": {
"position": [9,2,2],
"orientation": [1,0,0]
}
}
]
}

2
src/CMakeLists.txt

@ -12,6 +12,8 @@ include_directories(${GLEW_INCLUDE_DIRS}) @@ -12,6 +12,8 @@ include_directories(${GLEW_INCLUDE_DIRS})
file(GLOB testgamefiles
"*.h"
"*.cpp"
"*/*.cpp"
"*/*.h"
)
add_executable(testgame ${testgamefiles})

1
src/compile_commands.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
[]

46
src/defaultobjects/cubemap.cpp

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
#include "cubemap.h"
#include <GL/glew.h>
#include <GL/glu.h>
#include "../stb_image.h"
#include "../errors.h"
#include "../glutil.h"
#include <fmt/core.h>
Cubemap::Cubemap(std::vector<std::string> texture_faces) {
/* faces must be provided in the order:
*
* right, left, top, bottom, front, back
*/
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(false);
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
for (unsigned int i = 0; i < texture_faces.size(); i++) {
unsigned char *data = stbi_load(texture_faces[i].c_str(),
&width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glCheckError();
stbi_image_free(data);
} else {
A_ERROR(fmt::format("Load cubemap face {}\n", texture_faces[i]));
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}

11
src/defaultobjects/cubemap.h

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
#include <vector>
#include <string>
class Cubemap {
public:
unsigned int id;
Cubemap(std::vector<std::string> texture_faces) ;
};

126
src/drawing.cpp

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
#include "drawing.h"
#include "glutil.h"
// class simple_object_draw_system : public drawing_object_handle {
simple_object_draw_system::simple_object_draw_system(Shader *shader) : shader(shader) {}
int simple_object_draw_system::add(std::shared_ptr<Model> model, glm::vec3 position, glm::mat4 orientation) {
objects.push_back({position, orientation, model});
return objects.size() - 1;
}
void simple_object_draw_system::remove(int i) {
do_not_draw.insert(i);
}
void simple_object_draw_system::return_to_draw_list(int i) {
do_not_draw.erase(i);
}
void simple_object_draw_system::draw(int i, const glm::mat4 view, const glm::mat4 projection) {
shader->use();
int loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
auto obj = objects[i];
loc = shader->get_uniform("model");
glCheckError();
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(obj.orientation));
glCheckError();
printProgramLog(shader->program);
auto this_view = glm::translate(view, obj.position);
loc = shader->get_uniform("view");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(this_view));
glCheckError();
obj.model->draw(shader);
glCheckError();
}
void simple_object_draw_system::draw(const glm::mat4 view, const glm::mat4 projection) {
glCheckError();
shader->use();
glCheckError();
int loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
glCheckError();
int i = 0;
for (auto obj: objects) {
glCheckError();
int loc = shader->get_uniform("model");
glCheckError();
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(obj.orientation));
glCheckError();
auto this_view = glm::translate(view, obj.position);
loc = shader->get_uniform("view");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(this_view));
glCheckError();
obj.model->draw(shader);
glCheckError();
}
}
/* Draw a lot of the same object. */
instanced_drawing::instanced_drawing (Model *model, Shader *shader, std::vector<object> obj_models)
: models(obj_models), model(model), shader(shader)
{}
instanced_drawing::instanced_drawing (Model *model, Shader *shader)
: model(model), shader(shader)
{}
int instanced_drawing::finalize () {
glGenBuffers(1, &instance_VBO);
glBindBuffer(GL_ARRAY_BUFFER, instance_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(object) * models.size(), &models[0], GL_STATIC_DRAW);
glVertexAttribPointer(3,3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), NULL);
glVertexAttribPointer(5,16, GL_FLOAT, GL_FALSE, 16 * sizeof(float), (void *)offsetof(object, model));
glVertexAttribDivisor(3,1);
glVertexAttribDivisor(5,1);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(5);
return 0;
}
int instanced_drawing::add(glm::vec3 position, glm::mat4 orientation) {
models.push_back({position, orientation});
return models.size() - 1;
}
void instanced_drawing::draw(const glm::mat4 view, const glm::mat4 projection) {
shader->use();
int loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
glDrawArraysInstanced(GL_TRIANGLES, 0,36,1000);
}

73
src/drawing.h

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
#pragma once
#include <memory>
#include <glm/glm.hpp>
#include "mesh.h"
#include <set>
#include "glutil.h"
#include <GL/glu.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// handles shaders, models, meshes for drawing a collection of similar objects
class drawing_object_handle {
public:
virtual void draw(const glm::mat4 view, const glm::mat4 projection) = 0;
virtual void draw(int i, const glm::mat4 view, const glm::mat4 projection) = 0;
};
class simple_object_draw_system : public drawing_object_handle {
Shader *shader;
struct object {
glm::vec3 position;
glm::mat4 orientation;
std::shared_ptr<Model> model;
};
public:
std::vector<object> objects;
std::set<int> do_not_draw;
simple_object_draw_system(Shader *shader);
int add(std::shared_ptr<Model> model, glm::vec3 position, glm::mat4 orientation);
void remove(int i);
void return_to_draw_list(int i);
void draw(int i, const glm::mat4 view, const glm::mat4 projection) override;
void draw(const glm::mat4 view, const glm::mat4 projection) override;
};
/* Draw a lot of the same object. */
class instanced_drawing : public drawing_object_handle {
public:
struct object {
glm::vec3 position;
glm::mat4 model;
};
private:
std::vector<object> models;
Model *model;
Shader *shader;
unsigned int instance_VBO;
public:
instanced_drawing (Model *model, Shader *shader, std::vector<object> obj_models);
instanced_drawing (Model *model, Shader *shader);
int finalize ();
int add(glm::vec3 position, glm::mat4 orientation);
void draw(const glm::mat4 view, const glm::mat4 projection) override;
};

10
src/entity.h

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
#pragma once
// entity slug
struct entity {
int id;
int physics;
int model;
int light;
};

57
src/glutil.cpp

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
#include "glutil.h"
GLenum glCheckError_(const char *file, int line)
{
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
}
fmt::print("error::gl {} | {} {}\n", error, file, line);
}
return errorCode;
}
void printProgramLog( GLuint program )
{
//Make sure name is shader
if( glIsProgram( program ) )
{
//Program loglength
int infoLogLength = 0;
int maxLength = infoLogLength;
//Get info string length
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &maxLength );
//Allocate string
char* infoLog = new char[ maxLength ];
//Get info log
glGetProgramInfoLog( program, maxLength, &infoLogLength, infoLog );
if( infoLogLength > 0 )
{
//Print Log
fmt::print( "{}\n", infoLog );
}
//Deallocate string
delete[] infoLog;
}
else
{
fmt::print( "Name {} is not a program\n", program );
}
}

15
src/glutil.h

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
#pragma once
#define glCheckError() glCheckError_(__FILE__, __LINE__)
#include <GL/glew.h>
#include <string>
#include <iostream>
#include <fmt/core.h>
GLenum glCheckError_(const char *file, int line);
GLenum glCheckError_(const char *file, int line);
void printProgramLog( GLuint program );

179
src/level.cpp

@ -1,19 +1,168 @@ @@ -1,19 +1,168 @@
#include <vector>
#include "level.h"
class level {
int id;
std::vector<int> models;
std::vector<int> phys_meshes;
std::vector<int> sounds;
std::vector<int> static_models;
std::vector<int> lights;
#define DIRECTIONAL_LIGHT 0
#define POINT_LIGHT 1
#define SPOT_LIGHT 2
auto LIGHT_TYPES = std::unordered_map<std::string, unsigned int> {{"directional", 0}, {"point", 1}, {"spot", 2}};
void update_lights(Shader * shader, json &j) {
int i = 0;
for (auto &l: j["lights"]) {
if (i >= 9) {
A_ERROR("More than max lights defined");
}
glCheckError();
shader->setInt(fmt::format("lights[{}].type", i), LIGHT_TYPES.at(l["type"]));
glCheckError();
shader->setVec3(fmt::format("lights[{}].position", i),glm::vec3(l["position"][0],l["position"][1], l["position"][2]));
glCheckError();
shader->setVec3(fmt::format("lights[{}].ambient", i), glm::vec3(l["ambient"][0],l["ambient"][1], l["ambient"][2]));
glCheckError();
shader->setVec3(fmt::format("lights[{}].diffuse", i), glm::vec3(l["diffuse"][0],l["diffuse"][1], l["diffuse"][2]));
glCheckError();
shader->setVec3(fmt::format("lights[{}].specular", i), glm::vec3(l["specular"][0],l["specular"][1], l["specular"][2]));
glCheckError();
shader->setBool(fmt::format("lights[{}].attenuate", i), l["attenuate"]);
glCheckError();
shader->setVec3(fmt::format("lights[{}].attenuation", i), glm::vec3(l["attenuation"][0],l["attenuation"][1], l["attenuation"][2]));
glCheckError();
i++;
}
shader->setInt("num_lights", i);
glCheckError();
}
void level::load_entities(json j) {
int i = 0;
for (auto &m: j["entities"]) {
entity e {};
e.id = i++;
bool model = false;
bool physics = false;
if (m.count("draw")) {
if (m["draw"].count("model")) {
model = true;
e.model = model_ids.at(m["draw"].at("model"));
}
}
if (m.count("physics")) {
auto p = m["physics"];
physics = true;
glm::vec3 position {p["position"][0], p["position"][1], p["position"][2]};
glm::mat4 orientation = glm::mat4(1.0); // identity matrix
orientation = glm::rotate(orientation, (float)p["orientation"][0], glm::vec3(1,0,0));
orientation = glm::rotate(orientation, (float)p["orientation"][1], glm::vec3(0,1,0));
orientation = glm::rotate(orientation, (float)p["orientation"][2], glm::vec3(0,0,1));
physics_model entity_physics {.pos = position, .orientation = orientation};
int model_id = phys_meshes.size();
phys_meshes.emplace_back(entity_physics);
e.physics = model_id;
}
if (model && physics) {
auto phys = phys_meshes.at(e.physics);
auto model = models.at(e.model);
draw_system->add(model, phys.pos, phys.orientation);
} else {
fmt::print("warn::level inivisible entity");
}
entities.push_back(e);
i++;
}
}
level::level(const std::string &json_source)
{
json l;
json_source_file = json_source;
std::ifstream inp (json_source);
inp >> l;
fmt::print("loading level{}", l["name"]);
if (l == nullptr) {
A_ERROR("level | failed to parse json");
}
// main shader should be first
for (auto &s : l["shaders"]) {
if (s.size() > 1) {
shaders.emplace_back(fmt::format("{}/{}",SHADER_DIR , s[0]), fmt::format("{}/{}", SHADER_DIR , s[1]));
} else if (s.size() > 0) {
shaders.emplace_back(fmt::format("{}/{}",SHADER_DIR , s[0])) ;
}
}
if (l.size() <= 0) {
A_ERROR("level | no shader");
}
shader = &shaders[0];
shader->use();
draw_system = simple_object_draw_system(&shaders[0]);
stbi_set_flip_vertically_on_load(true);
for (auto & [key, v] : l["staticmodels"].items()) {
models.emplace_back(new Model(fmt::format("{}/{}/{}", OBJ_DIR, key, v["object"])));
int mid = models.size() - 1;
model_ids.insert({key, mid});
}
stbi_set_flip_vertically_on_load(false);
load_entities(l);
update_lights(shader, l);
// shader->setVec3("material.specular", glm::vec3(0.7));
// glCheckError();
// shader->setVec3("material.diffuse", glm::vec3(1.0, 0.7, 0.8));
// glCheckError();
// shader->setVec3("material.ambient", glm::vec3(0.2));
// glCheckError();
// shader->setFloat("material.shininess", 32.0);
// glCheckError();
}
void level::update() {
for (auto &s: shaders) {
s.reload();
}
json l;
try {
std::ifstream inp (json_source_file);
inp >> l;
} catch (std::exception &e) {
A_WARN("Failed to reload");
return;
}
shader->use();
update_lights(shader, l);
entities.clear();
draw_system->objects.clear();
load_entities(l);
}
public:
level();
level fromjson();
void activate();
void deactivate();
~level();
};

62
src/level.h

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
#include <vector>
#include <memory>
#include <unordered_map>
#include <optional>
#include <memory>
#include <nlohmann/json.hpp>
#include <unordered_map>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <fmt/core.h>
#include <fstream>
#include "stb_image.h"
using json = nlohmann::json;
#include "mesh.h"
#include "drawing.h"
#include "entity.h"
#include "errors.h"
#include "drawing.h"
#pragma once
static const char * DATA_DIR = "data";
static const char * OBJ_DIR = "data/objects";
static const char * SHADER_DIR = "data/shaders";
static const char * SKYBOX_DIR = "data/objects/cubemaps";
// for convenience
struct physics_model {
glm::vec3 pos;
glm::mat4 orientation;
};
class level {
void load_entities(json j);
public:
int id;
std::unordered_map<std::string, int> model_ids;
Shader *shader;
std::string json_source_file;
std::vector<physics_model> phys_meshes;
std::vector<int> sounds;
std::vector<std::shared_ptr<Model>> models;
std::vector<Shader> shaders;
std::vector<int> lights;
std::optional<simple_object_draw_system> draw_system {};
std::vector<entity> entities;
// level();
level(const std::string &json);
void update();
void activate();
void deactivate();
~level() = default;
level(level &&) = default;
};

511
src/main.cpp

@ -21,259 +21,19 @@ @@ -21,259 +21,19 @@
#include <stack>
#include <set>
#include <fmt/core.h>
#include <optional>
#include "shaders.h"
#include "mesh.h"
#include "stb_image.h"
#include "glerror.h"
#include "errors.h"
#include "glutil.h"
#include "defaultobjects/cubemap.h"
#include "drawing.h"
#include "level.h"
const char * DATA_DIR = "data";
const char * OBJ_DIR = "data/objects";
const char * SHADER_DIR = "data/shaders";
const char * SKYBOX_DIR = "data/objects/cubemaps";
GLenum glCheckError_(const char *file, int line)
{
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
}
std::cerr << error << " | " << file << " (" << line << ")" << std::endl;
}
return errorCode;
}
class Cubemap {
public:
unsigned int id;
Cubemap(std::vector<std::string> texture_faces) {
/* faces must be provided in the order:
*
* right, left, top, bottom, front, back
*/
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(false);
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
for (unsigned int i = 0; i < texture_faces.size(); i++) {
unsigned char *data = stbi_load(texture_faces[i].c_str(),
&width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB,
width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glCheckError();
stbi_image_free(data);
} else {
A_ERROR(fmt::format("Load cubemap face {}\n", texture_faces[i]));
stbi_image_free(data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
};
// handles shaders, models, meshes for drawing a collection of similar objects
class drawing_object_handle {
public:
virtual void draw(const glm::mat4 view, const glm::mat4 projection) = 0;
};
class simple_object_draw_system : public drawing_object_handle {
Shader *shader;
struct object {
glm::vec3 position;
glm::mat4 orientation;
Model model;
};
std::vector<object> objects;
std::set<int> do_not_draw;
public:
simple_object_draw_system(Shader *shader) : shader(shader) {}
int add(Model model, glm::vec3 position, glm::mat4 orientation) {
objects.push_back({position, orientation, model});
return objects.size() - 1;
}
void remove(int i) {
do_not_draw.insert(i);
}
void return_to_draw_list(int i) {
do_not_draw.erase(i);
}
void draw(const glm::mat4 view, const glm::mat4 projection) override {
shader->use();
int loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
int i = 0;
for (auto obj: objects) {
if (do_not_draw.count(i++)) {
continue;
}
int loc = shader->get_uniform("model");
glCheckError();
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(obj.orientation));
glCheckError();
auto this_view = glm::translate(view, obj.position);
loc = shader->get_uniform("view");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(this_view));
glCheckError();
obj.model.draw(*shader);
glCheckError();
}
}
};
/* Draw a lot of the same object. */
class instanced_drawing : public drawing_object_handle {
public:
struct object {
glm::vec3 position;
glm::mat4 model;
};
private:
std::vector<object> models;
Model *model;
Shader *shader;
unsigned int instance_VBO;
public:
instanced_drawing (Model *model, Shader *shader, std::vector<object> obj_models)
: models(obj_models), model(model), shader(shader)
{}
instanced_drawing (Model *model, Shader *shader)
: model(model), shader(shader)
{}
int finalize () {
glGenBuffers(1, &instance_VBO);
glBindBuffer(GL_ARRAY_BUFFER, instance_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(object) * models.size(), &models[0], GL_STATIC_DRAW);
glVertexAttribPointer(3,3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), NULL);
glVertexAttribPointer(5,16, GL_FLOAT, GL_FALSE, 16 * sizeof(float), (void *)offsetof(object, model));
glVertexAttribDivisor(3,1);
glVertexAttribDivisor(5,1);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(5);
return 0;
}
int add(glm::vec3 position, glm::mat4 orientation) {
models.push_back({position, orientation});
return models.size() - 1;
}
void draw(const glm::mat4 view, const glm::mat4 projection) override {
shader->use();
int loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
glDrawArraysInstanced(GL_TRIANGLES, 0,36,1000);
}
};
class drawing_system {
std::vector<drawing_object_handle *> draw_systems;
public:
void add_system(drawing_object_handle *obj) {
draw_systems.push_back(obj);
}
void run (void) {
for (auto a : draw_systems) {
}
}
};
void printProgramLog( GLuint program )
{
//Make sure name is shader
if( glIsProgram( program ) )
{
//Program loglength
int infoLogLength = 0;
int maxLength = infoLogLength;
//Get info string length
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &maxLength );
//Allocate string
char* infoLog = new char[ maxLength ];
//Get info log
glGetProgramInfoLog( program, maxLength, &infoLogLength, infoLog );
if( infoLogLength > 0 )
{
//Print Log
printf( "%s\n", infoLog );
}
//Deallocate string
delete[] infoLog;
}
else
{
printf( "Name %d is not a program\n", program );
}
}
class SDLGLGLWindow {
@ -312,15 +72,16 @@ class SDLGLGLWindow { @@ -312,15 +72,16 @@ class SDLGLGLWindow {
private:
public:
level * running_level;
Shader *shader;
Shader *modelShader;
Shader *texShader;
Shader *skyboxShader;
Model *bp_model;
Shader *modelShader;
Shader *skyboxShader;
Shader *texShader;
int skybox_object;
int screen_width;
int screen_height;
unsigned int framebuffer;
@ -413,28 +174,114 @@ class SDLGLGLWindow { @@ -413,28 +174,114 @@ class SDLGLGLWindow {
std::cerr << "Creating msbuffers"
<< SDL_GetError() << std::endl ;
// now we can load level
fmt::print("loading level\n");
running_level = new level(("data/levels/init.json"));
//Initialize OpenGL
if( !initGL() )
{
std::cerr << "Unable to initialie OpenGL!" << std::endl;
return false;
}
shader = &running_level->shaders[0];
initGL();
// init_level();
glEnable(GL_MULTISAMPLE);
glGetError();
// shader = &running_level->shaders[0];
return true;
}
/* assumes level is loaded */
int init_level() {
/*
* Basic Shaders
*
*/
texShader = new Shader("data/shaders/screentexture.vert", "data/shaders/screentexture.frag");
skyboxShader = new Shader("data/shaders/sky.vert", "data/shaders/sky.frag");
bool success = true;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
/* MSAA FRAMEBUFFERS */
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// create a multisampled color attachment texture
glGenTextures(1, &textureColorBufferMultiSampledHDR);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampledHDR);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, screen_width, screen_height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampledHDR, 0);
// create a (also multisampled) renderbuffer object for depth and stencil attachments
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, screen_width, screen_height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// configure second post-processing framebuffer
glGenFramebuffers(1, &intermediateFBO);
glBindFramebuffer(GL_FRAMEBUFFER, intermediateFBO);
// create a color attachment texture
glGenTextures(1, &screenTexture);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen_width, screen_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0); // we only need a color buffer
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Intermediate framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glEnable(GL_BLEND);
/********** CUBEMAPS ***************/
std::vector<std::string> faces {
fmt::format("{}/sky/right.png", SKYBOX_DIR),
fmt::format("{}/sky/left.png",SKYBOX_DIR),
fmt::format("{}/sky/up.png",SKYBOX_DIR),
fmt::format("{}/sky/down.png",SKYBOX_DIR),
fmt::format("{}/sky/front.png",SKYBOX_DIR),
fmt::format("{}/sky/back.png",SKYBOX_DIR),
};
Cubemap c (faces);
cubemap = c.id;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
}
int initGL() {
//Success flag
bool success = true;
//Generate program
shader = new Shader("data/shaders/test.vert", "data/shaders/test.frag");
modelShader = new Shader("data/shaders/test.vert", "data/shaders/test.frag");
//shader = new Shader("data/shaders/instanced.vert", "data/shaders/test.frag");
modelShader = new Shader("data/shaders/instanced.vert", "data/shaders/test.frag");
texShader = new Shader("data/shaders/screentexture.vert", "data/shaders/screentexture.frag");
skyboxShader = new Shader("data/shaders/sky.vert", "data/shaders/sky.frag");
glCheckError();
@ -442,17 +289,23 @@ class SDLGLGLWindow { @@ -442,17 +289,23 @@ class SDLGLGLWindow {
objects = new simple_object_draw_system(shader);
//modelShader->use();
stbi_set_flip_vertically_on_load(true);
objects->add(Model(fmt::format("{}/backpack/backpack.obj", OBJ_DIR)), {0,0,0}, glm::mat4(1.0));
// objects->add(new Model(fmt::format("{}/backpack/backpack.obj", OBJ_DIR)), {0,0,0}, glm::mat4(1.0));
stbi_set_flip_vertically_on_load(false);
// auto un = objects->add(Model(fmt::format("{}/untitled/untitled.obj", OBJ_DIR)), {10,0,0}, glm::mat4(1.0));
// objects->remove(un);
// skybox_object = un;
// objects->add(Model(fmt::format("{}/round/round.obj", OBJ_DIR)), {0,-5,0}, glm::mat4(1.0));
objects->add(Model(fmt::format("{}/round/round.obj", OBJ_DIR)), {0,-5,0}, glm::mat4(1.0));
//Link program
stbi_set_flip_vertically_on_load(true);
//modelShader->use();
bp_model = new Model(fmt::format("{}/backpack/backpack.obj", OBJ_DIR));
// bp_model = new Model(fmt::format("{}/backpack/backpack.obj", OBJ_DIR));
glCheckError();
//shader->use();
@ -708,12 +561,12 @@ class SDLGLGLWindow { @@ -708,12 +561,12 @@ class SDLGLGLWindow {
/********** CUBEMAPS ***************/
std::vector<std::string> faces {
fmt::format("{}/sky/right.jpg", SKYBOX_DIR),
fmt::format("{}/sky/left.jpg",SKYBOX_DIR),
fmt::format("{}/sky/top.jpg",SKYBOX_DIR),
fmt::format("{}/sky/bottom.jpg",SKYBOX_DIR),
fmt::format("{}/sky/front.jpg",SKYBOX_DIR),
fmt::format("{}/sky/back.jpg",SKYBOX_DIR),
fmt::format("{}/sky/right.png", SKYBOX_DIR),
fmt::format("{}/sky/left.png",SKYBOX_DIR),
fmt::format("{}/sky/up.png",SKYBOX_DIR),
fmt::format("{}/sky/down.png",SKYBOX_DIR),
fmt::format("{}/sky/front.png",SKYBOX_DIR),
fmt::format("{}/sky/back.png",SKYBOX_DIR),
};
stbi_set_flip_vertically_on_load(false);
@ -755,9 +608,6 @@ class SDLGLGLWindow { @@ -755,9 +608,6 @@ class SDLGLGLWindow {
glEnableVertexAttribArray(0);
glBindVertexArray(quadVAO);
glCheckError();
/*********** LIGHTS ****************/
return success;
}
@ -783,74 +633,59 @@ class SDLGLGLWindow { @@ -783,74 +633,59 @@ class SDLGLGLWindow {
float timeVal = SDL_GetTicks() / 1000.0;
//Bind program
shader->use();
printProgramLog(shader->program);
glCheckError();
// shader->setInt("num_lights", 1);
// shader->setInt("lights[0].type", 1);
// shader->setFloat("lights[0].angle_cutoff", glm::cos(glm::radians(12.5f)));
// shader->setFloat("lights[0].outer_angle_cutoff", glm::cos(glm::radians(17.5f)));
//
// shader->setVec3("lights[0].direction", glm::vec3(0,-1,0));
/// shader->setVec3("lights[0].position", camera_pos);
//
// shader->setVec3("lights[0].position", lightPositions[0]);
// shader->setVec3("lights[0].ambient", glm::vec3(0.5));
// shader->setVec3("lights[0].diffuse", glm::vec3(0.9,0.7,1.0) * glm::vec3(10));
// shader->setVec3("lights[0].specular", glm::vec3(1.0));
// shader->setBool("lights[0].attenuate", false);
// shader->setVec3("lights[0].attenuation", glm::vec3(1.0, 0.09, 0.032));
//
// shader->setInt("lights[1].type", 1);
// shader->setVec3("lights[1].position", lightPositions[1]);
// shader->setVec3("lights[1].ambient", glm::vec3(0.1));
// shader->setVec3("lights[1].diffuse", glm::vec3(0.6, 0.4, 0.4));
// shader->setVec3("lights[1].specular", glm::vec3(1.0));
// shader->setBool("lights[1].attenuate", false);
// shader->setVec3("lights[1].attenuation", glm::vec3(1.0, 0.09, 0.032));
//
// shader->setInt("lights[2].type", 0);
// shader->setVec3("lights[2].position", lightPositions[1]);
//
// shader->setVec3("lights[2].ambient", glm::vec3(0.1));
// shader->setVec3("lights[2].diffuse", glm::vec3(0.3, 0.4, 0.6));
// shader->setVec3("lights[2].specular", glm::vec3(0.3, 1.0, 0.5));
// shader->setBool("lights[2].attenuate", false);
// shader->setVec3("lights[2].attenuation", glm::vec3(1.0, 0.09, 0.032));
//
shader->setVec3("material.specular", glm::vec3(0.7));
shader->setVec3("material.diffuse", glm::vec3(1.0, 0.7, 0.8));
shader->setVec3("material.ambient", glm::vec3(0.2));
shader->setFloat("material.shininess", 32);
glCheckError();
glUniform3f(glGetUniformLocation(shader->program, "cameraPosition"), camera_pos.x, camera_pos.y, camera_pos.z);
glCheckError();
/*
modelShader->setInt("num_lights", 1);
modelShader->setInt("lights[0].type", 1);
modelShader->setFloat("lights[0].angle_cutoff", glm::cos(glm::radians(12.5f)));
modelShader->setFloat("lights[0].outer_angle_cutoff", glm::cos(glm::radians(17.5f)));
modelShader->setVec3("lights[0].direction", glm::vec3(0,-1,0));
modelShader->setVec3("lights[0].position", camera_pos);
modelShader->setVec3("lights[0].ambient", glm::vec3(0.1));
modelShader->setVec3("lights[0].diffuse", glm::vec3(0.8,0.7,1.0) * glm::vec3(200));
modelShader->setVec3("lights[0].specular", glm::vec3(1.0));
modelShader->setBool("lights[0].attenuate", false);
*/
shader->setInt("num_lights", 3);
shader->setInt("lights[0].type", 1);
shader->setFloat("lights[0].angle_cutoff", glm::cos(glm::radians(12.5f)));
shader->setFloat("lights[0].outer_angle_cutoff", glm::cos(glm::radians(17.5f)));
shader->setVec3("lights[0].direction", glm::vec3(0,-1,0));
// shader->setVec3("lights[0].position", camera_pos);
shader->setVec3("lights[0].position", lightPositions[0]);
shader->setVec3("lights[0].ambient", glm::vec3(0.5));
shader->setVec3("lights[0].diffuse", glm::vec3(0.9,0.7,1.0) * glm::vec3(10));
shader->setVec3("lights[0].specular", glm::vec3(1.0));
shader->setBool("lights[0].attenuate", false);
shader->setVec3("lights[0].attenuation", glm::vec3(1.0, 0.09, 0.032));
shader->setInt("lights[1].type", 1);
shader->setVec3("lights[1].position", lightPositions[1]);
shader->setVec3("lights[1].ambient", glm::vec3(0.1));
shader->setVec3("lights[1].diffuse", glm::vec3(0.6, 0.4, 0.4));
shader->setVec3("lights[1].specular", glm::vec3(1.0));
shader->setBool("lights[1].attenuate", false);
shader->setVec3("lights[1].attenuation", glm::vec3(1.0, 0.09, 0.032));
shader->setInt("lights[2].type", 0);
shader->setVec3("lights[2].position", lightPositions[1]);
shader->setVec3("lights[2].ambient", glm::vec3(0.1));
shader->setVec3("lights[2].diffuse", glm::vec3(0.3, 0.4, 0.6));
shader->setVec3("lights[2].specular", glm::vec3(0.3, 1.0, 0.5));
shader->setBool("lights[2].attenuate", false);
shader->setVec3("lights[2].attenuation", glm::vec3(1.0, 0.09, 0.032));
glUniform3f(glGetUniformLocation(shader->program, "cameraPosition"), camera_pos.x, camera_pos.y, camera_pos.z);
shader->setVec3("material.specular", glm::vec3(0.7));
shader->setVec3("material.diffuse", glm::vec3(1.0, 0.7, 0.8));
shader->setVec3("material.ambient", glm::vec3(0.2));
shader->setFloat("material.shininess", 32);
glCheckError();
/***** Light Attenuation
modelShader->setVec3("material.specular", glm::vec3(0.7));
modelShader->setVec3("material.diffuse", glm::vec3(1.0, 0.7, 0.8));
modelShader->setVec3("material.ambient", glm::vec3(0.2));
modelShader->setFloat("material.shininess", 32);
/***** Light Attenuation
*
* Constant x, Linear y, Quadratic z
*
@ -903,6 +738,7 @@ class SDLGLGLWindow { @@ -903,6 +738,7 @@ class SDLGLGLWindow {
glCheckError();
loc = shader->get_uniform("model");
glCheckError();
printProgramLog(shader->program);
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
glCheckError();
@ -913,14 +749,17 @@ class SDLGLGLWindow { @@ -913,14 +749,17 @@ class SDLGLGLWindow {
loc = shader->get_uniform("projection");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(projection));
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
running_level->draw_system->draw(view, projection);
//bp_model->draw(*shader);
objects->draw(view, projection);
// objects->draw(view, projection);
// objects->draw(skybox_object, view, projection);
glCheckError();
//*** Draw random cubes ****/
/*** Draw random cubes
shader->use();
glBindVertexArray(gVAO);
@ -934,6 +773,9 @@ class SDLGLGLWindow { @@ -934,6 +773,9 @@ class SDLGLGLWindow {
glDrawArraysInstanced(GL_TRIANGLES, 0,36,1000);
glCheckError();
*/
/** draw skybox cubemap */
@ -986,9 +828,6 @@ class SDLGLGLWindow { @@ -986,9 +828,6 @@ class SDLGLGLWindow {
printProgramLog(texShader->program);
glCheckError();
}
@ -1069,10 +908,8 @@ int main(int argc, char **argv) { @@ -1069,10 +908,8 @@ int main(int argc, char **argv) {
cont.camera_pos += camera_speed * glm::cross(cont.camera_front, cont.camera_up);
break;
case SDL_SCANCODE_R:
cont.shader->reload();
cont.modelShader->reload();
glCheckError();
glCheckError();
cont.running_level->update();
//cont.texShader->reload();
//cont.skyboxShader->reload();
break;

10
src/mesh.cpp

@ -46,7 +46,7 @@ void Mesh::setupMesh() @@ -46,7 +46,7 @@ void Mesh::setupMesh()
}
void Mesh::draw(Shader &shader) {
void Mesh::draw(Shader *shader) {
glCheckError();
unsigned int specularNr = 1;
unsigned int diffuseNr = 1;
@ -66,7 +66,9 @@ void Mesh::draw(Shader &shader) { @@ -66,7 +66,9 @@ void Mesh::draw(Shader &shader) {
number = std::to_string(normalNr++);
}
shader.setInt(("material." + name + number).c_str(), i);
glCheckError();
shader->setInt(("material." + name + number).c_str(), i);
glCheckError();
glBindTexture(GL_TEXTURE_2D, textures[i].id);
glCheckError();
}
@ -86,9 +88,9 @@ void Mesh::draw(Shader &shader) { @@ -86,9 +88,9 @@ void Mesh::draw(Shader &shader) {
/** Model */
void Model::draw(Shader &shader)
void Model::draw(Shader *shader)
{
shader.use();
shader->use();
for(auto mesh : meshes) {
mesh.draw(shader);
}

4
src/mesh.h

@ -35,7 +35,7 @@ class Mesh { @@ -35,7 +35,7 @@ class Mesh {
Mesh(std::vector<struct vertex> vertices,
std::vector<unsigned int> indices,
std::vector<struct texture> textures);
void draw(Shader &shader);
void draw(Shader *shader);
private:
unsigned int VAO, VBO, EBO;
void setupMesh();
@ -47,7 +47,7 @@ class Model { @@ -47,7 +47,7 @@ class Model {
Model(std::string path) {
load_model(path);
}
void draw(Shader &shader);
void draw(Shader *shader);
private:
Assimp::Importer importer;
std::vector<Mesh> meshes;

8
src/shaders.h

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
#ifndef G_SHADERSH
#define G_SHADERSH
#pragma once
#include <SDL2/SDL.h>
//Using SDL, SDL OpenGL, standard IO, and, strings
@ -21,15 +20,17 @@ class Shader { @@ -21,15 +20,17 @@ class Shader {
bool handle_error(std::string &filename, GLuint shader);
bool link();
public:
GLuint shader_vert = 0;
GLuint shader_frag = 0;
public:
GLuint program = 0;
Shader();
Shader(std::string filename);
Shader(std::string filename, std::string filename2);
~Shader();
Shader(Shader &&) = default;
Shader(Shader &) = default;
void use();
void reload();
@ -45,4 +46,3 @@ class Shader { @@ -45,4 +46,3 @@ class Shader {
GLint get_attrib(std::string attribute_name);
GLint get_uniform(std::string uniform_name);
};
#endif

Loading…
Cancel
Save