Can import .hgt files. TODO refactor

This commit is contained in:
Jack Christensen 2024-08-15 00:56:29 -04:00
parent 136b5cab9c
commit cba45bdecf
7 changed files with 163 additions and 34 deletions

View File

@ -4,10 +4,10 @@ Size=400,400
Collapsed=0
[Window][Terrain Controls]
Pos=0,19
Size=1280,94
Pos=929,19
Size=351,701
Collapsed=0
DockId=0x00000001,0
DockId=0x00000002,0
[Window][DockSpaceViewport_11111111]
Size=1280,720
@ -23,13 +23,13 @@ Size=1280,720
Collapsed=0
[Window][Scene Window]
Pos=0,115
Size=1280,605
Pos=0,19
Size=927,701
Collapsed=0
DockId=0x00000002,0
DockId=0x00000001,0
[Docking][Data]
DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1280,701 Split=Y Selected=0x9F2D9299
DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=1280,94 Selected=0xF69494A7
DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=1280,605 CentralNode=1 Selected=0x9F2D9299
DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1280,701 Split=X Selected=0x9F2D9299
DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=927,701 CentralNode=1 Selected=0x9F2D9299
DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=351,701 Selected=0xF69494A7

View File

@ -3,6 +3,8 @@
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
#include <string>
#include "fbo.h"
@ -16,6 +18,7 @@ class Scene {
void DrawGui(GLFWwindow* window);
void Idle();
void ReloadShader();
std::vector<int16_t> LoadHGT(const std::string& filename, int width, int height);
int window_width;
int window_height;
@ -42,6 +45,9 @@ class Scene {
glm::mat4 projection_matrix_;
void UpdateCamera();
int16_t Scene::SwapEndian(int16_t val);
float NormalizeHeight(int16_t value, int16_t minVal, int16_t maxVal);
GLuint CreateHeightmapTexture(std::vector<int16_t> data, int width, int height);
};
#endif // SCENE_H_

View File

@ -1,7 +1,7 @@
#version 430
precision highp float;
layout(binding = 0) uniform sampler2D diffuse_tex;
layout(binding = 0) uniform sampler2D heightTexture;
layout(location = 1) uniform float time;
layout(std140, binding = 0) uniform SceneUniforms
@ -26,15 +26,12 @@ layout(std140, binding = 2) uniform MaterialUniforms
float shininess; //specular exponent
};
in VertexData
{
vec2 tex_coord;
vec3 pw; //world-space vertex position
vec3 nw; //world-space normal vector
} inData; //block is named 'inData'
in vec3 frag_position;
in VertexData {
vec2 tex_coord;
} inData;
out vec4 frag_color; //the output color for this fragment
void main(void)
@ -58,6 +55,14 @@ void main(void)
// vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess);
// fragcolor = ambient_term + diffuse_term + specular_term;
frag_color = vec4(frag_position, 1.0f);
float height = texture(heightTexture, inData.tex_coord).r;
//frag_color = vec4(inData.tex_coord, 0.0f, 1.0f);
// if (height > 0.8) frag_color = vec4(vec3(1.0f-height), 1.0f);
// else frag_color = vec4(vec3(height), 1.0f);
frag_color = vec4(height, height, height, 1.0);
}

View File

@ -2,10 +2,19 @@
layout(vertices = 4) out; // Define the number of control points per patch (e.g., 4 for a quad)
in VertexData {
vec2 tex_coord;
} inData[];
out VertexData {
vec2 tex_coord;
} outData[];
void main()
{
// Pass through control points to the tessellation evaluation shader
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
outData[gl_InvocationID].tex_coord = inData[gl_InvocationID].tex_coord;
// Set the tessellation levels (outer and inner)
if (gl_InvocationID == 0) {

View File

@ -10,8 +10,16 @@ layout(std140, binding = 0) uniform SceneUniforms
vec4 eye_w; //world-space eye position
};
in VertexData {
vec2 tex_coord;
} inData[];
out vec3 frag_position; // Ensure this matches the input in fragment.glsl
out VertexData {
vec2 tex_coord;
} outData;
void main()
{
// Interpolate the position using the barycentric coordinates from tessellation
@ -21,5 +29,9 @@ void main()
frag_position = pos;
outData.tex_coord = mix(mix(inData[0].tex_coord, inData[1].tex_coord, gl_TessCoord.x),
mix(inData[3].tex_coord, inData[2].tex_coord, gl_TessCoord.x),
gl_TessCoord.y);
gl_Position = PV*M*vec4(pos, 1.0);
}

View File

@ -11,8 +11,15 @@ layout(location = 0) in vec3 pos_attrib;
layout(location = 1) in vec2 tex_coord_attrib;
layout(location = 2) in vec3 normal_attrib;
out VertexData
{
vec2 tex_coord;
} outData;
void main() {
gl_Position = vec4(pos_attrib, 1.0);
outData.tex_coord = tex_coord_attrib; //send tex_coord to fragment shader
}

View File

@ -15,6 +15,9 @@
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdint>
#include <algorithm>
#include "scene.h"
#include "Uniforms.h"
@ -32,6 +35,10 @@ const std::string kFragmentShaderPath = "shaders/fragment.glsl";
const std::string kQuadVertexPath = "shaders/quad_vertex.glsl";
const std::string kQuadFragmentPath = "shaders/quad_fragment.glsl";
const std::string kHGTPath = "C:/Users/jmchr/Downloads/N02E016.SRTMGL1.hgt/N02E016.hgt";
GLuint tex_id = -1;
} // namespace
Scene::Scene(int width, int height)
@ -46,7 +53,7 @@ Scene::Scene(int width, int height)
aspect_(static_cast<float>(width) / static_cast<float>(height)),
near_z_(0.01f),
far_z_(100.0f),
fov_(glm::pi<float>() / 4.0f)
fov_(glm::pi<float>() / 8.0f)
{}
Scene::~Scene() {
@ -68,6 +75,9 @@ void Scene::Init() {
fbo_.Init(window_width, window_height);
post_fbo_.Init(window_width, window_height);
std::vector<int16_t> heightData = LoadHGT(kHGTPath, 3601, 3601);
tex_id = CreateHeightmapTexture(heightData, 3601, 3601);
InitBuffers();
ReloadShader();
InitQuadBuffers();
@ -80,21 +90,13 @@ void Scene::Init() {
// Currently creates a test triangle and initializes its buffers
void Scene::InitBuffers() {
GLuint patch_vbo;
// Quad vertices in 3D space
// float patchVertices[] = {
// -0.5f, 0.0f, -0.5f, // Bottom-left
// 0.5f, 0.0f, -0.5f, // Bottom-right
// 0.5f, 0.0f, 0.5f, // Top-right
// -0.5f, 0.0f, 0.5f // Top-left
// };
float patchVertices[] = {
-0.5f, -0.5f, 0.0f, // Bottom-left
0.5f, -0.5f, 0.0f, // Bottom-right
0.5f, 0.5f, 0.0f, // Top-right
-0.5f, 0.5f, 0.0f // Top-left
// Positions // Texture Coords
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // Bottom-left
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // Bottom-right
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // Top-right
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // Top-left
};
glGenVertexArrays(1, &vao_);
@ -106,7 +108,11 @@ void Scene::InitBuffers() {
// Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
// Texture coordinate attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glBindVertexArray(0);
}
@ -163,13 +169,19 @@ void Scene::Display(GLFWwindow* window) {
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
view_matrix_ = glm::lookAt(glm::vec3(0.0f, 2.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
view_matrix_ = glm::lookAt(glm::vec3(1.2f, 1.2f, 1.2f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
Uniforms::SceneData.PV = projection_matrix_ * view_matrix_; // Projection-View matrix
Uniforms::BufferSceneData();
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);
glBindTexture(GL_TEXTURE_2D, tex_id);
GLint heightTextureLoc = glGetUniformLocation(shader_program_, "heightTexture");
glUniform1i(heightTextureLoc, 0);
glBindVertexArray(vao_);
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawArrays(GL_PATCHES, 0, 4);
@ -272,6 +284,84 @@ void Scene::Idle() {
}
int16_t Scene::SwapEndian(int16_t val) {
return (val << 8) | ((val >> 8) & 0xFF);
}
std::vector<int16_t> Scene::LoadHGT(const std::string& filename, int width, int height) {
std::ifstream file(filename, std::ios::binary);
std::vector<int16_t> elevationData;
if (file) {
for (int i = 0; i < width * height; ++i) {
int16_t value;
file.read(reinterpret_cast<char*>(&value), sizeof(int16_t));
// Handle endianness
value = SwapEndian(value);
if (value == -32768) {
value = -32767; // Clamp no-data values
}
elevationData.push_back(value);
}
} else {
std::cerr << "Failed to open HGT file!" << std::endl;
}
return elevationData;
}
void Scene::UpdateCamera() {
projection_matrix_ = glm::perspective(fov_, aspect_, near_z_, far_z_);
}
// HGT files are 16bit integers whereas OpenGL prefers floating point values for color data
float Scene::NormalizeHeight(int16_t value, int16_t minVal, int16_t maxVal) {
return static_cast<float>(value - minVal) / (maxVal - minVal);
}
GLuint Scene::CreateHeightmapTexture(std::vector<int16_t> data, int width, int height) {
int16_t minVal = *std::min_element(data.begin(), data.end());
int16_t maxVal = *std::max_element(data.begin(), data.end());
std::cout << "Min Val: " << minVal << "\n";
std::cout << "Max Val: " << maxVal << std::endl;
std::vector<float> floatData;
for (int16_t &d : data) {
// Normalize the value between 0 and 1 based on the min/max range
d = static_cast<int16_t>(
255 * (d - minVal) / (maxVal - minVal)
);
floatData.push_back(static_cast<float>(d / 255.0f));
//floatData.push_back((static_cast<float>(d) / 32767.0f + 1.0f) / 2.0f);
}
minVal = *std::min_element(data.begin(), data.end());
maxVal = *std::max_element(data.begin(), data.end());
std::cout << "Min Val: " << minVal << "\n";
std::cout << "Max Val: " << maxVal << std::endl;
float minFloatVal = *std::min_element(floatData.begin(), floatData.end());
float maxFloatVal = *std::max_element(floatData.begin(), floatData.end());
std::cout << "Min Float Val: " << minFloatVal << "\n";
std::cout << "Max Float Val: " << maxFloatVal << std::endl;
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, floatData.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return textureID;
}