Compare commits

..

No commits in common. "main" and "feature/texture-import" have entirely different histories.

57 changed files with 460 additions and 706 deletions

View File

@ -7,7 +7,6 @@ stages:
variables: variables:
VCPKG_ROOT: "/vcpkg" VCPKG_ROOT: "/vcpkg"
CMAKE_BUILD_TYPE: "Release"
build: build:
stage: build stage: build

View File

@ -1,11 +0,0 @@
## [v0.0.2] - 2024-08-25
### Changed
- Refactored uniform handling in the initial geometry pass to improve maintainability.
## [v0.0.3] - 2024-08-28
### Changed
- Correctly manage window resizing for camera aspect ratio
## [v0.0.4] - 2024-08-28
### Changed
- Added dynamic tessellation determined by the slope of the terrain

View File

@ -1,15 +1,9 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(TerraVisor VERSION 0.0.4) project(TerraVisor)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
configure_file(
"${PROJECT_SOURCE_DIR}/include/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
include_directories("${PROJECT_BINARY_DIR}")
# Find packages using vcpkg # Find packages using vcpkg
find_package(GLEW CONFIG REQUIRED) find_package(GLEW CONFIG REQUIRED)
find_package(glfw3 CONFIG REQUIRED) find_package(glfw3 CONFIG REQUIRED)

View File

@ -677,5 +677,4 @@ Public License instead of this License. But first, please read
This project also includes third-party software with different licenses: This project also includes third-party software with different licenses:
The FreeImage open source image library. See http://freeimage.sourceforge.net for details. - FreeImage is licensed under the FreeImage Public License (FIPL). See `licenses/LICENSE-FreeImage.txt` for details.
FreeImage is used under the (GNU GPL or FIPL), version (license version).

2
LICENSE Normal file
View File

@ -0,0 +1,2 @@
This project is licensed under the GNU General Public License v3.0.
See the COPYING file for more details.

View File

@ -79,7 +79,7 @@ GLEW - OpenGL Extension Wrangler Library \
GLFW - OpenGL Framework \ GLFW - OpenGL Framework \
GLM - OpenGL Mathematics \ GLM - OpenGL Mathematics \
ASSIMP - Open Asset Import Library \ ASSIMP - Open Asset Import Library \
FreeImage - Open Source Image Library \ FreeImage - Graphics Import Library \
Dear ImGui - GUI framework Dear ImGui - GUI framework
## Contact ## Contact

View File

@ -4,8 +4,8 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Terrain Controls] [Window][Terrain Controls]
Pos=861,19 Pos=925,19
Size=419,701 Size=403,701
Collapsed=0 Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
@ -19,31 +19,17 @@ Collapsed=0
[Window][TerraVisor] [Window][TerraVisor]
Pos=0,0 Pos=0,0
Size=2880,1676 Size=1328,720
Collapsed=0 Collapsed=0
[Window][Scene Window] [Window][Scene Window]
Pos=0,19 Pos=0,19
Size=859,701 Size=923,701
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000001,0
[Window][Viewport]
Pos=0,34
Size=2178,1641
Collapsed=0
DockId=0x00000003,0
[Window][Scene Settings]
Pos=2181,34
Size=699,1641
Collapsed=0
DockId=0x00000004,0
[Docking][Data] [Docking][Data]
DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,34 Size=2880,1641 Split=X Selected=0x9F2D9299 DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1328,701 Split=X Selected=0x9F2D9299
DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=0,0 Split=X Selected=0x13926F0B DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=875,701 CentralNode=1 Selected=0x9F2D9299
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=578,701 CentralNode=1 Selected=0x13926F0B DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=403,701 Selected=0xF69494A7
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=699,701 Selected=0x413E6147
DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=419,701 Selected=0xF69494A7

View File

@ -2,7 +2,6 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string>
namespace Uniforms namespace Uniforms
{ {
@ -16,17 +15,6 @@ namespace Uniforms
glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position
}; };
struct GeoUniforms
{
glm::mat4 PV;
glm::mat4 M;
float minTessellation = 1.0f;
float maxTessellation = 32.0f;
float displacementScale = 0.007f;
int gridDensity = 16;
};
struct LightUniforms struct LightUniforms
{ {
glm::vec4 La = glm::vec4(0.5f, 0.5f, 0.55f, 1.0f); //ambient light color glm::vec4 La = glm::vec4(0.5f, 0.5f, 0.55f, 1.0f); //ambient light color
@ -46,13 +34,11 @@ namespace Uniforms
extern SceneUniforms SceneData; extern SceneUniforms SceneData;
extern LightUniforms LightData; extern LightUniforms LightData;
extern MaterialUniforms MaterialData; extern MaterialUniforms MaterialData;
extern GeoUniforms GeoData;
//IDs for the buffer objects holding the uniform block data //IDs for the buffer objects holding the uniform block data
extern GLuint sceneUbo; extern GLuint scene_ubo;
extern GLuint lightUbo; extern GLuint light_ubo;
extern GLuint materialUbo; extern GLuint material_ubo;
extern GLuint geoUbo;
namespace UboBinding namespace UboBinding
{ {
@ -60,7 +46,6 @@ namespace Uniforms
extern int scene; extern int scene;
extern int light; extern int light;
extern int material; extern int material;
extern int geo;
}; };
//Locations for the uniforms which are not in uniform blocks //Locations for the uniforms which are not in uniform blocks

View File

@ -1,4 +0,0 @@
#define PROJECT_NAME "@PROJECT_NAME@"
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@

View File

@ -13,7 +13,6 @@ struct Framebuffer {
namespace FBO { namespace FBO {
Framebuffer GenerateFramebuffer(int width, int height); Framebuffer GenerateFramebuffer(int width, int height);
void UpdateFrameBuffer(Framebuffer& fbo, int width, int height);
void Bind(const Framebuffer& fbo); void Bind(const Framebuffer& fbo);
void Unbind(); void Unbind();
void Cleanup(const Framebuffer& fbo); void Cleanup(const Framebuffer& fbo);

View File

@ -1,29 +0,0 @@
#ifndef INTERFACE_H_
#define INTERFACE_H_
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <string>
#include <vector>
#include <functional>
struct Window {
std::string name;
ImVec2 size;
ImVec2 position;
bool isOpen = true;
std::function<void()> renderContent;
Window(const std::string& name, std::function<void()> renderFunc)
: name(name), size(ImVec2(512, 512)), position(ImVec2(0, 0)), renderContent(renderFunc) {}
};
namespace Interface {
void ApplyUIScaling(GLFWwindow* window);
void AddWindow(std::vector<Window>& windows, const std::string& name, std::function<void()> renderFunc);
Window* GetWindowByName(std::vector<Window>& windows, const std::string& name);
void RenderWindows(std::vector<Window>& windows);
}
#endif // INTERFACE_H_

View File

@ -8,7 +8,6 @@
#include "fbo.h" #include "fbo.h"
#include "camera.h" #include "camera.h"
#include "interface.h"
struct Vertex { struct Vertex {
glm::vec3 position; glm::vec3 position;
@ -26,21 +25,15 @@ class Scene {
void DrawGui(GLFWwindow* window); void DrawGui(GLFWwindow* window);
void Idle(); void Idle();
void ReloadShader(); void ReloadShader();
void UpdateCamera();
void OnScreenResize(Window* viewport);
void UpdateViewport();
std::vector<int16_t> LoadHGT(const std::string& filename, int width, int height); std::vector<int16_t> LoadHGT(const std::string& filename, int width, int height);
int window_width; int window_width;
int window_height; int window_height;
std::vector<Window> windows_;
private: private:
void InitBuffers(); void InitBuffers();
void InitQuadBuffers(); void InitQuadBuffers();
void InitShaders(); void InitShaders();
void InitUI();
Camera activeCamera_; Camera activeCamera_;
Framebuffer geo_fbo_; Framebuffer geo_fbo_;
@ -59,6 +52,7 @@ class Scene {
glm::mat4 view_matrix_; glm::mat4 view_matrix_;
glm::mat4 projection_matrix_; glm::mat4 projection_matrix_;
void UpdateCamera();
int16_t SwapEndian(int16_t val); int16_t SwapEndian(int16_t val);
GLuint CreateHeightmapTexture(std::vector<int16_t> data, int width, int height); GLuint CreateHeightmapTexture(std::vector<int16_t> data, int width, int height);
}; };

View File

@ -9,6 +9,12 @@ in TE_OUT {
vec3 normal; vec3 normal;
} fs_in; } fs_in;
layout(std140, binding = 0) uniform SceneUniforms
{
mat4 PV; //camera projection * view matrix
vec4 eye_w; //world-space eye position
};
layout(location = 0) out vec4 albedoGbuffer; layout(location = 0) out vec4 albedoGbuffer;
layout(location = 1) out vec4 positionGbuffer; layout(location = 1) out vec4 positionGbuffer;
layout(location = 2) out vec4 normalGbuffer; layout(location = 2) out vec4 normalGbuffer;

View File

@ -1,4 +1,5 @@
#version 450 core #version 430
precision highp float;
out vec4 frag_color; out vec4 frag_color;

View File

@ -1,5 +1,4 @@
#version 450 core #version 430
layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices
layout(location = 1) in vec2 tex_coord_attrib; layout(location = 1) in vec2 tex_coord_attrib;
layout(location = 2) in vec3 normal_attrib; layout(location = 2) in vec3 normal_attrib;

View File

@ -2,20 +2,6 @@
layout(vertices = 4) out; layout(vertices = 4) out;
layout(binding = 0) uniform sampler2D heightTexture;
uniform float tessellationFactor;
layout(std140, binding = 4) uniform GeoUniforms
{
mat4 PV;
mat4 M;
float minTessellation;
float maxTessellation;
float displacementScale;
int gridDensity;
};
in VS_OUT { in VS_OUT {
vec3 position; vec3 position;
vec2 texCoord; vec2 texCoord;
@ -24,48 +10,23 @@ in VS_OUT {
out TC_OUT { out TC_OUT {
vec3 position; vec3 position;
vec2 texCoord; vec2 texCoord;
float tessLevel;
} tc_out[]; } tc_out[];
float getHeight(vec2 uv) { uniform float tessellationFactor;
return texture(heightTexture, uv).r * displacementScale;
}
float calculateSlope() {
float step = 1.0f / (float(gridDensity) * maxTessellation + 1.0f);
// Find surrounding heights
float hLeft = getHeight(tc_in[gl_InvocationID].texCoord + vec2(-step, 0.0f));
float hRight = getHeight(tc_in[gl_InvocationID].texCoord + vec2(step, 0.0f));
float hUp = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, step));
float hDown = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, -step));
float slopeX = abs(hLeft - hRight) * displacementScale;
float slopeY = abs(hUp - hDown) * displacementScale;
float maxSlope = max(slopeX, slopeY);
return maxSlope;
}
void main() { void main() {
// Set tessellation levels
if (gl_InvocationID == 0) {
gl_TessLevelOuter[0] = tessellationFactor; // Level of tessellation along one edge
gl_TessLevelOuter[1] = tessellationFactor; // Level of tessellation along another edge
gl_TessLevelOuter[2] = tessellationFactor; // Level of tessellation along the other edge
gl_TessLevelOuter[3] = tessellationFactor; // Level of tessellation along the other edge
gl_TessLevelInner[0] = tessellationFactor; // Level of tessellation for the inner part
gl_TessLevelInner[1] = tessellationFactor; // Level of tessellation for the inner part
}
// Pass through position and texture coordinates to the tessellation evaluation shader // Pass through position and texture coordinates to the tessellation evaluation shader
tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position; tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position;
tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord; tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord;
float slope = calculateSlope();
float tessLevel = tessellationFactor * (1.0f + slope * 10.0f);
tessLevel = max(tessLevel, maxTessellation);
tc_out[gl_InvocationID].tessLevel = tessLevel;
// Set tessellation levels
if (gl_InvocationID == 0) {
gl_TessLevelOuter[0] = tessLevel;
gl_TessLevelOuter[1] = tessLevel;
gl_TessLevelOuter[2] = tessLevel;
gl_TessLevelOuter[3] = tessLevel;
gl_TessLevelInner[0] = tessLevel;
gl_TessLevelInner[1] = tessLevel;
}
} }

View File

@ -3,22 +3,20 @@
layout(quads, fractional_even_spacing, cw) in; layout(quads, fractional_even_spacing, cw) in;
layout(binding = 0) uniform sampler2D heightTexture; layout(binding = 0) uniform sampler2D heightTexture;
layout(location = 0) uniform mat4 M;
layout(std140, binding = 4) uniform GeoUniforms uniform float displacementScale = 0.025f;
uniform float tessellationFactor;
layout(std140, binding = 0) uniform SceneUniforms
{ {
mat4 PV; mat4 PV; //camera projection * view matrix
mat4 M; vec4 eye_w; //world-space eye position
float minTessellation;
float maxTessellation;
float displacementScale;
int gridDensity;
}; };
in TC_OUT { in TC_OUT {
vec3 position; vec3 position;
vec2 texCoord; vec2 texCoord;
float tessLevel;
} te_in[]; } te_in[];
out TE_OUT { out TE_OUT {
@ -31,25 +29,16 @@ float getHeight(vec2 uv) {
return texture(heightTexture, uv).r * displacementScale; return texture(heightTexture, uv).r * displacementScale;
} }
float getNeighbor(float tessFactor) {
return (float(gridDensity) * tessFactor + 1.0f);
}
vec3 calculateSmoothNormal(vec3 pos, vec2 coord) { vec3 calculateSmoothNormal(vec3 pos, vec2 coord) {
// Currently hardcoded to match patch density float step = 1.0f / (16.0f * tessellationFactor + 1.0f);
//float step = 1.0f / (float(gridDensity) * tessLevel + 1.0f);
float stepU = 1.0f / (float(gridDensity) * gl_TessLevelInner[0]);
float stepV = 1.0f / (float(gridDensity) * gl_TessLevelInner[1]);
// Find surrounding heights float hLeft = getHeight(coord + vec2(-step, 0.0f));
float hLeft = getHeight(coord + vec2(-stepU, 0.0f)); float hRight = getHeight(coord + vec2(step, 0.0f));
float hRight = getHeight(coord + vec2(stepU, 0.0f)); float hUp = getHeight(coord + vec2(0.0f, step));
float hUp = getHeight(coord + vec2(0.0f, stepV)); float hDown = getHeight(coord + vec2(0.0f, -step));
float hDown = getHeight(coord + vec2(0.0f, -stepV));
// Calculate tangents vec3 tangentX = normalize(vec3(step, hRight - hLeft, 0.0));
vec3 tangentX = normalize(vec3(stepU, hRight - hLeft, 0.0)); vec3 tangentY = normalize(vec3(0.0, hUp - hDown, step));
vec3 tangentY = normalize(vec3(0.0, hUp - hDown, stepV));
return normalize(cross(tangentY, tangentX)); return normalize(cross(tangentY, tangentX));
} }

View File

@ -1,7 +1,7 @@
#version 450 core #version 450 core
layout(location = 0) in vec3 posAttrib; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 texCoordAttrib; layout(location = 1) in vec2 inTexCoord;
out VS_OUT { out VS_OUT {
vec3 position; vec3 position;
@ -9,6 +9,6 @@ out VS_OUT {
} vs_out; } vs_out;
void main() { void main() {
vs_out.position = (vec4(posAttrib, 1.0f)).xyz; vs_out.position = (vec4(inPosition, 1.0f)).xyz;
vs_out.texCoord = texCoordAttrib; vs_out.texCoord = inTexCoord;
} }

View File

@ -10,106 +10,106 @@ using namespace std;
// Create a NULL-terminated string by reading the provided file // Create a NULL-terminated string by reading the provided file
static char* readShaderSource(const char* shaderFile) static char* readShaderSource(const char* shaderFile)
{ {
ifstream ifs(shaderFile, ios::in | ios::binary | ios::ate); ifstream ifs(shaderFile, ios::in | ios::binary | ios::ate);
if (ifs.is_open()) if (ifs.is_open())
{ {
unsigned int filesize = static_cast<unsigned int>(ifs.tellg()); unsigned int filesize = static_cast<unsigned int>(ifs.tellg());
ifs.seekg(0, ios::beg); ifs.seekg(0, ios::beg);
char* bytes = new char[filesize + 1]; char* bytes = new char[filesize + 1];
memset(bytes, 0, filesize + 1); memset(bytes, 0, filesize + 1);
ifs.read(bytes, filesize); ifs.read(bytes, filesize);
ifs.close(); ifs.close();
return bytes; return bytes;
} }
return NULL; return NULL;
} }
void printShaderCompileError(GLuint shader) void printShaderCompileError(GLuint shader)
{ {
GLint logSize; GLint logSize;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize]; char* logMsg = new char[logSize];
glGetShaderInfoLog(shader, logSize, NULL, logMsg); glGetShaderInfoLog(shader, logSize, NULL, logMsg);
std::cerr << logMsg << std::endl; std::cerr << logMsg << std::endl;
delete[] logMsg; delete[] logMsg;
} }
void printProgramLinkError(GLuint program) void printProgramLinkError(GLuint program)
{ {
GLint logSize; GLint logSize;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize]; char* logMsg = new char[logSize];
glGetProgramInfoLog(program, logSize, NULL, logMsg); glGetProgramInfoLog(program, logSize, NULL, logMsg);
std::cerr << logMsg << std::endl; std::cerr << logMsg << std::endl;
delete[] logMsg; delete[] logMsg;
} }
GLuint InitShader(const char* computeShaderFile) GLuint InitShader(const char* computeShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[1] = } shaders[1] =
{ {
{ computeShaderFile, GL_COMPUTE_SHADER, NULL } { computeShaderFile, GL_COMPUTE_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 1; ++i) for (int i = 0; i < 1; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
@ -117,301 +117,294 @@ GLuint InitShader(const char* computeShaderFile)
GLuint InitShader(const char* vShaderFile, const char* fShaderFile) GLuint InitShader(const char* vShaderFile, const char* fShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[2] = } shaders[2] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, NULL }, { vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL } { fShaderFile, GL_FRAGMENT_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
//set shader attrib locations //set shader attrib locations
const int posLoc = 0; const int pos_loc = 0;
const int texCoordLoc = 1; const int tex_coord_loc = 1;
const int normalLoc = 2; const int normal_loc = 2;
glBindAttribLocation(program, posLoc, "posAttrib"); glBindAttribLocation(program, pos_loc, "pos_attrib");
glBindAttribLocation(program, texCoordLoc, "texCoordAttrib"); glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib");
glBindAttribLocation(program, normalLoc, "normalAttrib"); glBindAttribLocation(program, normal_loc, "normal_attrib");
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
// Create a GLSL program object from vertex and fragment shader files // Create a GLSL program object from vertex and fragment shader files
GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char* fShaderFile) GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char* fShaderFile)
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
GLchar* source; GLchar* source;
} shaders[3] = } shaders[3] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, NULL }, { vShaderFile, GL_VERTEX_SHADER, NULL },
{ gShaderFile, GL_GEOMETRY_SHADER, NULL }, { gShaderFile, GL_GEOMETRY_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL } { fShaderFile, GL_FRAGMENT_SHADER, NULL }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if (shaders[i].source == NULL) if (shaders[i].source == NULL)
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader(s.type); GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); glShaderSource(shader, 1, (const GLchar**)&s.source, NULL);
glCompileShader(shader); glCompileShader(shader);
GLint compiled; GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) if (!compiled)
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
delete[] s.source; delete[] s.source;
glAttachShader(program, shader); glAttachShader(program, shader);
} }
//set shader attrib locations //set shader attrib locations
const int posLoc = 0; const int pos_loc = 0;
const int texCoordLoc = 1; const int tex_coord_loc = 1;
const int normalLoc = 2; const int normal_loc = 2;
glBindAttribLocation(program, posLoc, "posAttrib"); glBindAttribLocation(program, pos_loc, "pos_attrib");
glBindAttribLocation(program, texCoordLoc, "texCoordAttrib"); glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib");
glBindAttribLocation(program, normalLoc, "normalAttrib"); glBindAttribLocation(program, normal_loc, "normal_attrib");
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) if (!linked)
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if (error == true) if (error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile ) GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile )
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
std::string source; std::string source;
} shaders[4] = } shaders[4] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, "" }, { vShaderFile, GL_VERTEX_SHADER, "" },
{ tcShader, GL_TESS_CONTROL_SHADER, "" }, { tcShader, GL_TESS_CONTROL_SHADER, "" },
{ teShader, GL_TESS_EVALUATION_SHADER, "" }, { teShader, GL_TESS_EVALUATION_SHADER, "" },
{ fShaderFile, GL_FRAGMENT_SHADER, "" } { fShaderFile, GL_FRAGMENT_SHADER, "" }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for ( int i = 0; i < 4; ++i ) for ( int i = 0; i < 4; ++i )
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if ( shaders[i].source.length() == 0 ) if ( shaders[i].source.length() == 0 )
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader( s.type ); GLuint shader = glCreateShader( s.type );
const char *c_str = s.source.c_str(); const char *c_str = s.source.c_str();
glShaderSource(shader, 1, (const GLchar**)&c_str, NULL); glShaderSource(shader, 1, (const GLchar**)&c_str, NULL);
glCompileShader( shader ); glCompileShader( shader );
GLint compiled; GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) if ( !compiled )
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
glAttachShader( program, shader ); glAttachShader( program, shader );
} }
//set shader attrib locations /* link and error check */
const int posLoc = 0; glLinkProgram(program);
const int texCoordLoc = 1;
glBindAttribLocation(program, posLoc, "posAttrib"); GLint linked;
glBindAttribLocation(program, texCoordLoc, "texCoordAttrib"); glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked )
{
std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program);
/* link and error check */ error = true;
glLinkProgram(program); }
GLint linked; if(error == true)
glGetProgramiv( program, GL_LINK_STATUS, &linked ); {
if ( !linked ) return -1;
{ }
std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program);
error = true; /* use program object */
} glUseProgram(program);
if(error == true) return program;
{
return -1;
}
/* use program object */
glUseProgram(program);
return program;
} }
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* gShaderFile, const char* fShaderFile ) GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* gShaderFile, const char* fShaderFile )
{ {
bool error = false; bool error = false;
struct Shader struct Shader
{ {
const char* filename; const char* filename;
GLenum type; GLenum type;
std::string source; std::string source;
} shaders[5] = } shaders[5] =
{ {
{ vShaderFile, GL_VERTEX_SHADER, "" }, { vShaderFile, GL_VERTEX_SHADER, "" },
{ tcShader, GL_TESS_CONTROL_SHADER, "" }, { tcShader, GL_TESS_CONTROL_SHADER, "" },
{ teShader, GL_TESS_EVALUATION_SHADER, "" }, { teShader, GL_TESS_EVALUATION_SHADER, "" },
{ gShaderFile, GL_GEOMETRY_SHADER, "" }, { gShaderFile, GL_GEOMETRY_SHADER, "" },
{ fShaderFile, GL_FRAGMENT_SHADER, "" } { fShaderFile, GL_FRAGMENT_SHADER, "" }
}; };
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
for ( int i = 0; i < 5; ++i ) for ( int i = 0; i < 5; ++i )
{ {
Shader& s = shaders[i]; Shader& s = shaders[i];
s.source = readShaderSource(s.filename); s.source = readShaderSource(s.filename);
if ( shaders[i].source.length() == 0 ) if ( shaders[i].source.length() == 0 )
{ {
std::cerr << "Failed to read " << s.filename << std::endl; std::cerr << "Failed to read " << s.filename << std::endl;
error = true; error = true;
} }
GLuint shader = glCreateShader( s.type ); GLuint shader = glCreateShader( s.type );
const char *c_str = s.source.c_str(); const char *c_str = s.source.c_str();
glShaderSource( shader, 1, (const GLchar**) &c_str, NULL ); glShaderSource( shader, 1, (const GLchar**) &c_str, NULL );
glCompileShader( shader ); glCompileShader( shader );
GLint compiled; GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) if ( !compiled )
{ {
std::cerr << s.filename << " failed to compile:" << std::endl; std::cerr << s.filename << " failed to compile:" << std::endl;
printShaderCompileError(shader); printShaderCompileError(shader);
error = true; error = true;
} }
glAttachShader( program, shader ); glAttachShader( program, shader );
} }
/* link and error check */ /* link and error check */
glLinkProgram(program); glLinkProgram(program);
GLint linked; GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked ); glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) if ( !linked )
{ {
std::cerr << "Shader program failed to link" << std::endl; std::cerr << "Shader program failed to link" << std::endl;
printProgramLinkError(program); printProgramLinkError(program);
error = true; error = true;
} }
if(error == true) if(error == true)
{ {
return -1; return -1;
} }
/* use program object */ /* use program object */
glUseProgram(program); glUseProgram(program);
return program; return program;
} }

View File

@ -1,4 +1,4 @@
#include "uniforms.h" #include "Uniforms.h"
#include <GL/glew.h> #include <GL/glew.h>
namespace Uniforms namespace Uniforms
@ -6,13 +6,11 @@ namespace Uniforms
SceneUniforms SceneData; SceneUniforms SceneData;
LightUniforms LightData; LightUniforms LightData;
MaterialUniforms MaterialData; MaterialUniforms MaterialData;
GeoUniforms GeoData;
//IDs for the buffer objects holding the uniform block data //IDs for the buffer objects holding the uniform block data
GLuint sceneUbo = 0; GLuint scene_ubo = -1;
GLuint lightUbo = 0; GLuint light_ubo = -1;
GLuint materialUbo = 0; GLuint material_ubo = -1;
GLuint geoUbo = 0;
namespace UboBinding namespace UboBinding
{ {
@ -20,7 +18,6 @@ namespace Uniforms
int scene = 0; int scene = 0;
int light = 1; int light = 1;
int material = 2; int material = 2;
int geometry = 4;
}; };
//Locations for the uniforms which are not in uniform blocks //Locations for the uniforms which are not in uniform blocks
@ -33,37 +30,28 @@ namespace Uniforms
void Init() void Init()
{ {
//Create and initialize uniform buffers //Create and initialize uniform buffers
glGenBuffers(1, &Uniforms::sceneUbo); glGenBuffers(1, &Uniforms::scene_ubo);
glBindBuffer(GL_UNIFORM_BUFFER, sceneUbo); glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, sceneUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, scene_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &lightUbo); glGenBuffers(1, &light_ubo);
glBindBuffer(GL_UNIFORM_BUFFER, lightUbo); glBindBuffer(GL_UNIFORM_BUFFER, light_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, lightUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, light_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &materialUbo); glGenBuffers(1, &material_ubo);
glBindBuffer(GL_UNIFORM_BUFFER, materialUbo); glBindBuffer(GL_UNIFORM_BUFFER, material_ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, materialUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, material_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glGenBuffers(1, &geoUbo);
glBindBuffer(GL_UNIFORM_BUFFER, geoUbo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GeoUniforms), &GeoData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null).
glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::geometry, geoUbo); //Associate this uniform buffer with the uniform block in the shader that has the same binding.
glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0);
} }
void BufferSceneData() void BufferSceneData()
{ {
glBindBuffer(GL_UNIFORM_BUFFER, sceneUbo); //Bind the OpenGL UBO before we update the data. glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); //Bind the OpenGL UBO before we update the data.
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values. glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values.
glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo
glBindBuffer(GL_UNIFORM_BUFFER, geoUbo); //Bind the OpenGL UBO before we update the data.
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GeoData), &GeoData); //Upload the new uniform values.
glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo
} }
}; };

View File

@ -1,7 +1,6 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "callbacks.h" #include "callbacks.h"
#include "interface.h"
namespace Callbacks { namespace Callbacks {
Scene* scene_ = nullptr; Scene* scene_ = nullptr;
@ -53,17 +52,11 @@ void Callbacks::MouseButton(GLFWwindow* window, int button, int action, int mods
void Callbacks::Resize(GLFWwindow* window, int width, int height) void Callbacks::Resize(GLFWwindow* window, int width, int height)
{ {
Window* viewport = Interface::GetWindowByName(scene_->windows_, "Viewport"); width = glm::max(1, width);
height = glm::max(1, height);
scene_->window_width = static_cast<int>(viewport->size.x); //Set viewport to cover entire framebuffer
scene_->window_height = static_cast<int>(viewport->size.y); glViewport(0, 0, width, height);
scene_->OnScreenResize(viewport);
//Set aspect ratio used in view matrix calculation //Set aspect ratio used in view matrix calculation
// scene_->window_width = width;
// scene_->window_height = height;
// scene_->Scene::UpdateCamera();
//Scene::Camera::Aspect = float(width) / float(height); //Scene::Camera::Aspect = float(width) / float(height);
//Scene::Camera::UpdateP(); //Scene::Camera::UpdateP();
} }

View File

@ -54,13 +54,6 @@ namespace FBO {
Framebuffer GenerateFramebuffer(int width, int height) { Framebuffer GenerateFramebuffer(int width, int height) {
Framebuffer fbo; Framebuffer fbo;
fbo.id = CreateFramebuffer(); fbo.id = CreateFramebuffer();
UpdateFrameBuffer(fbo, width, height);
return fbo;
}
void UpdateFrameBuffer(Framebuffer& fbo, int width, int height) {
glBindFramebuffer(GL_FRAMEBUFFER, fbo.id); glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
fbo.albedoTexture = CreateTexture(width, height, GL_RGBA); fbo.albedoTexture = CreateTexture(width, height, GL_RGBA);
@ -80,6 +73,8 @@ namespace FBO {
} }
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fbo;
} }
void Bind(const Framebuffer& fbo) { void Bind(const Framebuffer& fbo) {

View File

@ -1,107 +0,0 @@
#include "interface.h"
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <algorithm>
#include <iostream>
#include <filesystem>
namespace Interface {
void ApplyUIScaling(GLFWwindow* window) {
float xScale, yScale;
glfwGetWindowContentScale(window, &xScale, &yScale);
float scale = (xScale + yScale) * 0.5f;
ImGui::GetIO().FontGlobalScale = scale;
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(scale);
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
#ifdef _WIN32
io.Fonts->AddFontFromFileTTF("imgui/misc/fonts/JetBrainsMono/JetBrainsMono-Medium.ttf", 8.0f * scale);
#else
io.Fonts->AddFontFromFileTTF("../imgui/misc/fonts/JetBrainsMono/JetBrainsMono-Medium.ttf", 8.0f * scale);
#endif
io.Fonts->Build();
}
void AddWindow(std::vector<Window>& windows, const std::string& name, std::function<void()> renderFunc) {
windows.emplace_back(name, renderFunc);
}
Window* GetWindowByName(std::vector<Window>& windows, const std::string& name) {
auto it = std::find_if(windows.begin(), windows.end(), [&name](const Window& window) {
return window.name == name;
});
if (it != windows.end()) {
return &(*it); // Return pointer to the found window
} else {
return nullptr; // Return nullptr if the window was not found
}
}
void RenderWindows(std::vector<Window>& windows) {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui::NewFrame();
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
// Style windows
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("TerraVisor", nullptr, window_flags);
ImGui::PopStyleVar(3);
// Submit the DockSpace
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) {
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
}
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Options")) {
ImGui::Text("Nothing Here Yet, Check Back Later!");
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::End();
for (auto& window : windows) {
if (window.isOpen && ImGui::Begin(window.name.c_str(), &window.isOpen)) {
window.size = ImGui::GetWindowSize();
window.position = ImGui::GetWindowPos();
if (window.renderContent) {
window.renderContent();
}
}
ImGui::End();
}
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
}

View File

@ -28,8 +28,6 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <iostream> #include <iostream>
#include <string>
#include <sstream>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
@ -39,10 +37,8 @@
#include <FreeImage.h> #include <FreeImage.h>
#include "config.h"
#include "callbacks.h" #include "callbacks.h"
#include "scene.h" #include "scene.h"
#include "interface.h"
namespace { namespace {
@ -65,11 +61,7 @@ GLFWwindow* CreateGlfwWindow() {
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
#endif #endif
std::stringstream ss; GLFWwindow* window = glfwCreateWindow(kInitWindowWidth, kInitWindowHeight, "TerraVisor", nullptr, nullptr);
ss << PROJECT_NAME << " " << PROJECT_VERSION_MAJOR << "." << PROJECT_VERSION_MINOR << "." << PROJECT_VERSION_PATCH;
std::string title = ss.str();
GLFWwindow* window = glfwCreateWindow(kInitWindowWidth, kInitWindowHeight, title.c_str(), nullptr, nullptr);
if (!window) { if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl; std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate(); glfwTerminate();
@ -157,7 +149,6 @@ int main() {
scene.Init(); scene.Init();
InitializeImGui(window); InitializeImGui(window);
FreeImage_Initialise(); FreeImage_Initialise();
Interface::ApplyUIScaling(window);
// Check if we're in test mode // Check if we're in test mode
const char* testEnv = std::getenv("TEST_MODE"); const char* testEnv = std::getenv("TEST_MODE");

View File

@ -9,6 +9,10 @@
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -21,11 +25,10 @@
#include "scene.h" #include "scene.h"
#include "camera.h" #include "camera.h"
#include "uniforms.h" #include "Uniforms.h"
#include "InitShader.h" #include "InitShader.h"
#include "DebugCallback.h" #include "DebugCallback.h"
#include "load_texture.h" #include "load_texture.h"
#include "interface.h"
namespace { namespace {
@ -88,7 +91,6 @@ void Scene::Init() {
InitBuffers(); InitBuffers();
ReloadShader(); ReloadShader();
InitQuadBuffers(); InitQuadBuffers();
InitUI();
CameraControls::SetPosition(activeCamera_, glm::vec3(1.4f, 1.4f, 0.0f)); CameraControls::SetPosition(activeCamera_, glm::vec3(1.4f, 1.4f, 0.0f));
CameraControls::SetRotation(activeCamera_, -glm::normalize(CameraControls::GetPosition(activeCamera_))); CameraControls::SetRotation(activeCamera_, -glm::normalize(CameraControls::GetPosition(activeCamera_)));
@ -137,7 +139,7 @@ void Scene::GenerateGrid(int divisions, std::vector<Vertex>& verts, std::vector<
// Currently creates a test triangle and initializes its buffers // Currently creates a test triangle and initializes its buffers
void Scene::InitBuffers() { void Scene::InitBuffers() {
int divisions = Uniforms::GeoData.gridDensity; // Number of divisions along one axis of the grid int divisions = 16; // Number of divisions along one axis of the grid
GenerateGrid(divisions, vertices, indices); GenerateGrid(divisions, vertices, indices);
// Create and bind VAO, VBO, and EBO, and pass the data to OpenGL // Create and bind VAO, VBO, and EBO, and pass the data to OpenGL
@ -195,25 +197,6 @@ void Scene::InitQuadBuffers() {
glBindVertexArray(0); glBindVertexArray(0);
} }
void Scene::InitUI() {
Interface::AddWindow(windows_, "Viewport", [this]() {
ImGui::Image((void*)(intptr_t)lht_fbo_.albedoTexture, ImVec2(window_width, window_height), ImVec2(0, 1), ImVec2(1, 0));
});
Interface::AddWindow(windows_, "Scene Settings", [this]() {
// if (ImGui::Button("Quit")) {
// glfwSetWindowShouldClose(window, GLFW_TRUE);
// }
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::SliderFloat("Tessellation Level", &Uniforms::GeoData.maxTessellation, 1.0f, 64.0f);
ImGui::SliderInt("Patch Grid Density", &Uniforms::GeoData.gridDensity, 1, 24);
ImGui::SliderFloat("Max Height", &Uniforms::GeoData.displacementScale, 0.0f, 1.0f);
Window* viewport = Interface::GetWindowByName(windows_, "Viewport");
ImGui::Text("Viewport size: (%.3f, %.3f)", viewport->size.x, viewport->size.y);
});
}
// Allows for runtime shader updates // Allows for runtime shader updates
void Scene::ReloadShader() { void Scene::ReloadShader() {
@ -240,17 +223,13 @@ void Scene::Display(GLFWwindow* window) {
glUseProgram(shader_program_); glUseProgram(shader_program_);
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Window* viewport = Interface::GetWindowByName(windows_, "Viewport"); Uniforms::SceneData.PV = projection_matrix_ * CameraControls::GetViewMatrix(activeCamera_); // Projection-View matrix
if (viewport && viewport->size.x > 0 && viewport->size.y > 0) {
OnScreenResize(viewport);
}
Uniforms::GeoData.PV = projection_matrix_ * CameraControls::GetViewMatrix(activeCamera_); // Projection-View matrix
Uniforms::BufferSceneData(); Uniforms::BufferSceneData();
Uniforms::GeoData.M = glm::rotate(angle_, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::vec3(scale_)); glm::mat4 model_matrix = glm::rotate(angle_, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::scale(glm::vec3(scale_));
glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(model_matrix));
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id); glBindTexture(GL_TEXTURE_2D, tex_id);
@ -269,9 +248,7 @@ void Scene::Display(GLFWwindow* window) {
glPatchParameteri(GL_PATCH_VERTICES, 4); glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, 0); glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, 0);
FBO::Unbind(); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
FBO::Bind(lht_fbo_); FBO::Bind(lht_fbo_);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -298,24 +275,78 @@ void Scene::Display(GLFWwindow* window) {
FBO::Unbind(); FBO::Unbind();
//DrawGui(window); DrawGui(window);
Interface::RenderWindows(windows_);
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
void Scene::OnScreenResize(Window* viewport) { void Scene::DrawGui(GLFWwindow* window) {
if (window_width != static_cast<int>(viewport->size.x) || window_height != static_cast<int>(viewport->size.y)) { // Begin ImGui frame
window_width = static_cast<int>(viewport->size.x); ImGui_ImplOpenGL3_NewFrame();
window_height = static_cast<int>(viewport->size.y); ImGui_ImplGlfw_NewFrame();
UpdateCamera(); // Enable docking
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui::NewFrame();
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
// Add menu bar
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
// Style windows
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("TerraVisor", nullptr, window_flags);
ImGui::PopStyleVar(3);
// Submit the DockSpace
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) {
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
} }
}
void Scene::UpdateViewport() { if (ImGui::BeginMenuBar()) {
window_width = ImGui::GetWindowSize().x; if (ImGui::BeginMenu("Options")) {
window_height = ImGui::GetWindowSize().y; ImGui::Text("Nothing Here Yet, Check Back Later!");
UpdateCamera();
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::End();
// Draw Gui
ImGui::Begin("Terrain Controls");
if (ImGui::Button("Quit")) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::SliderFloat("Tessellation Level", &tessellationFactor, 1.0f, 64.0f);
ImGui::End();
// Draw FBO to ImGui window
ImGui::Begin("Scene Window");
ImVec2 windowSize = ImGui::GetContentRegionAvail();
ImGui::Image((void*)(intptr_t)lht_fbo_.albedoTexture, windowSize, ImVec2(0, 1), ImVec2(1, 0));
ImGui::End();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
} }
void Scene::Idle() { void Scene::Idle() {
@ -352,7 +383,7 @@ std::vector<int16_t> Scene::LoadHGT(const std::string& filename, int width, int
} }
void Scene::UpdateCamera() { void Scene::UpdateCamera() {
projection_matrix_ = glm::perspective(CameraControls::GetFOV(activeCamera_), static_cast<float>(window_width) / window_height, activeCamera_.nearPlane, activeCamera_.farPlane); projection_matrix_ = glm::perspective(CameraControls::GetFOV(activeCamera_), aspect_, activeCamera_.nearPlane, activeCamera_.farPlane);
} }
GLuint Scene::CreateHeightmapTexture(std::vector<int16_t> data, int width, int height) { GLuint Scene::CreateHeightmapTexture(std::vector<int16_t> data, int width, int height) {