big update
This commit is contained in:
736
src/Application.cpp
Normal file
736
src/Application.cpp
Normal file
@ -0,0 +1,736 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/mat3x3.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw_gl3.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using glm::vec3;
|
||||
using glm::uvec3;
|
||||
using std::map;
|
||||
using std::vector;
|
||||
|
||||
void calculateNormals(const vector<vec3> &vtx, vector<uvec3> &tri,
|
||||
vector<vec3> &normals) {
|
||||
normals.clear();
|
||||
normals.resize(vtx.size(), vec3(0));
|
||||
for (size_t i = 0; i < tri.size(); i++) {
|
||||
int a = tri[i].x, b = tri[i].y, c = tri[i].z;
|
||||
vec3 faceNormal = normalize(
|
||||
glm::cross(vtx[b] - vtx[a], vtx[c] - vtx[a]));
|
||||
normals[a] += faceNormal;
|
||||
normals[b] += faceNormal;
|
||||
normals[c] += faceNormal;
|
||||
}
|
||||
for (size_t i = 0; i < normals.size(); i++)
|
||||
normals[i] = glm::normalize(normals[i]);
|
||||
|
||||
}
|
||||
|
||||
void moveToMean(vector<vec3> &vtx) {
|
||||
vec3 mean(0);
|
||||
for (size_t i = 0; i < vtx.size(); i++) {
|
||||
mean += vtx[i];
|
||||
}
|
||||
mean *= vec3(1.f / vtx.size());
|
||||
for (size_t i = 0; i < vtx.size(); i++) {
|
||||
vtx[i] -= mean;
|
||||
}
|
||||
}
|
||||
|
||||
void smooth(vector<vec3> &vtx, const vector<uvec3> &tri) {
|
||||
vector<vec3> cogs(vtx.size(), vec3(0.f));
|
||||
vector<int> valence(vtx.size(), 0);
|
||||
|
||||
for (size_t iTri = 0; iTri < tri.size(); iTri++) {
|
||||
const uvec3 &idx = tri[iTri];
|
||||
for (size_t iE = 0; iE < 3; iE++) {
|
||||
valence[idx[iE]] += 2;
|
||||
cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]];
|
||||
cogs[idx[iE]] += vtx[idx[(iE + 2) % 3]];
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) {
|
||||
cog[0] = cog[1] = cog[2] = valence = 0.0;
|
||||
|
||||
for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) {
|
||||
cog += mesh.point(*vv_it);
|
||||
++valence;
|
||||
}
|
||||
cogs.push_back(cog / valence);
|
||||
}
|
||||
for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end;
|
||||
++v_it, ++cog_it)
|
||||
if (!mesh.is_boundary(*v_it))
|
||||
mesh.set_point(*v_it, *cog_it);
|
||||
|
||||
*/
|
||||
for (size_t i = 0; i < vtx.size(); i++) {
|
||||
// vtx[i] = vtx[i] * vec3(0.8)
|
||||
// + cogs[i] * vec3(0.2f / valence[i]);
|
||||
vtx[i] = cogs[i] * vec3(1.f / valence[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void saveAttrib(std::ostream &out, const char *prefix, vector<vec3> &elements) {
|
||||
for (size_t i = 0; i < elements.size(); i++) {
|
||||
out << prefix << elements[i].x << " " << elements[i].y << " "
|
||||
<< elements[i].z << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void saveAttrib(std::ostream &out, const char *prefix,
|
||||
vector<glm::vec2> &elements) {
|
||||
for (size_t i = 0; i < elements.size(); i++) {
|
||||
out << prefix << elements[i].x << " " << elements[i].y << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void saveFaces(std::ostream &out, const vector<uvec3> &tris, size_t attribs) {
|
||||
for (size_t i = 0; i < tris.size(); i++) {
|
||||
out << "f";
|
||||
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
int v = tris[i][j] + 1;
|
||||
out << " " << v;
|
||||
if (attribs > 1)
|
||||
out << "/" << v;
|
||||
if (attribs > 2)
|
||||
out << "/" << v;
|
||||
out << " ";
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void calculateEdges(const vector<vec3> &vtx, vector<uvec3> &tri,
|
||||
vector<glm::uvec4> &edges) {
|
||||
edges.clear();
|
||||
map<std::pair<uint32_t, uint32_t>, uint32_t> edgeMap;
|
||||
for (size_t iTri = 0; iTri < tri.size(); iTri++) {
|
||||
uvec3 idx = tri[iTri];
|
||||
for (size_t k = 0; k < 3; k++) {
|
||||
int a = idx[k];
|
||||
int b = idx[(k + 1) % 3];
|
||||
glm::uvec4 edge1(std::min(a, b), std::max(a, b), iTri, 0);
|
||||
auto it1 = edgeMap.find(std::make_pair(edge1.x, edge1.y));
|
||||
if (it1 != edgeMap.end()) {
|
||||
edges[it1->second].z = iTri;
|
||||
} else {
|
||||
edges.push_back(edge1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void computeTangentBasis(vector<vec3> & vertices, vector<glm::vec2> & uvs,
|
||||
vector<vec3> & normals, vector<vec3> & tangents,
|
||||
vector<vec3> & bitangents) {
|
||||
|
||||
for (size_t i = 0; i < vertices.size(); i += 3) {
|
||||
|
||||
// Shortcuts for vertices
|
||||
vec3 & v0 = vertices[i + 0];
|
||||
vec3 & v1 = vertices[i + 1];
|
||||
vec3 & v2 = vertices[i + 2];
|
||||
|
||||
// Shortcuts for UVs
|
||||
glm::vec2 & uv0 = uvs[i + 0];
|
||||
glm::vec2 & uv1 = uvs[i + 1];
|
||||
glm::vec2 & uv2 = uvs[i + 2];
|
||||
|
||||
// Edges of the triangle : postion delta
|
||||
vec3 deltaPos1 = v1 - v0;
|
||||
vec3 deltaPos2 = v2 - v0;
|
||||
|
||||
// UV delta
|
||||
glm::vec2 deltaUV1 = uv1 - uv0;
|
||||
glm::vec2 deltaUV2 = uv2 - uv0;
|
||||
|
||||
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
||||
vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
|
||||
vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
|
||||
// Set the same tangent for all three vertices of the triangle.
|
||||
// They will be merged later, in vboindexer.cpp
|
||||
tangents.push_back(tangent);
|
||||
tangents.push_back(tangent);
|
||||
tangents.push_back(tangent);
|
||||
|
||||
// Same thing for binormals
|
||||
bitangents.push_back(bitangent);
|
||||
bitangents.push_back(bitangent);
|
||||
bitangents.push_back(bitangent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool glck(const char* call) {
|
||||
int err = glGetError();
|
||||
if (err == 0) {
|
||||
return true;
|
||||
} else {
|
||||
switch (err) {
|
||||
case GL_INVALID_VALUE:
|
||||
printf("GL_INVALID_VALUE: %s\n", call);
|
||||
break;
|
||||
case GL_INVALID_ENUM:
|
||||
printf("GL_INVALID_ENUM: %s\n", call);
|
||||
break;
|
||||
case GL_INVALID_OPERATION:
|
||||
printf("GL_INVALID_OPERATION: %s\n", call);
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN Error: %s\n", call);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define GLCK(a) {a; assert(glck(#a));}
|
||||
|
||||
static void error_callback(int error, const char* description) {
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
||||
int mods) {
|
||||
Application::instance().KeyCallback(window, key, scancode, action, mods);
|
||||
}
|
||||
|
||||
static void mouse_button_callback(GLFWwindow* window, int button, int action,
|
||||
int mods) {
|
||||
Application::instance().MouseButtonCallback(window, button, action, mods);
|
||||
|
||||
}
|
||||
static void scroll_callback(GLFWwindow* window, double xoffset,
|
||||
double yoffset) {
|
||||
Application::instance().ScrollCallback(window, xoffset, yoffset);
|
||||
}
|
||||
|
||||
static void char_callback(GLFWwindow* window, unsigned int c) {
|
||||
Application::instance().CharCallback(window, c);
|
||||
}
|
||||
|
||||
Application::Application() :
|
||||
window(0), density(), densityIsolevel(0.2), polygonizer(density,
|
||||
densityIsolevel), textureSize(512), texturemapper(density,
|
||||
textureSize), programId(0), vPositionLoc(-1), vTexCoordLoc(-1), vNormalLoc(
|
||||
-1), meteoridCount(1000), meteroidMinRadius(0.005), meteroidMaxRadius(
|
||||
0.2), meteroidSizeExponent(2048), densityFrequency(2), densityOctave(
|
||||
2), densityScale(1.0f), resolution(0.1), viewDistance(3.0f), fpsMode(
|
||||
false) {
|
||||
init();
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
Application &Application::instance() {
|
||||
static Application app;
|
||||
return app;
|
||||
}
|
||||
|
||||
void Application::init() {
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
|
||||
window = glfwCreateWindow(1200, 800, "Procedural Asteroid Generator", NULL,
|
||||
NULL);
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
GLFWimage icon;
|
||||
int n;
|
||||
icon.pixels = stbi_load("icon.png", &icon.width, &icon.height, &n, 4);
|
||||
if (icon.pixels) {
|
||||
glfwSetWindowIcon(window, 1, &icon);
|
||||
stbi_image_free(icon.pixels);
|
||||
} else
|
||||
std::cout << "Failed to load icon.png" << std::endl;
|
||||
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetCharCallback(window, char_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
|
||||
std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||
<< std::endl;
|
||||
std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
|
||||
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
|
||||
|
||||
ImGui_ImplGlfwGL3_Init(window, false);
|
||||
|
||||
GLCK(glGenVertexArrays(1, &vertexArrayId))
|
||||
GLCK(glGenBuffers(1, &vPositionId))
|
||||
GLCK(glGenBuffers(1, &vTexCoordId))
|
||||
GLCK(glGenBuffers(1, &vNormalId))
|
||||
GLCK(glGenBuffers(1, &indexBufferId))
|
||||
|
||||
GLCK(glGenTextures(1, &tAlbedoId))
|
||||
GLCK(glGenTextures(1, &tNormalId))
|
||||
GLCK(glGenTextures(1, &tRoughnessId))
|
||||
GLCK(glGenTextures(1, &tMetalicId))
|
||||
|
||||
loadShader();
|
||||
updateVertexArrayObject();
|
||||
generateAsteroid();
|
||||
uploadMesh();
|
||||
}
|
||||
|
||||
void Application::shutdown() {
|
||||
ImGui_ImplGlfwGL3_Shutdown();
|
||||
|
||||
GLCK(glDeleteBuffers(1, &vPositionId))
|
||||
GLCK(glDeleteBuffers(1, &vTexCoordId))
|
||||
GLCK(glDeleteBuffers(1, &vNormalId))
|
||||
GLCK(glDeleteBuffers(1, &indexBufferId))
|
||||
GLCK(glDeleteVertexArrays(1, &vertexArrayId))
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void Application::KeyCallback(GLFWwindow* window, int key, int scancode,
|
||||
int action, int mods) {
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
if (ImGui::IsMouseHoveringAnyWindow())
|
||||
ImGui_ImplGlfwGL3_KeyCallback(window, key, scancode, action, mods);
|
||||
else {
|
||||
if (key == GLFW_KEY_TAB && action == GLFW_RELEASE) {
|
||||
toogleFpsMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::MouseButtonCallback(GLFWwindow* window, int button,
|
||||
int action, int mods) {
|
||||
ImGui_ImplGlfwGL3_MouseButtonCallback(window, button, action, mods);
|
||||
}
|
||||
void Application::ScrollCallback(GLFWwindow* window, double xoffset,
|
||||
double yoffset) {
|
||||
if (ImGui::IsMouseHoveringAnyWindow())
|
||||
ImGui_ImplGlfwGL3_ScrollCallback(window, xoffset, yoffset);
|
||||
else
|
||||
viewDistance -= yoffset * viewDistance * 0.1;
|
||||
}
|
||||
void Application::CharCallback(GLFWwindow* window, unsigned int c) {
|
||||
|
||||
ImGui_ImplGlfwGL3_CharCallback(window, c);
|
||||
}
|
||||
|
||||
void Application::toogleFpsMode() {
|
||||
if (fpsMode) {
|
||||
fpsMode = false;
|
||||
} else {
|
||||
fpsMode = true;
|
||||
fpsTrafo = glm::lookAt(vec3(0, 0, viewDistance), vec3(0, 0, 0),
|
||||
vec3(0, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::generateAsteroid() {
|
||||
std::srand(123);
|
||||
|
||||
if (density.getImpacts().size() == 0)
|
||||
density.addRandomImpacts(1000, 0.2, 0.01, 0.005, 0.2, 4096);
|
||||
//density.saveCrossSection("density.png", 512);
|
||||
|
||||
polygonizer.polygonize(resolution);
|
||||
{
|
||||
std::ofstream out("stage1.obj");
|
||||
saveAttrib(out, "v ", polygonizer.vertices);
|
||||
saveFaces(out, polygonizer.indices, 1);
|
||||
}
|
||||
|
||||
smooth(polygonizer.vertices, polygonizer.indices);
|
||||
{
|
||||
std::ofstream out("stage2.obj");
|
||||
saveAttrib(out, "v ", polygonizer.vertices);
|
||||
saveFaces(out, polygonizer.indices, 1);
|
||||
}
|
||||
calculateNormals(polygonizer.vertices, polygonizer.indices, normals);
|
||||
{
|
||||
std::ofstream out("stage3.obj");
|
||||
saveAttrib(out, "v ", polygonizer.vertices);
|
||||
saveAttrib(out, "vn ", normals);
|
||||
saveFaces(out, polygonizer.indices, 2);
|
||||
}
|
||||
|
||||
vector<glm::uvec4> edges;
|
||||
std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl;
|
||||
std::cout << "Triangles: " << polygonizer.indices.size() << std::endl;
|
||||
|
||||
texturemapper.map(polygonizer.vertices, normals, polygonizer.indices);
|
||||
moveToMean(texturemapper.vertices);
|
||||
|
||||
{
|
||||
std::ofstream out("stage4.obj");
|
||||
saveAttrib(out, "v ", texturemapper.vertices);
|
||||
saveAttrib(out, "vn ", texturemapper.normals);
|
||||
saveAttrib(out, "vt ", texturemapper.texcoords);
|
||||
saveFaces(out, texturemapper.indices, 3);
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::bindVertexAttrib(GLuint id, GLint loc, GLuint size) {
|
||||
if (loc < 0)
|
||||
return false;
|
||||
GLCK(glBindBuffer(GL_ARRAY_BUFFER, id))
|
||||
GLCK(glEnableVertexAttribArray(loc))
|
||||
GLCK(glVertexAttribPointer(loc, // attribute
|
||||
size,// size
|
||||
GL_FLOAT,// type
|
||||
GL_FALSE,// normalized?
|
||||
0,// stride
|
||||
(void* ) 0// array buffer offset
|
||||
))
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::updateVertexArrayObject() {
|
||||
GLCK(glBindVertexArray(vertexArrayId))
|
||||
|
||||
if (vPositionLoc >= 0)
|
||||
GLCK(glDisableVertexAttribArray(vPositionLoc))
|
||||
if (vNormalLoc >= 0)
|
||||
GLCK(glDisableVertexAttribArray(vNormalLoc))
|
||||
if (vTexCoordLoc >= 0)
|
||||
GLCK(glDisableVertexAttribArray(vTexCoordLoc))
|
||||
|
||||
bindVertexAttrib(vPositionId, vPositionLoc, 3);
|
||||
bindVertexAttrib(vNormalId, vNormalLoc, 3);
|
||||
bindVertexAttrib(vTexCoordId, vTexCoordLoc, 2);
|
||||
|
||||
GLCK(glBindVertexArray(0))
|
||||
}
|
||||
|
||||
GLuint Application::loadProgram(const std::string &name) {
|
||||
|
||||
// Create the shaders
|
||||
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
// Read the Vertex Shader code from the file
|
||||
std::string VertexShaderCode;
|
||||
std::string vertex_file_path = "shader/" + name + ".vertex.glsl";
|
||||
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
|
||||
if (VertexShaderStream.is_open()) {
|
||||
std::string Line = "";
|
||||
while (getline(VertexShaderStream, Line))
|
||||
VertexShaderCode += "\n" + Line;
|
||||
VertexShaderStream.close();
|
||||
} else {
|
||||
std::cout << "Failed to open " << vertex_file_path << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the Fragment Shader code from the file
|
||||
std::string FragmentShaderCode;
|
||||
std::string fragment_file_path = "shader/" + name + ".fragment.glsl";
|
||||
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
|
||||
if (FragmentShaderStream.is_open()) {
|
||||
std::string Line = "";
|
||||
while (getline(FragmentShaderStream, Line))
|
||||
FragmentShaderCode += "\n" + Line;
|
||||
FragmentShaderStream.close();
|
||||
} else {
|
||||
std::cout << "Failed to open " << vertex_file_path << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
|
||||
// Compile Vertex Shader
|
||||
std::cout << "Compiling vertex shader : " << name << std::endl;
|
||||
char const * VertexSourcePointer = VertexShaderCode.c_str();
|
||||
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
|
||||
glCompileShader(VertexShaderID);
|
||||
|
||||
// Check Vertex Shader
|
||||
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if (InfoLogLength > 0) {
|
||||
vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
|
||||
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL,
|
||||
&VertexShaderErrorMessage[0]);
|
||||
printf("%s\n", &VertexShaderErrorMessage[0]);
|
||||
}
|
||||
|
||||
// Compile Fragment Shader
|
||||
std::cout << "Compiling fragment shader : " << name << std::endl;
|
||||
|
||||
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
|
||||
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
|
||||
glCompileShader(FragmentShaderID);
|
||||
|
||||
// Check Fragment Shader
|
||||
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if (InfoLogLength > 0) {
|
||||
vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
|
||||
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL,
|
||||
&FragmentShaderErrorMessage[0]);
|
||||
printf("%s\n", &FragmentShaderErrorMessage[0]);
|
||||
}
|
||||
|
||||
// Link the program
|
||||
std::cout << "Linking program : " << name << std::endl;
|
||||
|
||||
GLuint ProgramID = glCreateProgram();
|
||||
glAttachShader(ProgramID, VertexShaderID);
|
||||
glAttachShader(ProgramID, FragmentShaderID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
// Check the program
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
if (InfoLogLength > 0) {
|
||||
vector<char> ProgramErrorMessage(InfoLogLength + 1);
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL,
|
||||
&ProgramErrorMessage[0]);
|
||||
printf("%s\n", &ProgramErrorMessage[0]);
|
||||
}
|
||||
|
||||
glDetachShader(ProgramID, VertexShaderID);
|
||||
glDetachShader(ProgramID, FragmentShaderID);
|
||||
|
||||
glDeleteShader(VertexShaderID);
|
||||
glDeleteShader(FragmentShaderID);
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
void Application::loadShader() {
|
||||
if (programId >= 0)
|
||||
GLCK(glDeleteProgram(programId))
|
||||
programId = loadProgram("standard");
|
||||
|
||||
GLCK(MVPloc = glGetUniformLocation(programId, "MVP"))
|
||||
GLCK(Mloc = glGetUniformLocation(programId, "M"))
|
||||
GLCK(Vloc = glGetUniformLocation(programId, "V"))
|
||||
GLCK(
|
||||
LightPosition_worldspaceloc = glGetUniformLocation(programId, "LightPosition_worldspace"))
|
||||
|
||||
GLCK(vPositionLoc = glGetAttribLocation(programId, "vPosition"))
|
||||
GLCK(vTexCoordLoc = glGetAttribLocation(programId, "vTexCoord"))
|
||||
GLCK(vNormalLoc = glGetAttribLocation(programId, "vNormal"))
|
||||
|
||||
GLCK(tAlbedoLoc = glGetAttribLocation(programId, "tAlbedo"))
|
||||
GLCK(tNormalLoc = glGetAttribLocation(programId, "tNormal"))
|
||||
GLCK(tRoughnessLoc = glGetAttribLocation(programId, "tRoughness"))
|
||||
GLCK(tMetalicLoc = glGetAttribLocation(programId, "tMetalic"))
|
||||
}
|
||||
|
||||
void Application::uploadMesh() {
|
||||
GLCK(glBindVertexArray(vertexArrayId))
|
||||
|
||||
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId))
|
||||
GLCK(
|
||||
glBufferData(GL_ARRAY_BUFFER, texturemapper.vertices.size() * sizeof(vec3), texturemapper.vertices.data(), GL_STATIC_DRAW))
|
||||
|
||||
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vTexCoordId))
|
||||
GLCK(
|
||||
glBufferData(GL_ARRAY_BUFFER, texturemapper.texcoords.size() * sizeof(glm::vec2), texturemapper.texcoords.data(), GL_STATIC_DRAW))
|
||||
|
||||
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vNormalId))
|
||||
GLCK(
|
||||
glBufferData(GL_ARRAY_BUFFER, texturemapper.normals.size() * sizeof(vec3), texturemapper.normals.data(), GL_STATIC_DRAW))
|
||||
|
||||
GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId))
|
||||
GLCK(
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, texturemapper.indices.size() * sizeof(uvec3), texturemapper.indices.data(), GL_STATIC_DRAW))
|
||||
|
||||
GLCK(glBindVertexArray(0))
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tAlbedoId);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturemapper.getTextureSize(),
|
||||
texturemapper.getTextureSize(), 0, GL_BGR, GL_UNSIGNED_BYTE,
|
||||
texturemapper.albedo.data());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
void Application::renderMesh() {
|
||||
GLCK(glBindVertexArray(vertexArrayId))
|
||||
GLCK(
|
||||
glDrawElements(GL_TRIANGLES, texturemapper.indices.size() * 3, GL_UNSIGNED_INT, (void* ) 0))
|
||||
GLCK(glBindVertexArray(0))
|
||||
|
||||
}
|
||||
|
||||
void Application::prepareShader() {
|
||||
glm::mat4 model(1.0f);
|
||||
glm::mat4 view;
|
||||
|
||||
if (fpsMode) {
|
||||
glm::vec4 movement(0.0);
|
||||
if (fpsMode) {
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
|
||||
movement += glm::vec4(0.0, 0.0, 0.1, 0.0);
|
||||
} else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
|
||||
movement -= glm::vec4(0.0, 0.0, 0.1, 0.0);
|
||||
}
|
||||
}
|
||||
glm::vec3 absolute = glm::transpose(fpsTrafo) * movement;
|
||||
fpsTrafo = glm::translate(fpsTrafo, absolute);
|
||||
view = fpsTrafo;
|
||||
} else {
|
||||
model = glm::rotate(model, (float) glfwGetTime(), vec3(0.f, 1.f, 0.f));
|
||||
|
||||
view = glm::lookAt(vec3(0, 0, viewDistance), // Camera is at (4,3,3), in World Space
|
||||
vec3(0, 0, 0), // and looks at the origin
|
||||
vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
|
||||
);
|
||||
}
|
||||
glm::mat4 perspective = glm::perspective(glm::radians(45.0f),
|
||||
(float) width / (float) height, 0.1f, 100.0f);
|
||||
glm::mat4 mvp = perspective * view * model;
|
||||
|
||||
GLCK(glUseProgram(programId))
|
||||
if (MVPloc >= 0) {
|
||||
GLCK(glUniformMatrix4fv(MVPloc, 1, GL_FALSE, glm::value_ptr(mvp)))
|
||||
}
|
||||
if (Mloc >= 0) {
|
||||
GLCK(glUniformMatrix4fv(Mloc, 1, GL_FALSE, glm::value_ptr(model)))
|
||||
}
|
||||
if (Vloc >= 0) {
|
||||
GLCK(glUniformMatrix4fv(Vloc, 1, GL_FALSE, glm::value_ptr(view)))
|
||||
}
|
||||
if (LightPosition_worldspaceloc >= 0) {
|
||||
vec3 LightPosition_worldspace(10.0f, 10.0f, 10.0f);
|
||||
GLCK(
|
||||
glUniform3fv(LightPosition_worldspaceloc, 1, glm::value_ptr(LightPosition_worldspace)))
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
if (tAlbedoLoc >= 0) {
|
||||
glUniform1i(tAlbedoLoc, idx);
|
||||
glActiveTexture(GL_TEXTURE0 + idx);
|
||||
glBindTexture(GL_TEXTURE_2D, tAlbedoId);
|
||||
idx++;
|
||||
}
|
||||
if (tNormalLoc >= 0) {
|
||||
glUniform1i(tNormalLoc, idx);
|
||||
glActiveTexture(GL_TEXTURE0 + idx);
|
||||
glBindTexture(GL_TEXTURE_2D, tNormalId);
|
||||
idx++;
|
||||
}
|
||||
if (tRoughnessLoc >= 0) {
|
||||
glUniform1i(tRoughnessLoc, idx);
|
||||
glActiveTexture(GL_TEXTURE0 + idx);
|
||||
glBindTexture(GL_TEXTURE_2D, tRoughnessId);
|
||||
idx++;
|
||||
}
|
||||
if (tMetalicLoc >= 0) {
|
||||
glUniform1i(tMetalicLoc, idx);
|
||||
glActiveTexture(GL_TEXTURE0 + idx);
|
||||
glBindTexture(GL_TEXTURE_2D, tMetalicId);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::gui() {
|
||||
ImGui::Begin("Mesh Generation");
|
||||
ImGui::Text("Vertices: %lu, Triangles: %lu", polygonizer.vertices.size(),
|
||||
polygonizer.indices.size());
|
||||
//ImGui::InputFloat("Resolution", &resolution);
|
||||
ImGui::SliderFloat("Resolution", &resolution, 0.1, 0.001, "%.3f", 0.1);
|
||||
if (ImGui::SliderFloat("Frequency", &densityFrequency, 1, 10, "%.0f", 1))
|
||||
density.setFrequency(densityFrequency);
|
||||
if (ImGui::SliderFloat("Octave", &densityOctave, 1, 10, "%.0f", 1))
|
||||
density.setOctave(densityOctave);
|
||||
|
||||
// if (ImGui::InputFloat("Frequency", &densityFrequency))
|
||||
// if (ImGui::InputFloat("Octave", &densityOctave))
|
||||
// density.setOctave(densityOctave);
|
||||
|
||||
static const char *textureSizesStrings[] = { "512", "1024", "2048", "4096" };
|
||||
static const int textureSizes[] = { 512, 1024, 2048, 4096 };
|
||||
static int currentTextureSize = 0;
|
||||
if (ImGui::Combo("Texture Size", ¤tTextureSize, textureSizesStrings,
|
||||
4, -1)) {
|
||||
texturemapper.setTextureSize(textureSizes[currentTextureSize]);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Generate")) {
|
||||
generateAsteroid();
|
||||
uploadMesh();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Rendering");
|
||||
if (ImGui::Button("Reload Shader")) {
|
||||
loadShader();
|
||||
updateVertexArrayObject();
|
||||
}
|
||||
if (ImGui::Button("Wireframe"))
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
if (ImGui::Button("Fill"))
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
|
||||
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Textures");
|
||||
ImGui::Image((ImTextureID) (intptr_t) tAlbedoId,
|
||||
ImVec2(ImGui::GetWindowContentRegionMax().x,
|
||||
ImGui::GetWindowContentRegionMax().x));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Application::run() {
|
||||
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
ImGui_ImplGlfwGL3_NewFrame();
|
||||
|
||||
gui();
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
prepareShader();
|
||||
renderMesh();
|
||||
|
||||
ImGui::Render();
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user