mirror of
https://github.com/brammie15/VoxelRenderer.git
synced 2025-12-16 10:01:47 +01:00
Add MC
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
[Bb]uild/*
|
[Bb]uild/*
|
||||||
!*/.gitkeep
|
!*/.gitkeep
|
||||||
|
|
||||||
|
cmake-build-debug/*
|
||||||
|
|||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
1
.idea/.name
generated
Normal file
1
.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
|||||||
|
gloom
|
||||||
2
.idea/VoxelEngine.iml
generated
Normal file
2
.idea/VoxelEngine.iml
generated
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||||
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/VoxelEngine.iml" filepath="$PROJECT_DIR$/.idea/VoxelEngine.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -4,6 +4,12 @@
|
|||||||
cmake_minimum_required (VERSION 3.0)
|
cmake_minimum_required (VERSION 3.0)
|
||||||
project (gloom)
|
project (gloom)
|
||||||
|
|
||||||
|
# set c++ 17
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# CMake setup
|
# CMake setup
|
||||||
#
|
#
|
||||||
@@ -78,3 +84,15 @@ target_link_libraries (${PROJECT_NAME}
|
|||||||
${GLAD_LIBRARIES})
|
${GLAD_LIBRARIES})
|
||||||
set_target_properties (${PROJECT_NAME} PROPERTIES
|
set_target_properties (${PROJECT_NAME} PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
|
||||||
|
## Copy shaders to build directory with a symlink
|
||||||
|
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||||
|
${CMAKE_SOURCE_DIR}/gloom/shaders
|
||||||
|
$<TARGET_FILE_DIR:${PROJECT_NAME}>/shaders)
|
||||||
|
|
||||||
|
## Copy assets folder to build folder
|
||||||
|
|
||||||
|
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_SOURCE_DIR}/gloom/assets
|
||||||
|
$<TARGET_FILE_DIR:${PROJECT_NAME}>/assets)
|
||||||
|
|||||||
BIN
gloom/assets/dirt.png
Normal file
BIN
gloom/assets/dirt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -1,8 +1,17 @@
|
|||||||
#version 430 core
|
#version 460 core
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec3 ourColor;
|
||||||
|
in vec2 TexCoord;
|
||||||
|
in vec3 pos;
|
||||||
|
|
||||||
|
uniform sampler2D ourTexture;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
FragColor = texture(ourTexture, TexCoord);
|
||||||
}
|
// FragColor = vec4(1.0f, TexCoord.x, 1.0f, 1.0);
|
||||||
|
// FragColor = vec4(137 / 255, 85 / 255, 95 / 255, 1.0f);
|
||||||
|
}
|
||||||
34
gloom/shaders/simple.shader
Normal file
34
gloom/shaders/simple.shader
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aColor;
|
||||||
|
layout (location = 2) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
out vec3 ourColor;
|
||||||
|
out vec2 TexCoord;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||||
|
ourColor = aColor;
|
||||||
|
TexCoord = aTexCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec3 ourColor;
|
||||||
|
in vec2 TexCoord;
|
||||||
|
|
||||||
|
uniform sampler2D ourTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = texture(ourTexture, TexCoord);
|
||||||
|
// FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0);
|
||||||
|
}
|
||||||
@@ -1,8 +1,20 @@
|
|||||||
#version 430 core
|
#version 460 core
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
in vec3 position;
|
layout (location = 0) in vec3 aPos;
|
||||||
|
//layout (location = 1) in vec3 aColor;
|
||||||
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec3 pos;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = vec4(position, 1.0f);
|
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||||
}
|
TexCoord = aTexCoord;
|
||||||
|
pos = aPos;
|
||||||
|
}
|
||||||
5
gloom/src/Block.cpp
Normal file
5
gloom/src/Block.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 26/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Block.h"
|
||||||
26
gloom/src/Block.h
Normal file
26
gloom/src/Block.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 26/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_BLOCK_H
|
||||||
|
#define GLOOM_BLOCK_H
|
||||||
|
|
||||||
|
//This will hold all the data of a block, but not the mesh since this is held by the chunk
|
||||||
|
|
||||||
|
|
||||||
|
#include "BlockType.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Block {
|
||||||
|
public:
|
||||||
|
Block(BlockType type) : m_type(type) {}
|
||||||
|
|
||||||
|
BlockType getType() const { return m_type; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
BlockType m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_BLOCK_H
|
||||||
17
gloom/src/BlockType.h
Normal file
17
gloom/src/BlockType.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 26/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_BLOCKTYPE_H
|
||||||
|
#define GLOOM_BLOCKTYPE_H
|
||||||
|
|
||||||
|
enum class BlockType{
|
||||||
|
AIR = 0,
|
||||||
|
DIRT = 1,
|
||||||
|
STONE = 2,
|
||||||
|
GONCALO = 3,
|
||||||
|
SNOW = 4,
|
||||||
|
GRASS = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GLOOM_BLOCKTYPE_H
|
||||||
134
gloom/src/Chunk.cpp
Normal file
134
gloom/src/Chunk.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 25/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Chunk.h"
|
||||||
|
#include "gloom/Mesh.h"
|
||||||
|
#include "Cube.h"
|
||||||
|
#include "gloom/Singleton.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Chunk::loadBlocks() {
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_HEIGHT; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
|
glm::vec3 actualPos = glm::vec3(x, y, z) + glm::vec3(m_chunkPos.x * CHUNK_SIZE, 0, m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
BlockType blockType = generateTerrain(actualPos);
|
||||||
|
if (m_blocks[x][y][z] != nullptr) {
|
||||||
|
delete m_blocks[x][y][z];
|
||||||
|
}
|
||||||
|
m_blocks[x][y][z] = new Block(blockType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chunk::loadMesh() {
|
||||||
|
std::vector<Mesh::Vertex> vertexes{};
|
||||||
|
std::vector<unsigned int> indices{};
|
||||||
|
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_HEIGHT; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
|
//Check direction and call LoadFace on that direction
|
||||||
|
Block* block = this->getBlock(x, y, z);
|
||||||
|
if (block->getType() != BlockType::AIR) {
|
||||||
|
BlockType type = block->getType();
|
||||||
|
//Get the block in world space using World::GetInstance().getBlock
|
||||||
|
Block* leftBlock = World::GetInstance().getBlock(x - 1 + m_chunkPos.x * CHUNK_SIZE, y, z + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
Block* rightBlock = World::GetInstance().getBlock(x + 1 + m_chunkPos.x * CHUNK_SIZE, y, z + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
Block* bottomBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y - 1, z + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
Block* topBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y + 1, z + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
Block* backBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y, z - 1 + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
Block* frontBlock = World::GetInstance().getBlock(x + m_chunkPos.x * CHUNK_SIZE, y, z + 1 + m_chunkPos.y * CHUNK_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (leftBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::LEFT, vertexes, indices, glm::vec3(x, y, z), type);
|
||||||
|
}
|
||||||
|
if (rightBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::RIGHT, vertexes, indices, glm::vec3(x, y, z),type);
|
||||||
|
}
|
||||||
|
if (bottomBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::BOTTOM, vertexes, indices, glm::vec3(x, y, z), type);
|
||||||
|
}
|
||||||
|
if (topBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::TOP, vertexes, indices, glm::vec3(x, y, z), type);
|
||||||
|
}
|
||||||
|
if (backBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::FRONT, vertexes, indices, glm::vec3(x, y, z), type);
|
||||||
|
}
|
||||||
|
if (frontBlock->getType() == BlockType::AIR) {
|
||||||
|
Cube::LoadFace(Face::BACK, vertexes, indices, glm::vec3(x, y, z), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mesh = Mesh(vertexes, indices);
|
||||||
|
m_mesh.setPosition(glm::vec3(m_chunkPos.x * CHUNK_SIZE, 0, m_chunkPos.y * CHUNK_SIZE));
|
||||||
|
m_mesh.setupMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk::Chunk(const glm::vec2 &pos): m_chunkPos(pos) {
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_HEIGHT; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
|
m_blocks[x][y][z] = new Block(BlockType::AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockType Chunk::generateTerrain(glm::vec3 position) {
|
||||||
|
double noise = perlin.octave2D_01((position.x * 0.01), (position.z * 0.01), 4);
|
||||||
|
noise = pow(noise, 3);
|
||||||
|
int height = noise * 70;
|
||||||
|
if (position.y > height) {
|
||||||
|
return BlockType::AIR;
|
||||||
|
}
|
||||||
|
else if (position.y == height) {
|
||||||
|
//snow
|
||||||
|
int variance = ((float)rand() / RAND_MAX) * 7; //between 0-7
|
||||||
|
if (position.y > 20 + variance)
|
||||||
|
return BlockType::SNOW; //snow
|
||||||
|
return BlockType::GRASS; //grass
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return BlockType::DIRT; //dirt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk::Chunk() {
|
||||||
|
// m_chunkPos = glm::vec2(0, 0);
|
||||||
|
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_HEIGHT; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
|
m_blocks[x][y][z] = new Block(BlockType::AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk::~Chunk() {
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; ++x) {
|
||||||
|
for (int y = 0; y < CHUNK_HEIGHT; ++y) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; ++z) {
|
||||||
|
delete m_blocks[x][y][z]; // Delete each dynamically allocated Block
|
||||||
|
m_blocks[x][y][z] = nullptr; // Set the pointer to nullptr to avoid dangling references
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
69
gloom/src/Chunk.h
Normal file
69
gloom/src/Chunk.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 25/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_CHUNK_H
|
||||||
|
#define GLOOM_CHUNK_H
|
||||||
|
|
||||||
|
#include "gloom/config.hpp"
|
||||||
|
#include "gloom/Mesh.h"
|
||||||
|
#include "gloom/PerlinNoise.hpp"
|
||||||
|
#include "BlockType.h"
|
||||||
|
#include "Block.h"
|
||||||
|
|
||||||
|
enum class ChunkLoadStatus{
|
||||||
|
GENERATED,
|
||||||
|
GENERATING,
|
||||||
|
NOT_GENERATED,
|
||||||
|
NOT_AVAILABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int BLOCK_TYPES_COUNT = 4;
|
||||||
|
|
||||||
|
class Chunk {
|
||||||
|
public:
|
||||||
|
Chunk();
|
||||||
|
Chunk(const glm::vec2& pos);
|
||||||
|
|
||||||
|
~Chunk();
|
||||||
|
|
||||||
|
void loadBlocks();
|
||||||
|
void loadMesh();
|
||||||
|
|
||||||
|
void Draw(GLuint shaderProgram) {
|
||||||
|
m_mesh.draw(shaderProgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh m_mesh;
|
||||||
|
|
||||||
|
BlockType generateTerrain(glm::vec3 position);
|
||||||
|
|
||||||
|
Block* getBlock(int x, int y, int z) {
|
||||||
|
//if out of bounds, return dirt
|
||||||
|
if (x < 0 || x >= CHUNK_SIZE || y < 0 || y >= CHUNK_HEIGHT || z < 0 || z >= CHUNK_SIZE) {
|
||||||
|
return new Block(BlockType::AIR);
|
||||||
|
} else {
|
||||||
|
if(m_blocks[x][y][z] == nullptr) {
|
||||||
|
return new Block(BlockType::AIR);
|
||||||
|
} else {
|
||||||
|
return m_blocks[x][y][z];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBlock(int x, int y, int z, const Block& block) {
|
||||||
|
m_blocks[x][y][z] = new Block(block.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Block* m_blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE]{ nullptr };
|
||||||
|
|
||||||
|
glm::vec3 m_position;
|
||||||
|
glm::vec2 m_chunkPos;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_CHUNK_H
|
||||||
140
gloom/src/Cube.cpp
Normal file
140
gloom/src/Cube.cpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Cube.h"
|
||||||
|
|
||||||
|
glm::vec3 unitVertices[8] = {
|
||||||
|
glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(1.0f, 0.0f, 1.0f),
|
||||||
|
glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int faceVertices[6][4] = {
|
||||||
|
{3, 2, 6, 7},
|
||||||
|
{1, 0, 4, 5},
|
||||||
|
{4, 0, 3, 7},
|
||||||
|
{1, 5, 6, 2},
|
||||||
|
// FRONT (0, 1, 2, 3)
|
||||||
|
{0, 1, 2, 3},
|
||||||
|
// BACK (5, 4, 7, 6)
|
||||||
|
{5, 4, 7, 6}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const glm::vec2 DIRTCOORDS = Cube::getTexCoords(0);
|
||||||
|
static const glm::vec2 STONECOORDS = Cube::getTexCoords(1);
|
||||||
|
static const glm::vec2 GONCALOCOORDS = Cube::getTexCoords(2);
|
||||||
|
static const glm::vec2 GRASSCOORDS = Cube::getTexCoords(3);
|
||||||
|
static const glm::vec2 SNOWCOORDS = Cube::getTexCoords(4);
|
||||||
|
|
||||||
|
Cube::Cube(const glm::vec3 &position, BlockType blockType) : position(position), texture("assets/dirt.png"),
|
||||||
|
type(blockType) {
|
||||||
|
// setupCube();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cube::LoadFace(Face face, std::vector<Mesh::Vertex> &vertices, std::vector<unsigned int> &indices, const glm::vec3 &position, BlockType type) {
|
||||||
|
|
||||||
|
glm::vec3 normal;
|
||||||
|
switch (face) {
|
||||||
|
case Face::TOP:
|
||||||
|
normal = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case Face::BOTTOM:
|
||||||
|
normal = glm::vec3(0.0f, -1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case Face::LEFT:
|
||||||
|
normal = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case Face::RIGHT:
|
||||||
|
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case Face::FRONT:
|
||||||
|
normal = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case Face::BACK:
|
||||||
|
normal = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
glm::vec2 textureOffset = glm::vec2(0.0f, 0.0f);
|
||||||
|
|
||||||
|
switch(type){
|
||||||
|
case BlockType::STONE:
|
||||||
|
textureOffset = STONECOORDS;
|
||||||
|
break;
|
||||||
|
case BlockType::DIRT:
|
||||||
|
textureOffset = DIRTCOORDS;
|
||||||
|
break;
|
||||||
|
case BlockType::GONCALO:
|
||||||
|
textureOffset = GONCALOCOORDS;
|
||||||
|
break;
|
||||||
|
case BlockType::GRASS:
|
||||||
|
textureOffset = GRASSCOORDS;
|
||||||
|
break;
|
||||||
|
case BlockType::SNOW:
|
||||||
|
textureOffset = SNOWCOORDS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 uvCoordinates[4] = {
|
||||||
|
glm::vec2(textureOffset.x, textureOffset.y + CELL_HEIGHT),
|
||||||
|
glm::vec2(textureOffset.x + CELL_WIDTH, textureOffset.y + CELL_HEIGHT),
|
||||||
|
glm::vec2(textureOffset.x + CELL_WIDTH, textureOffset.y),
|
||||||
|
glm::vec2(textureOffset.x, textureOffset.y)
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int index = vertices.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
unsigned int vertexIndex = faceVertices[faceToIndex(face)][i];
|
||||||
|
Mesh::Vertex v;
|
||||||
|
v.position = unitVertices[vertexIndex] + position;
|
||||||
|
v.texCoords = uvCoordinates[i];
|
||||||
|
vertices.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
indices.push_back(index);
|
||||||
|
indices.push_back(index + 1);
|
||||||
|
indices.push_back(index + 2);
|
||||||
|
indices.push_back(index);
|
||||||
|
indices.push_back(index + 2);
|
||||||
|
indices.push_back(index + 3);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cube::LoadAllFaces(std::vector<Mesh::Vertex> &vertices, std::vector<unsigned int> &indices, const glm::vec3 &position, BlockType type) {
|
||||||
|
Cube::LoadFace(Face::TOP, vertices, indices, position, type);
|
||||||
|
Cube::LoadFace(Face::BOTTOM, vertices, indices, position, type);
|
||||||
|
Cube::LoadFace(Face::LEFT, vertices, indices, position, type);
|
||||||
|
Cube::LoadFace(Face::RIGHT, vertices, indices, position, type);
|
||||||
|
Cube::LoadFace(Face::FRONT, vertices, indices, position, type);
|
||||||
|
Cube::LoadFace(Face::BACK, vertices, indices, position, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Cube::faceToIndex(Face face) {
|
||||||
|
switch (face) {
|
||||||
|
case Face::TOP:
|
||||||
|
return 0;
|
||||||
|
case Face::BOTTOM:
|
||||||
|
return 1;
|
||||||
|
case Face::LEFT:
|
||||||
|
return 2;
|
||||||
|
case Face::RIGHT:
|
||||||
|
return 3;
|
||||||
|
case Face::FRONT:
|
||||||
|
return 4;
|
||||||
|
case Face::BACK:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::dvec2 Cube::getTexCoords(int pos) {
|
||||||
|
int x = pos % TEXTURE_WIDTH;
|
||||||
|
int y = pos / 16;
|
||||||
|
return glm::vec2(x * CELL_WIDTH, y * CELL_HEIGHT);
|
||||||
|
}
|
||||||
62
gloom/src/Cube.h
Normal file
62
gloom/src/Cube.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_CUBE_H
|
||||||
|
#define GLOOM_CUBE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <array>
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "gloom/Texture.h"
|
||||||
|
#include "gloom/config.hpp"
|
||||||
|
#include "Chunk.h"
|
||||||
|
#include "gloom/Mesh.h"
|
||||||
|
|
||||||
|
struct CubeVertex {
|
||||||
|
CubeVertex(glm::vec3 pos, glm::vec3 color, glm::vec2 texCoords) : position(pos), color(color),
|
||||||
|
texCoords(texCoords) {};
|
||||||
|
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 color;
|
||||||
|
glm::vec2 texCoords;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum Face {
|
||||||
|
TOP = 0x01, // 0000 0001
|
||||||
|
BOTTOM = 0x02, // 0000 0010
|
||||||
|
LEFT = 0x04, // 0000 0100
|
||||||
|
RIGHT = 0x08, // 0000 1000
|
||||||
|
FRONT = 0x10, // 0001 0000
|
||||||
|
BACK = 0x20 // 0010 0000
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Cube {
|
||||||
|
public:
|
||||||
|
explicit Cube(const glm::vec3 &position, BlockType blockType);
|
||||||
|
|
||||||
|
|
||||||
|
static void LoadFace(Face face, std::vector<Mesh::Vertex>& vertices, std::vector<unsigned int>& indices, const glm::vec3& position, BlockType type);
|
||||||
|
static void LoadAllFaces(std::vector<Mesh::Vertex>& vertices, std::vector<unsigned int>& indices, const glm::vec3& position, BlockType type);
|
||||||
|
|
||||||
|
static int faceToIndex(Face face);
|
||||||
|
|
||||||
|
static glm::dvec2 getTexCoords(int pos);
|
||||||
|
|
||||||
|
Mesh* mesh;
|
||||||
|
private:
|
||||||
|
glm::vec3 position;
|
||||||
|
|
||||||
|
Texture texture;
|
||||||
|
BlockType type{ BlockType::AIR };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_CUBE_H
|
||||||
273
gloom/src/Game.cpp
Normal file
273
gloom/src/Game.cpp
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "gloom/config.hpp"
|
||||||
|
#include "gloom/Camera.h"
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// A callback which allows GLFW to report errors whenever they occur
|
||||||
|
static void glfwErrorCallback(int error, const char *description) {
|
||||||
|
fprintf(stderr, "GLFW returned an error:\n\t%s (%i)\n", description, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
|
||||||
|
glm::vec2 mousePos((float) xpos, (float) -ypos);
|
||||||
|
|
||||||
|
Camera::getInstance().updateMouse(mousePos);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::Game() {
|
||||||
|
// Initialise GLFW
|
||||||
|
if (!glfwInit()) {
|
||||||
|
fprintf(stderr, "Could not start GLFW\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set core window options (adjust version numbers if needed)
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
// Enable the GLFW runtime error callback function defined previously.
|
||||||
|
glfwSetErrorCallback(glfwErrorCallback);
|
||||||
|
// We to good for errors
|
||||||
|
|
||||||
|
// Set additional window options
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, windowResizable);
|
||||||
|
// glfwWindowHint(GLFW_SAMPLES, windowSamples); // MSAA
|
||||||
|
|
||||||
|
// glDisable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
|
// Create window using GLFW
|
||||||
|
m_window = glfwCreateWindow(windowWidth,
|
||||||
|
windowHeight,
|
||||||
|
windowTitle.c_str(),
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
// Ensure the window is set up correctly
|
||||||
|
if (!m_window) {
|
||||||
|
fprintf(stderr, "Could not open GLFW window\n");
|
||||||
|
//Get the error and print it
|
||||||
|
const char *description;
|
||||||
|
int error = glfwGetError(&description);
|
||||||
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the window be the current OpenGL context and initialise glad
|
||||||
|
glfwMakeContextCurrent(m_window);
|
||||||
|
gladLoadGL();
|
||||||
|
|
||||||
|
// Print various OpenGL information to stdout
|
||||||
|
printf("%s: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
|
||||||
|
printf("GLFW\t %s\n", glfwGetVersionString());
|
||||||
|
printf("OpenGL\t %s\n", glGetString(GL_VERSION));
|
||||||
|
printf("GLSL\t %s\n\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
|
||||||
|
// Set up the mouse callback
|
||||||
|
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
glfwSetCursorPosCallback(m_window, mouse_callback);
|
||||||
|
|
||||||
|
// Set up the shader
|
||||||
|
m_shader.setShader("shaders/simple.vert", "shaders/simple.frag");
|
||||||
|
|
||||||
|
// Set up the block
|
||||||
|
// // 16 x 16
|
||||||
|
// for (int x = 0; x < CHUNK_SIZE; x+=1) {
|
||||||
|
// for(int y = 0; y < CHUNK_HEIGHT / 4; y+=1) {
|
||||||
|
// for (int z = 0; z < CHUNK_SIZE; z+=1) {
|
||||||
|
// BlockType type = static_cast<BlockType>(rand() % 3);
|
||||||
|
// m_cubes.emplace_back(glm::vec3(x, y, z), type);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// //10 x 10 chunk
|
||||||
|
// for (int i = 0; i < 10; ++i) {
|
||||||
|
// for (int j = 0; j < 10; ++j) {
|
||||||
|
// m_chunks.push_back(new Chunk(glm::vec2(i, j)));
|
||||||
|
// m_chunks[m_chunks.size() - 1]->loadBlocks();
|
||||||
|
// m_chunks[m_chunks.size() - 1]->loadMesh();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
m_world = &World::GetInstance();
|
||||||
|
m_world->generateChunk(0, 0);
|
||||||
|
// m_world->generateChunk(1, 0);
|
||||||
|
// m_world->getChunk(0, 0)->loadMesh();
|
||||||
|
// m_world->generateChunk(0, 1);
|
||||||
|
// m_world->generateChunk(1, 1);
|
||||||
|
// m_world->getChunk(1, 0)->loadMesh();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game() {
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::run() {
|
||||||
|
// Enable depth (Z) buffer (accept "closest" fragment)
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
|
// Configure miscellaneous OpenGL settings
|
||||||
|
// glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
// Set default colour after clearing the colour buffer
|
||||||
|
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
|
||||||
|
|
||||||
|
double lastChunkUpdate = glfwGetTime();
|
||||||
|
|
||||||
|
// Set up your scene here (create Vertex Array Objects, etc.)
|
||||||
|
|
||||||
|
// Rendering Loop
|
||||||
|
while (!glfwWindowShouldClose(this->m_window)) {
|
||||||
|
|
||||||
|
// Calculate delta time
|
||||||
|
double currentTime = glfwGetTime();
|
||||||
|
m_deltaTime = currentTime - m_lastFrameTime;
|
||||||
|
m_lastFrameTime = currentTime;
|
||||||
|
|
||||||
|
// // wait until next frame with fps
|
||||||
|
// while (glfwGetTime() - m_lastFrameTime < 1.0 / MAX_FPS) {
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Clear colour and depth buffers
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Draw your scene here
|
||||||
|
|
||||||
|
// Set the shader program
|
||||||
|
m_shader.use();
|
||||||
|
glViewport(0, 0, windowWidth, windowHeight);
|
||||||
|
|
||||||
|
m_shader.setMat4("view", Camera::getInstance().getViewMatrix());
|
||||||
|
m_shader.setMat4("projection", Camera::getInstance().projectionMatrix);
|
||||||
|
|
||||||
|
|
||||||
|
// for (auto &chunk: m_chunks) {
|
||||||
|
// chunk->Draw(m_shader.ID);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
m_world->Draw(m_shader.ID, Camera::getInstance().camPos);
|
||||||
|
//
|
||||||
|
// // if player is above chunk that is not generated, generate it, add a variance of the renderdistance
|
||||||
|
int playerX = (int) Camera::getInstance().camPos.x / CHUNK_SIZE;
|
||||||
|
int playerZ = (int) Camera::getInstance().camPos.z / CHUNK_SIZE;
|
||||||
|
|
||||||
|
if(glfwGetTime() - lastChunkUpdate > 0.5) {
|
||||||
|
lastChunkUpdate = glfwGetTime();
|
||||||
|
for (int x = playerX - RENDER_DISTANCE; x < playerX + RENDER_DISTANCE; x++) {
|
||||||
|
for (int z = playerZ - RENDER_DISTANCE; z < playerZ + RENDER_DISTANCE; z++) {
|
||||||
|
if (m_world->isChunkGenerated(x,z) == ChunkLoadStatus::NOT_GENERATED) {
|
||||||
|
m_world->generateChunk(x, z);
|
||||||
|
//Now take the 4 chunks next to it and update those
|
||||||
|
//
|
||||||
|
if (m_world->isChunkGenerated(x + 1, z) == ChunkLoadStatus::GENERATED) {
|
||||||
|
m_world->getChunk(x + 1, z)->loadMesh();
|
||||||
|
}
|
||||||
|
if (m_world->isChunkGenerated(x - 1, z) == ChunkLoadStatus::GENERATED) {
|
||||||
|
m_world->getChunk(x - 1, z)->loadMesh();
|
||||||
|
}
|
||||||
|
if (m_world->isChunkGenerated(x, z + 1) == ChunkLoadStatus::GENERATED) {
|
||||||
|
m_world->getChunk(x, z + 1)->loadMesh();
|
||||||
|
}
|
||||||
|
if (m_world->isChunkGenerated(x, z - 1) == ChunkLoadStatus::GENERATED) {
|
||||||
|
m_world->getChunk(x, z - 1)->loadMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
// Handle other events
|
||||||
|
glfwPollEvents();
|
||||||
|
this->handleKeyboard();
|
||||||
|
|
||||||
|
// Flip buffers
|
||||||
|
glfwSwapBuffers(this->m_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::handleKeyboard() {
|
||||||
|
if (glfwGetKey(m_window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||||
|
glfwSetWindowShouldClose(m_window, GL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 moveDir(0, 0, 0);
|
||||||
|
|
||||||
|
//movement
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_W) == GLFW_PRESS)
|
||||||
|
moveDir.z -= 1; // Move forward
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_S) == GLFW_PRESS)
|
||||||
|
moveDir.z += 1; // Move backward
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_A) == GLFW_PRESS)
|
||||||
|
moveDir.x -= 1; // Move left
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_D) == GLFW_PRESS)
|
||||||
|
moveDir.x += 1; // Move right
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_E) == GLFW_PRESS)
|
||||||
|
moveDir.y += 1;
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_Q) == GLFW_PRESS)
|
||||||
|
moveDir.y -= 1;
|
||||||
|
|
||||||
|
if (length(moveDir) > 0)
|
||||||
|
Camera::getInstance().updatePos(normalize(moveDir), m_deltaTime);
|
||||||
|
|
||||||
|
static bool lastR = false; //Kinda shitty but damm i could not care less
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_R) == GLFW_PRESS && !lastR) {
|
||||||
|
renderWireframe = !renderWireframe;
|
||||||
|
lastR = true;
|
||||||
|
} else if (glfwGetKey(this->m_window, GLFW_KEY_R) == GLFW_RELEASE) {
|
||||||
|
lastR = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unlock mouse
|
||||||
|
static bool keyWasPressed = false;
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_T) == GLFW_PRESS) {
|
||||||
|
if (!keyWasPressed) {
|
||||||
|
m_isMouseLocked = !m_isMouseLocked; // Toggle the state
|
||||||
|
glfwSetInputMode(this->m_window, GLFW_CURSOR, m_isMouseLocked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
|
||||||
|
keyWasPressed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keyWasPressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool balls = false;
|
||||||
|
if (glfwGetKey(this->m_window, GLFW_KEY_F) == GLFW_PRESS) {
|
||||||
|
if (!balls) {
|
||||||
|
//Random number between 1234u and 500u
|
||||||
|
SEED = rand() * 10000u;
|
||||||
|
perlin = siv::PerlinNoise(SEED);
|
||||||
|
m_world->generateChunk(1, 0);
|
||||||
|
m_world->generateChunk(0, 1);
|
||||||
|
m_world->generateChunk(0, 0);
|
||||||
|
m_world->generateChunk(1, 1);
|
||||||
|
std::cout << "Seed: " << SEED << std::endl;
|
||||||
|
balls = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
balls = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
43
gloom/src/Game.h
Normal file
43
gloom/src/Game.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_GAME_H
|
||||||
|
#define GLOOM_GAME_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
#include "gloom/Shader.h"
|
||||||
|
#include "Cube.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
static void glfwErrorCallback(int error, const char *description);
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
public:
|
||||||
|
Game();
|
||||||
|
~Game();
|
||||||
|
|
||||||
|
void run();
|
||||||
|
void handleKeyboard();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLFWwindow* m_window;
|
||||||
|
|
||||||
|
bool m_isMouseLocked{ false };
|
||||||
|
|
||||||
|
double m_lastFrameTime{ 0.0 };
|
||||||
|
double m_deltaTime{ 0.0 };
|
||||||
|
|
||||||
|
Shader m_shader;
|
||||||
|
|
||||||
|
// Mesh* m_mesh;
|
||||||
|
// std::vector<Chunk*> m_chunks;
|
||||||
|
// std::vector<Cube> m_cubes;
|
||||||
|
|
||||||
|
World* m_world;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_GAME_H
|
||||||
104
gloom/src/World.cpp
Normal file
104
gloom/src/World.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 26/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "World.h"
|
||||||
|
#include <iostream>
|
||||||
|
Chunk * World::getChunk(int x, int z) {
|
||||||
|
return chunks[x][z];
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::generateChunk(int x, int z) {
|
||||||
|
//Calc offset so there is a 1 block space between each chunk
|
||||||
|
// glm::vec2 offset = glm::vec2(x * 2, z * 2);
|
||||||
|
if(chunks[x][z] != nullptr){
|
||||||
|
delete chunks[x][z];
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks[x][z] = new Chunk(glm::vec2(x, z));
|
||||||
|
chunkGenerated[x][z] = ChunkLoadStatus::GENERATING;
|
||||||
|
chunks[x][z]->loadBlocks();
|
||||||
|
chunks[x][z]->loadMesh();
|
||||||
|
chunkGenerated[x][z] = ChunkLoadStatus::GENERATED;
|
||||||
|
|
||||||
|
//Call the sourounding chunks to update their mesh
|
||||||
|
if (x > 0) {
|
||||||
|
if(chunkGenerated[x - 1][z] == ChunkLoadStatus::GENERATED)
|
||||||
|
chunks[x - 1][z]->loadMesh();
|
||||||
|
}
|
||||||
|
if (x < WORLD_WIDTH - 1) {
|
||||||
|
if(chunkGenerated[x + 1][z] == ChunkLoadStatus::GENERATED)
|
||||||
|
chunks[x + 1][z]->loadMesh();
|
||||||
|
}
|
||||||
|
if (z > 0) {
|
||||||
|
if(chunkGenerated[x][z - 1] == ChunkLoadStatus::GENERATED)
|
||||||
|
chunks[x][z - 1]->loadMesh();
|
||||||
|
}
|
||||||
|
if (z < WORLD_HEIGHT - 1) {
|
||||||
|
if(chunkGenerated[x][z + 1] == ChunkLoadStatus::GENERATED)
|
||||||
|
chunks[x][z + 1]->loadMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Block* World::getBlock(int x, int y, int z) {
|
||||||
|
int chunkX = x / CHUNK_SIZE;
|
||||||
|
int chunkZ = z / CHUNK_SIZE;
|
||||||
|
|
||||||
|
int blockX = x % CHUNK_SIZE;
|
||||||
|
int blockZ = z % CHUNK_SIZE;
|
||||||
|
|
||||||
|
Chunk* chunk = chunks[chunkX][chunkZ];
|
||||||
|
ChunkLoadStatus status = isChunkGenerated(chunkX, chunkZ);
|
||||||
|
|
||||||
|
// check if the chunk is generated
|
||||||
|
switch(isChunkGenerated(chunkX, chunkZ)) {
|
||||||
|
case ChunkLoadStatus::NOT_GENERATED:
|
||||||
|
// generateChunk(chunkX, chunkZ);
|
||||||
|
return new Block(BlockType::DIRT);
|
||||||
|
break;
|
||||||
|
case ChunkLoadStatus::NOT_AVAILABLE:
|
||||||
|
return new Block(BlockType::AIR);
|
||||||
|
break;
|
||||||
|
case ChunkLoadStatus::GENERATING:
|
||||||
|
//Prob current chunk is generating
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks[chunkX][chunkZ]->getBlock(blockX, y, blockZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::setBlock(int x, int y, int z, const Block &block) {
|
||||||
|
int chunkX = x / CHUNK_SIZE;
|
||||||
|
int chunkZ = z / CHUNK_SIZE;
|
||||||
|
|
||||||
|
int blockX = x % CHUNK_SIZE;
|
||||||
|
int blockZ = z % CHUNK_SIZE;
|
||||||
|
|
||||||
|
chunks[chunkX][chunkZ]->setBlock(blockX, y, blockZ, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::Draw(GLuint shaderProgram, glm::vec3 playerPos) {
|
||||||
|
for (int x = 0; x < WORLD_WIDTH; x++) {
|
||||||
|
for (int z = 0; z < WORLD_HEIGHT; z++) {
|
||||||
|
//Check if the player is RENDERDISTANCE chunks away from the chunk
|
||||||
|
if (glm::distance(playerPos, glm::vec3(x * CHUNK_SIZE, 0, z * CHUNK_SIZE)) > RENDER_DISTANCE * CHUNK_SIZE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (chunkGenerated[x][z] == ChunkLoadStatus::GENERATED) {
|
||||||
|
chunks[x][z]->Draw(shaderProgram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
World::World() {
|
||||||
|
for (int x = 0; x < WORLD_WIDTH; x++) {
|
||||||
|
for (int z = 0; z < WORLD_HEIGHT; z++) {
|
||||||
|
chunks[x][z] = nullptr;
|
||||||
|
chunkGenerated[x][z] = ChunkLoadStatus::NOT_GENERATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
gloom/src/World.h
Normal file
42
gloom/src/World.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 26/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_WORLD_H
|
||||||
|
#define GLOOM_WORLD_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Chunk.h"
|
||||||
|
#include "gloom/Singleton.h"
|
||||||
|
|
||||||
|
|
||||||
|
class World: public Singleton<World> {
|
||||||
|
public:
|
||||||
|
World();
|
||||||
|
Chunk * getChunk(int x, int z);
|
||||||
|
void generateChunk(int x, int z);
|
||||||
|
|
||||||
|
//Optional ig
|
||||||
|
Block* getBlock(int x, int y, int z);
|
||||||
|
void setBlock(int x, int y, int z, const Block& block);
|
||||||
|
|
||||||
|
void Draw(GLuint shaderProgram, glm::vec3 playerPos);
|
||||||
|
|
||||||
|
ChunkLoadStatus isChunkGenerated(int x, int z) {
|
||||||
|
//if out of bounds, return true
|
||||||
|
if (x < 0 || x >= WORLD_WIDTH || z < 0 || z >= WORLD_HEIGHT) {
|
||||||
|
return ChunkLoadStatus::NOT_AVAILABLE;
|
||||||
|
} else {
|
||||||
|
return chunkGenerated[x][z];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//2D array
|
||||||
|
Chunk* chunks[WORLD_HEIGHT][WORLD_WIDTH]{ nullptr };
|
||||||
|
ChunkLoadStatus chunkGenerated[WORLD_HEIGHT][WORLD_WIDTH]{ ChunkLoadStatus::NOT_GENERATED };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_WORLD_H
|
||||||
64
gloom/src/gloom/Camera.cpp
Normal file
64
gloom/src/gloom/Camera.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Camera.h"
|
||||||
|
|
||||||
|
const float CAM_SENSITIVITY = .002f;
|
||||||
|
const float CAM_SPEED = 20;
|
||||||
|
|
||||||
|
//projection params
|
||||||
|
|
||||||
|
Camera::Camera() {
|
||||||
|
projectionMatrix = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / SCR_HEIGHT, NEAR_PLANE, FAR_PLANE);
|
||||||
|
camPos = glm::vec3(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 Camera::getFrontVector() {
|
||||||
|
glm::vec3 front;
|
||||||
|
front.x = cos(cameraAngle.x) * cos(cameraAngle.y);
|
||||||
|
front.y = sin(cameraAngle.y);
|
||||||
|
front.z = sin(cameraAngle.x) * cos(cameraAngle.y);
|
||||||
|
|
||||||
|
return front;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::updateMouse(glm::vec2 mousePos) {
|
||||||
|
glm::vec2 offset = mousePos - lastMousePos;
|
||||||
|
lastMousePos = mousePos;
|
||||||
|
cameraAngle += offset * CAM_SENSITIVITY;
|
||||||
|
cameraAngle.y = glm::clamp(cameraAngle.y, glm::radians(-89.0f), glm::radians(89.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Camera::updatePos(glm::vec3 moveDirection, double dt) {
|
||||||
|
glm::vec3 up(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
glm::vec3 front = glm::normalize(getFrontVector());
|
||||||
|
glm::vec3 right = glm::normalize(glm::cross(front, up));
|
||||||
|
up = glm::normalize(glm::cross(right, front));
|
||||||
|
|
||||||
|
camPos += up * moveDirection.y * CAM_SPEED * (float)dt;
|
||||||
|
camPos += front * moveDirection.z * -CAM_SPEED * (float)dt;
|
||||||
|
camPos += right * moveDirection.x * CAM_SPEED * (float)dt;
|
||||||
|
|
||||||
|
// Camera::print();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Camera::getViewMatrix() {
|
||||||
|
glm::vec3 front = getFrontVector();
|
||||||
|
|
||||||
|
glm::vec3 cameraTarget = camPos + front;
|
||||||
|
|
||||||
|
|
||||||
|
return glm::lookAt(camPos, cameraTarget, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::print() {
|
||||||
|
std::cout << "Camera Position: " << camPos.x << ", " << camPos.y << ", " <<camPos.z << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera& Camera::getInstance() {
|
||||||
|
static Camera instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
44
gloom/src/gloom/Camera.h
Normal file
44
gloom/src/gloom/Camera.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_CAMERA_H
|
||||||
|
#define GLOOM_CAMERA_H
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
glm::vec2 cameraAngle; //pitch and yaw
|
||||||
|
glm::vec3 getFrontVector();
|
||||||
|
glm::vec2 lastMousePos = glm::vec2(400.0f, 300.0f);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Camera();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//constants
|
||||||
|
static constexpr int SCR_WIDTH = 1200;
|
||||||
|
static constexpr int SCR_HEIGHT = 900;
|
||||||
|
static constexpr float FOV = 90;
|
||||||
|
static constexpr float NEAR_PLANE = 0.1f;
|
||||||
|
static constexpr float FAR_PLANE = 200.0f;
|
||||||
|
|
||||||
|
static Camera& getInstance();
|
||||||
|
|
||||||
|
glm::vec3 camPos = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
void updateMouse(glm::vec2 mousePos);
|
||||||
|
void updatePos(glm::vec3 moveDirection, double dt);
|
||||||
|
void print();
|
||||||
|
glm::mat4 getViewMatrix();
|
||||||
|
glm::mat4 projectionMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_CAMERA_H
|
||||||
89
gloom/src/gloom/Mesh.cpp
Normal file
89
gloom/src/gloom/Mesh.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Mesh.h"
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "config.hpp"
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include "TextureManager.h"
|
||||||
|
|
||||||
|
Mesh::Mesh() {
|
||||||
|
VAO = 0;
|
||||||
|
VBO = 0;
|
||||||
|
EBO = 0;
|
||||||
|
VAOSIZE = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::~Mesh() {
|
||||||
|
glDeleteVertexArrays(1, &VAO);
|
||||||
|
glDeleteBuffers(1, &VBO);
|
||||||
|
glDeleteBuffers(1, &EBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::Mesh(const std::vector<Vertex> &vertices, const std::vector<unsigned int> &indices) {
|
||||||
|
this->vertices = vertices;
|
||||||
|
this->indices = indices;
|
||||||
|
m_texture = TextureManager::GetInstance().getTexture("assets/dirt.png");
|
||||||
|
setupMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::draw(GLuint shaderID) {
|
||||||
|
|
||||||
|
glUseProgram(shaderID);
|
||||||
|
|
||||||
|
GLuint modelLoc = glGetUniformLocation(shaderID, "model");
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
model = glm::translate(model, m_position);
|
||||||
|
model = glm::rotate(model, glm::radians(m_rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, glm::radians(m_rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, glm::radians(m_rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
model = glm::scale(model, m_scale);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
|
||||||
|
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
|
||||||
|
if(renderWireframe) {
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
} else {
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_texture->bind(0);
|
||||||
|
|
||||||
|
//Get error
|
||||||
|
glDrawElements(GL_TRIANGLES, VAOSIZE, GL_UNSIGNED_INT, nullptr);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::setupMesh() {
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &VAO);
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
glGenBuffers(1, &EBO);
|
||||||
|
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// vertex positions
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, position));
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// vertex texture coords
|
||||||
|
glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, texCoords));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
VAOSIZE = indices.size(); // Now using the size of the indices
|
||||||
|
}
|
||||||
46
gloom/src/gloom/Mesh.h
Normal file
46
gloom/src/gloom/Mesh.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_MESH_H
|
||||||
|
#define GLOOM_MESH_H
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
struct Vertex{
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::dvec2 texCoords;
|
||||||
|
};
|
||||||
|
|
||||||
|
Mesh();
|
||||||
|
~Mesh();
|
||||||
|
Mesh(const std::vector<Mesh::Vertex>& vertices, const std::vector<unsigned int>& indices);
|
||||||
|
|
||||||
|
|
||||||
|
void draw(GLuint shaderID);
|
||||||
|
void setupMesh();
|
||||||
|
|
||||||
|
void setPosition(glm::vec3 position) { m_position = position; }
|
||||||
|
void setRotation(glm::vec3 rotation) { m_rotation = rotation; }
|
||||||
|
void setScale(glm::vec3 scale) { m_scale = scale; }
|
||||||
|
private:
|
||||||
|
unsigned int VAO, VBO, EBO, VAOSIZE;
|
||||||
|
|
||||||
|
glm::vec3 m_position{ 0.0f, -5.0f, 0.0f };
|
||||||
|
glm::vec3 m_rotation{ 0.0f, 0.0f, 0.0f };
|
||||||
|
glm::vec3 m_scale{ 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
std::vector<unsigned int> indices;
|
||||||
|
|
||||||
|
Texture* m_texture{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_MESH_H
|
||||||
659
gloom/src/gloom/PerlinNoise.hpp
Normal file
659
gloom/src/gloom/PerlinNoise.hpp
Normal file
@@ -0,0 +1,659 @@
|
|||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// siv::PerlinNoise
|
||||||
|
// Perlin noise library for modern C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2013-2021 Ryo Suzuki <reputeless@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files(the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions :
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# pragma once
|
||||||
|
# include <cstdint>
|
||||||
|
# include <algorithm>
|
||||||
|
# include <array>
|
||||||
|
# include <iterator>
|
||||||
|
# include <numeric>
|
||||||
|
# include <random>
|
||||||
|
# include <type_traits>
|
||||||
|
|
||||||
|
# if __has_include(<concepts>) && defined(__cpp_concepts)
|
||||||
|
# include <concepts>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
// Library major version
|
||||||
|
# define SIVPERLIN_VERSION_MAJOR 3
|
||||||
|
|
||||||
|
// Library minor version
|
||||||
|
# define SIVPERLIN_VERSION_MINOR 0
|
||||||
|
|
||||||
|
// Library revision version
|
||||||
|
# define SIVPERLIN_VERSION_REVISION 0
|
||||||
|
|
||||||
|
// Library version
|
||||||
|
# define SIVPERLIN_VERSION ((SIVPERLIN_VERSION_MAJOR * 100 * 100) + (SIVPERLIN_VERSION_MINOR * 100) + (SIVPERLIN_VERSION_REVISION))
|
||||||
|
|
||||||
|
|
||||||
|
// [[nodiscard]] for constructors
|
||||||
|
# if (201907L <= __has_cpp_attribute(nodiscard))
|
||||||
|
# define SIVPERLIN_NODISCARD_CXX20 [[nodiscard]]
|
||||||
|
# else
|
||||||
|
# define SIVPERLIN_NODISCARD_CXX20
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
// std::uniform_random_bit_generator concept
|
||||||
|
# if __cpp_lib_concepts
|
||||||
|
# define SIVPERLIN_CONCEPT_URBG template <std::uniform_random_bit_generator URBG>
|
||||||
|
# define SIVPERLIN_CONCEPT_URBG_ template <std::uniform_random_bit_generator URBG>
|
||||||
|
# else
|
||||||
|
# define SIVPERLIN_CONCEPT_URBG template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>* = nullptr>
|
||||||
|
# define SIVPERLIN_CONCEPT_URBG_ template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>*>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
// arbitrary value for increasing entropy
|
||||||
|
# ifndef SIVPERLIN_DEFAULT_Y
|
||||||
|
# define SIVPERLIN_DEFAULT_Y (0.12345)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// arbitrary value for increasing entropy
|
||||||
|
# ifndef SIVPERLIN_DEFAULT_Z
|
||||||
|
# define SIVPERLIN_DEFAULT_Z (0.34567)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace siv
|
||||||
|
{
|
||||||
|
template <class Float>
|
||||||
|
class BasicPerlinNoise
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static_assert(std::is_floating_point_v<Float>);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Typedefs
|
||||||
|
//
|
||||||
|
|
||||||
|
using state_type = std::array<std::uint8_t, 256>;
|
||||||
|
|
||||||
|
using value_type = Float;
|
||||||
|
|
||||||
|
using default_random_engine = std::mt19937;
|
||||||
|
|
||||||
|
using seed_type = typename default_random_engine::result_type;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Constructors
|
||||||
|
//
|
||||||
|
|
||||||
|
SIVPERLIN_NODISCARD_CXX20
|
||||||
|
constexpr BasicPerlinNoise() noexcept;
|
||||||
|
|
||||||
|
SIVPERLIN_NODISCARD_CXX20
|
||||||
|
explicit BasicPerlinNoise(seed_type seed);
|
||||||
|
|
||||||
|
SIVPERLIN_CONCEPT_URBG
|
||||||
|
SIVPERLIN_NODISCARD_CXX20
|
||||||
|
explicit BasicPerlinNoise(URBG&& urbg);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Reseed
|
||||||
|
//
|
||||||
|
|
||||||
|
void reseed(seed_type seed);
|
||||||
|
|
||||||
|
SIVPERLIN_CONCEPT_URBG
|
||||||
|
void reseed(URBG&& urbg);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Serialization
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr const state_type& serialize() const noexcept;
|
||||||
|
|
||||||
|
constexpr void deserialize(const state_type& state) noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Noise (The result is in the range [-1, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise1D(value_type x) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise2D(value_type x, value_type y) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise3D(value_type x, value_type y, value_type z) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Noise (The result is remapped to the range [0, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise1D_01(value_type x) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise2D_01(value_type x, value_type y) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise3D_01(value_type x, value_type y, value_type z) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Octave noise (The result can be out of the range [-1, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Octave noise (The result is clamped to the range [-1, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave1D_11(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave2D_11(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave3D_11(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Octave noise (The result is clamped and remapped to the range [0, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type octave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Octave noise (The result is normalized to the range [-1, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Octave noise (The result is normalized and remapped to the range [0, 1])
|
||||||
|
//
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
state_type m_permutation;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PerlinNoise = BasicPerlinNoise<double>;
|
||||||
|
|
||||||
|
namespace perlin_detail
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// These functions are provided for consistency.
|
||||||
|
// You may get different results from std::shuffle() with different standard library implementations.
|
||||||
|
//
|
||||||
|
SIVPERLIN_CONCEPT_URBG
|
||||||
|
[[nodiscard]]
|
||||||
|
inline std::uint64_t Random(const std::uint64_t max, URBG&& urbg)
|
||||||
|
{
|
||||||
|
return (urbg() % (max + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class RandomIt, class URBG>
|
||||||
|
inline void Shuffle(RandomIt first, RandomIt last, URBG&& urbg)
|
||||||
|
{
|
||||||
|
if (first == last)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using difference_type = typename std::iterator_traits<RandomIt>::difference_type;
|
||||||
|
|
||||||
|
for (RandomIt it = first + 1; it < last; ++it)
|
||||||
|
{
|
||||||
|
const std::uint64_t n = static_cast<std::uint64_t>(it - first);
|
||||||
|
std::iter_swap(it, first + static_cast<difference_type>(Random(n, std::forward<URBG>(urbg))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float Fade(const Float t) noexcept
|
||||||
|
{
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float Lerp(const Float a, const Float b, const Float t) noexcept
|
||||||
|
{
|
||||||
|
return (a + (b - a) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float Grad(const std::uint8_t hash, const Float x, const Float y, const Float z) noexcept
|
||||||
|
{
|
||||||
|
const std::uint8_t h = hash & 15;
|
||||||
|
const Float u = h < 8 ? x : y;
|
||||||
|
const Float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||||
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float Remap_01(const Float x) noexcept
|
||||||
|
{
|
||||||
|
return (x * Float(0.5) + Float(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float Clamp_11(const Float x) noexcept
|
||||||
|
{
|
||||||
|
return std::clamp(x, Float(-1.0), Float(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float RemapClamp_01(const Float x) noexcept
|
||||||
|
{
|
||||||
|
if (x <= Float(-1.0))
|
||||||
|
{
|
||||||
|
return Float(0.0);
|
||||||
|
}
|
||||||
|
else if (Float(1.0) <= x)
|
||||||
|
{
|
||||||
|
return Float(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (x * Float(0.5) + Float(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Noise, class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline auto Octave1D(const Noise& noise, Float x, const std::int32_t octaves, const Float persistence) noexcept
|
||||||
|
{
|
||||||
|
using value_type = Float;
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amplitude = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += (noise.noise1D(x) * amplitude);
|
||||||
|
x *= 2;
|
||||||
|
amplitude *= persistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Noise, class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline auto Octave2D(const Noise& noise, Float x, Float y, const std::int32_t octaves, const Float persistence) noexcept
|
||||||
|
{
|
||||||
|
using value_type = Float;
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amplitude = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += (noise.noise2D(x, y) * amplitude);
|
||||||
|
x *= 2;
|
||||||
|
y *= 2;
|
||||||
|
amplitude *= persistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Noise, class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline auto Octave3D(const Noise& noise, Float x, Float y, Float z, const std::int32_t octaves, const Float persistence) noexcept
|
||||||
|
{
|
||||||
|
using value_type = Float;
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amplitude = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += (noise.noise3D(x, y, z) * amplitude);
|
||||||
|
x *= 2;
|
||||||
|
y *= 2;
|
||||||
|
z *= 2;
|
||||||
|
amplitude *= persistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
[[nodiscard]]
|
||||||
|
inline constexpr Float MaxAmplitude(const std::int32_t octaves, const Float persistence) noexcept
|
||||||
|
{
|
||||||
|
using value_type = Float;
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amplitude = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += amplitude;
|
||||||
|
amplitude *= persistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline constexpr BasicPerlinNoise<Float>::BasicPerlinNoise() noexcept
|
||||||
|
: m_permutation{ 151,160,137,91,90,15,
|
||||||
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 } {}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline BasicPerlinNoise<Float>::BasicPerlinNoise(const seed_type seed)
|
||||||
|
{
|
||||||
|
reseed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
SIVPERLIN_CONCEPT_URBG_
|
||||||
|
inline BasicPerlinNoise<Float>::BasicPerlinNoise(URBG&& urbg)
|
||||||
|
{
|
||||||
|
reseed(std::forward<URBG>(urbg));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline void BasicPerlinNoise<Float>::reseed(const seed_type seed)
|
||||||
|
{
|
||||||
|
reseed(default_random_engine{ seed });
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
SIVPERLIN_CONCEPT_URBG_
|
||||||
|
inline void BasicPerlinNoise<Float>::reseed(URBG&& urbg)
|
||||||
|
{
|
||||||
|
std::iota(m_permutation.begin(), m_permutation.end(), uint8_t{ 0 });
|
||||||
|
|
||||||
|
perlin_detail::Shuffle(m_permutation.begin(), m_permutation.end(), std::forward<URBG>(urbg));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline constexpr const typename BasicPerlinNoise<Float>::state_type& BasicPerlinNoise<Float>::serialize() const noexcept
|
||||||
|
{
|
||||||
|
return m_permutation;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline constexpr void BasicPerlinNoise<Float>::deserialize(const state_type& state) noexcept
|
||||||
|
{
|
||||||
|
m_permutation = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D(const value_type x) const noexcept
|
||||||
|
{
|
||||||
|
return noise3D(x,
|
||||||
|
static_cast<value_type>(SIVPERLIN_DEFAULT_Y),
|
||||||
|
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D(const value_type x, const value_type y) const noexcept
|
||||||
|
{
|
||||||
|
return noise3D(x,
|
||||||
|
y,
|
||||||
|
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D(const value_type x, const value_type y, const value_type z) const noexcept
|
||||||
|
{
|
||||||
|
const value_type _x = std::floor(x);
|
||||||
|
const value_type _y = std::floor(y);
|
||||||
|
const value_type _z = std::floor(z);
|
||||||
|
|
||||||
|
const std::int32_t ix = static_cast<std::int32_t>(_x) & 255;
|
||||||
|
const std::int32_t iy = static_cast<std::int32_t>(_y) & 255;
|
||||||
|
const std::int32_t iz = static_cast<std::int32_t>(_z) & 255;
|
||||||
|
|
||||||
|
const value_type fx = (x - _x);
|
||||||
|
const value_type fy = (y - _y);
|
||||||
|
const value_type fz = (z - _z);
|
||||||
|
|
||||||
|
const value_type u = perlin_detail::Fade(fx);
|
||||||
|
const value_type v = perlin_detail::Fade(fy);
|
||||||
|
const value_type w = perlin_detail::Fade(fz);
|
||||||
|
|
||||||
|
const std::uint8_t A = (m_permutation[ix & 255] + iy) & 255;
|
||||||
|
const std::uint8_t B = (m_permutation[(ix + 1) & 255] + iy) & 255;
|
||||||
|
|
||||||
|
const std::uint8_t AA = (m_permutation[A] + iz) & 255;
|
||||||
|
const std::uint8_t AB = (m_permutation[(A + 1) & 255] + iz) & 255;
|
||||||
|
|
||||||
|
const std::uint8_t BA = (m_permutation[B] + iz) & 255;
|
||||||
|
const std::uint8_t BB = (m_permutation[(B + 1) & 255] + iz) & 255;
|
||||||
|
|
||||||
|
const value_type p0 = perlin_detail::Grad(m_permutation[AA], fx, fy, fz);
|
||||||
|
const value_type p1 = perlin_detail::Grad(m_permutation[BA], fx - 1, fy, fz);
|
||||||
|
const value_type p2 = perlin_detail::Grad(m_permutation[AB], fx, fy - 1, fz);
|
||||||
|
const value_type p3 = perlin_detail::Grad(m_permutation[BB], fx - 1, fy - 1, fz);
|
||||||
|
const value_type p4 = perlin_detail::Grad(m_permutation[(AA + 1) & 255], fx, fy, fz - 1);
|
||||||
|
const value_type p5 = perlin_detail::Grad(m_permutation[(BA + 1) & 255], fx - 1, fy, fz - 1);
|
||||||
|
const value_type p6 = perlin_detail::Grad(m_permutation[(AB + 1) & 255], fx, fy - 1, fz - 1);
|
||||||
|
const value_type p7 = perlin_detail::Grad(m_permutation[(BB + 1) & 255], fx - 1, fy - 1, fz - 1);
|
||||||
|
|
||||||
|
const value_type q0 = perlin_detail::Lerp(p0, p1, u);
|
||||||
|
const value_type q1 = perlin_detail::Lerp(p2, p3, u);
|
||||||
|
const value_type q2 = perlin_detail::Lerp(p4, p5, u);
|
||||||
|
const value_type q3 = perlin_detail::Lerp(p6, p7, u);
|
||||||
|
|
||||||
|
const value_type r0 = perlin_detail::Lerp(q0, q1, v);
|
||||||
|
const value_type r1 = perlin_detail::Lerp(q2, q3, v);
|
||||||
|
|
||||||
|
return perlin_detail::Lerp(r0, r1, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D_01(const value_type x) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(noise1D(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D_01(const value_type x, const value_type y) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(noise2D(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D_01(const value_type x, const value_type y, const value_type z) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(noise3D(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Octave1D(*this, x, octaves, persistence);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Octave2D(*this, x, y, octaves, persistence);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Octave3D(*this, x, y, z, octaves, persistence);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_11(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Clamp_11(octave1D(x, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_11(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Clamp_11(octave2D(x, y, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_11(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Clamp_11(octave3D(x, y, z, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::RemapClamp_01(octave1D(x, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::RemapClamp_01(octave2D(x, y, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::RemapClamp_01(octave3D(x, y, z, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return (octave1D(x, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return (octave2D(x, y, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return (octave3D(x, y, z, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(normalizedOctave1D(x, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(normalizedOctave2D(x, y, octaves, persistence));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Float>
|
||||||
|
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
||||||
|
{
|
||||||
|
return perlin_detail::Remap_01(normalizedOctave3D(x, y, z, octaves, persistence));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# undef SIVPERLIN_NODISCARD_CXX20
|
||||||
|
# undef SIVPERLIN_CONCEPT_URBG
|
||||||
|
# undef SIVPERLIN_CONCEPT_URBG_
|
||||||
157
gloom/src/gloom/Shader.cpp
Normal file
157
gloom/src/gloom/Shader.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Shader::Shader() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::setShader(const char* vertexPath, const char* fragmentPath) {
|
||||||
|
std::string vertexCode, fragmentCode;
|
||||||
|
std::ifstream vShaderFile, fShaderFile;
|
||||||
|
|
||||||
|
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
try {
|
||||||
|
//open files
|
||||||
|
vShaderFile.open(vertexPath);
|
||||||
|
fShaderFile.open(fragmentPath);
|
||||||
|
std::stringstream vShaderStream, fShaderStream;
|
||||||
|
|
||||||
|
vShaderStream << vShaderFile.rdbuf();
|
||||||
|
fShaderStream << fShaderFile.rdbuf();
|
||||||
|
|
||||||
|
vShaderFile.close();
|
||||||
|
fShaderFile.close();
|
||||||
|
|
||||||
|
vertexCode = vShaderStream.str();
|
||||||
|
fragmentCode = fShaderStream.str();
|
||||||
|
}
|
||||||
|
catch (std::ifstream::failure e) {
|
||||||
|
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* vShaderCode = vertexCode.c_str();
|
||||||
|
const char* fShaderCode = fragmentCode.c_str();
|
||||||
|
|
||||||
|
|
||||||
|
//next, compile shaders
|
||||||
|
unsigned int vertex, fragment;
|
||||||
|
int success;
|
||||||
|
char infoLog[512];
|
||||||
|
//vertex
|
||||||
|
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(vertex, 1, &vShaderCode, NULL);
|
||||||
|
glCompileShader(vertex);
|
||||||
|
//vertex errors
|
||||||
|
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
|
||||||
|
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fragment
|
||||||
|
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fragment, 1, &fShaderCode, NULL);
|
||||||
|
glCompileShader(fragment);
|
||||||
|
//fragment compile errors
|
||||||
|
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
|
||||||
|
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup shader program
|
||||||
|
ID = glCreateProgram();
|
||||||
|
glAttachShader(ID, vertex);
|
||||||
|
glAttachShader(ID, fragment);
|
||||||
|
glLinkProgram(ID);
|
||||||
|
//shader program linking errors
|
||||||
|
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
glGetProgramInfoLog(ID, 512, NULL, infoLog);
|
||||||
|
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
glDeleteShader(vertex);
|
||||||
|
glDeleteShader(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//shadow mapping
|
||||||
|
void Shader::setupShadowMap() {
|
||||||
|
// Create framebuffer to attach depth texture
|
||||||
|
glGenFramebuffers(1, &depthMapFBO);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
|
||||||
|
// Create depth texture
|
||||||
|
glGenTextures(1, &depthMap);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, depthMap);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
glReadBuffer(GL_NONE);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowWidth, shadowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthMap, 0);
|
||||||
|
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
std::cout << "Error getting framebuffer" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
void Shader::renderShadowMap(glm::mat4 lightSpaceMatrix) {
|
||||||
|
glViewport(0, 0, shadowWidth, shadowHeight);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Render the scene
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//enable this shader
|
||||||
|
void Shader::use() {
|
||||||
|
glUseProgram(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//uniform set functions
|
||||||
|
void Shader::setBool(const std::string& name, bool value) const
|
||||||
|
{
|
||||||
|
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
|
||||||
|
}
|
||||||
|
void Shader::setInt(const std::string& name, int value) const
|
||||||
|
{
|
||||||
|
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
|
||||||
|
}
|
||||||
|
void Shader::setFloat(const std::string& name, float value) const
|
||||||
|
{
|
||||||
|
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
|
||||||
|
}
|
||||||
|
void Shader::setMat4(const std::string& name, glm::mat4 value) const
|
||||||
|
{
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value));
|
||||||
|
|
||||||
|
}
|
||||||
|
void Shader::setVec3(const std::string& name, glm::vec3 value) const {
|
||||||
|
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, glm::value_ptr(value));
|
||||||
|
}
|
||||||
41
gloom/src/gloom/Shader.h
Normal file
41
gloom/src/gloom/Shader.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_SHADER_H
|
||||||
|
#define GLOOM_SHADER_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unsigned int ID;
|
||||||
|
Shader();
|
||||||
|
|
||||||
|
void use();
|
||||||
|
void setShader(const char* vertexPath, const char* fragmentPath);
|
||||||
|
|
||||||
|
void setBool(const std::string& name, bool value) const;
|
||||||
|
void setInt(const std::string& name, int value) const;
|
||||||
|
void setFloat(const std::string& name, float value) const;
|
||||||
|
void setMat4(const std::string& name, glm::mat4 value) const;
|
||||||
|
void setVec3(const std::string& name, glm::vec3 value) const;
|
||||||
|
|
||||||
|
|
||||||
|
//shadow map
|
||||||
|
unsigned int depthMapFBO, depthMap;
|
||||||
|
int shadowWidth = 4096, shadowHeight = 4096; // Adjust the size as needed
|
||||||
|
void setupShadowMap();
|
||||||
|
void renderShadowMap(glm::mat4 lightSpaceMatrix);
|
||||||
|
};
|
||||||
|
#endif //GLOOM_SHADER_H
|
||||||
35
gloom/src/gloom/Singleton.h
Normal file
35
gloom/src/gloom/Singleton.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 25/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_SINGLETON_H
|
||||||
|
#define GLOOM_SINGLETON_H
|
||||||
|
|
||||||
|
#ifndef SINGLETON_H
|
||||||
|
#define SINGLETON_H
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Singleton {
|
||||||
|
public:
|
||||||
|
static T &GetInstance() {
|
||||||
|
static T instance{};
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Singleton() = default;
|
||||||
|
|
||||||
|
Singleton(Singleton &&other) = delete;
|
||||||
|
|
||||||
|
Singleton(const Singleton &other) = delete;
|
||||||
|
|
||||||
|
Singleton &operator=(Singleton &&other) = delete;
|
||||||
|
|
||||||
|
Singleton &operator=(const Singleton &other) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Singleton() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SINGLETON_H
|
||||||
|
|
||||||
|
#endif //GLOOM_SINGLETON_H
|
||||||
52
gloom/src/gloom/Texture.cpp
Normal file
52
gloom/src/gloom/Texture.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Texture.h"
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
|
||||||
|
Texture::Texture(const std::string &filename) {
|
||||||
|
// Load the image
|
||||||
|
int width, height, channels;
|
||||||
|
unsigned char* image = stbi_load(filename.c_str(), &width, &height, &channels, 0);
|
||||||
|
|
||||||
|
// Generate a texture
|
||||||
|
glGenTextures(1, &m_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||||
|
|
||||||
|
// Set the texture wrapping/filtering options
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
//mipmap resizing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Load and generate the texture
|
||||||
|
if (image) {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to load texture" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the image
|
||||||
|
stbi_image_free(image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::bind(unsigned int slot) const {
|
||||||
|
glActiveTexture(GL_TEXTURE0 + slot);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::unbind() const {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
24
gloom/src/gloom/Texture.h
Normal file
24
gloom/src/gloom/Texture.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 23/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_TEXTURE_H
|
||||||
|
#define GLOOM_TEXTURE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
public:
|
||||||
|
Texture(const std::string& filename);
|
||||||
|
|
||||||
|
void bind(unsigned int slot = 0) const;
|
||||||
|
void unbind() const;
|
||||||
|
|
||||||
|
unsigned int getTexture() const { return m_texture; }
|
||||||
|
private:
|
||||||
|
unsigned int m_texture{ 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_TEXTURE_H
|
||||||
12
gloom/src/gloom/TextureManager.cpp
Normal file
12
gloom/src/gloom/TextureManager.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 25/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TextureManager.h"
|
||||||
|
|
||||||
|
Texture * TextureManager::getTexture(const std::string &path) {
|
||||||
|
if (m_textures.find(path) == m_textures.end()) {
|
||||||
|
m_textures[path] = new Texture(path);
|
||||||
|
}
|
||||||
|
return m_textures[path];
|
||||||
|
}
|
||||||
27
gloom/src/gloom/TextureManager.h
Normal file
27
gloom/src/gloom/TextureManager.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by Bram on 25/08/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GLOOM_TEXTUREMANAGER_H
|
||||||
|
#define GLOOM_TEXTUREMANAGER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Singleton.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TextureManager: public Singleton<TextureManager>{
|
||||||
|
public:
|
||||||
|
TextureManager() = default;
|
||||||
|
~TextureManager() override = default;
|
||||||
|
|
||||||
|
Texture * getTexture(const std::string& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, Texture*> m_textures;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GLOOM_TEXTUREMANAGER_H
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
#ifndef CAMERA_HPP
|
|
||||||
#define CAMERA_HPP
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// System headers
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Gloom
|
|
||||||
{
|
|
||||||
class Camera
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 2.0f),
|
|
||||||
GLfloat movementSpeed = 5.0f,
|
|
||||||
GLfloat mouseSensitivity = 0.005f)
|
|
||||||
{
|
|
||||||
cPosition = position;
|
|
||||||
cMovementSpeed = movementSpeed;
|
|
||||||
cMouseSensitivity = mouseSensitivity;
|
|
||||||
|
|
||||||
// Set up the initial view matrix
|
|
||||||
updateViewMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public member functions
|
|
||||||
|
|
||||||
/* Getter for the view matrix */
|
|
||||||
glm::mat4 getViewMatrix() { return matView; }
|
|
||||||
|
|
||||||
|
|
||||||
/* Handle keyboard inputs from a callback mechanism */
|
|
||||||
void handleKeyboardInputs(int key, int action)
|
|
||||||
{
|
|
||||||
// Keep track of pressed/released buttons
|
|
||||||
if (key >= 0 && key < 512)
|
|
||||||
{
|
|
||||||
if (action == GLFW_PRESS)
|
|
||||||
{
|
|
||||||
keysInUse[key] = true;
|
|
||||||
}
|
|
||||||
else if (action == GLFW_RELEASE)
|
|
||||||
{
|
|
||||||
keysInUse[key] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Handle mouse button inputs from a callback mechanism */
|
|
||||||
void handleMouseButtonInputs(int button, int action)
|
|
||||||
{
|
|
||||||
// Ensure that the camera only rotates when the left mouse button is
|
|
||||||
// pressed
|
|
||||||
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
|
|
||||||
{
|
|
||||||
isMousePressed = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isMousePressed = false;
|
|
||||||
resetMouse = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Handle cursor position from a callback mechanism */
|
|
||||||
void handleCursorPosInput(double xpos, double ypos)
|
|
||||||
{
|
|
||||||
// Do nothing if the left mouse button is not pressed
|
|
||||||
if (isMousePressed == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// There should be no movement when the mouse button is released
|
|
||||||
if (resetMouse)
|
|
||||||
{
|
|
||||||
lastXPos = xpos;
|
|
||||||
lastYPos = ypos;
|
|
||||||
resetMouse = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of pitch and yaw for the current frame
|
|
||||||
fYaw = xpos - lastXPos;
|
|
||||||
fPitch = ypos - lastYPos;
|
|
||||||
|
|
||||||
// Update last known cursor position
|
|
||||||
lastXPos = xpos;
|
|
||||||
lastYPos = ypos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Update the camera position and view matrix
|
|
||||||
`deltaTime` is the time between the current and last frame */
|
|
||||||
void updateCamera(GLfloat deltaTime)
|
|
||||||
{
|
|
||||||
// Extract movement information from the view matrix
|
|
||||||
glm::vec3 dirX(matView[0][0], matView[1][0], matView[2][0]);
|
|
||||||
glm::vec3 dirY(matView[0][1], matView[1][1], matView[2][1]);
|
|
||||||
glm::vec3 dirZ(matView[0][2], matView[1][2], matView[2][2]);
|
|
||||||
|
|
||||||
// Alter position in the appropriate direction
|
|
||||||
glm::vec3 fMovement(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_W]) // forward
|
|
||||||
fMovement -= dirZ;
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_S]) // backward
|
|
||||||
fMovement += dirZ;
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_A]) // left
|
|
||||||
fMovement -= dirX;
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_D]) // right
|
|
||||||
fMovement += dirX;
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_E]) // vertical up
|
|
||||||
fMovement += dirY;
|
|
||||||
|
|
||||||
if (keysInUse[GLFW_KEY_Q]) // vertical down
|
|
||||||
fMovement -= dirY;
|
|
||||||
|
|
||||||
// Trick to balance PC speed with movement
|
|
||||||
GLfloat velocity = cMovementSpeed * deltaTime;
|
|
||||||
|
|
||||||
// Update camera position using the appropriate velocity
|
|
||||||
cPosition += fMovement * velocity;
|
|
||||||
|
|
||||||
// Update the view matrix based on the new information
|
|
||||||
updateViewMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Disable copying and assignment
|
|
||||||
Camera(Camera const &) = delete;
|
|
||||||
Camera & operator =(Camera const &) = delete;
|
|
||||||
|
|
||||||
// Private member function
|
|
||||||
|
|
||||||
/* Update the view matrix based on the current information */
|
|
||||||
void updateViewMatrix()
|
|
||||||
{
|
|
||||||
// Adjust cursor movement using the specified sensitivity
|
|
||||||
fPitch *= cMouseSensitivity;
|
|
||||||
fYaw *= cMouseSensitivity;
|
|
||||||
|
|
||||||
// Create quaternions given the current pitch and yaw
|
|
||||||
glm::quat qPitch = glm::quat(glm::vec3(fPitch, 0.0f, 0.0f));
|
|
||||||
glm::quat qYaw = glm::quat(glm::vec3(0.0f, fYaw, 0.0f));
|
|
||||||
|
|
||||||
// Reset pitch and yaw values for the current rotation
|
|
||||||
fPitch = 0.0f;
|
|
||||||
fYaw = 0.0f;
|
|
||||||
|
|
||||||
// Update camera quaternion and normalise
|
|
||||||
cQuaternion = qYaw * qPitch * cQuaternion;
|
|
||||||
cQuaternion = glm::normalize(cQuaternion);
|
|
||||||
|
|
||||||
// Build rotation matrix using the camera quaternion
|
|
||||||
glm::mat4 matRotation = glm::mat4_cast(cQuaternion);
|
|
||||||
|
|
||||||
// Build translation matrix
|
|
||||||
glm::mat4 matTranslate = glm::translate(glm::mat4(1.0f), -cPosition);
|
|
||||||
|
|
||||||
// Update view matrix
|
|
||||||
matView = matRotation * matTranslate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private member variables
|
|
||||||
|
|
||||||
// Camera quaternion and frame pitch and yaw
|
|
||||||
glm::quat cQuaternion;
|
|
||||||
GLfloat fPitch = 0.0f;
|
|
||||||
GLfloat fYaw = 0.0f;
|
|
||||||
|
|
||||||
// Camera position
|
|
||||||
glm::vec3 cPosition;
|
|
||||||
|
|
||||||
// Variables used for bookkeeping
|
|
||||||
GLboolean resetMouse = true;
|
|
||||||
GLboolean isMousePressed = false;
|
|
||||||
GLboolean keysInUse[512];
|
|
||||||
|
|
||||||
// Last cursor position
|
|
||||||
GLfloat lastXPos = 0.0f;
|
|
||||||
GLfloat lastYPos = 0.0f;
|
|
||||||
|
|
||||||
// Camera settings
|
|
||||||
GLfloat cMovementSpeed;
|
|
||||||
GLfloat cMouseSensitivity;
|
|
||||||
|
|
||||||
// View matrix
|
|
||||||
glm::mat4 matView;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
45
gloom/src/gloom/config.hpp
Normal file
45
gloom/src/gloom/config.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Preprocessor directives
|
||||||
|
#ifndef GLOOM_HPP
|
||||||
|
#define GLOOM_HPP
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// System Headers
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
// Standard headers
|
||||||
|
#include <string>
|
||||||
|
#include "PerlinNoise.hpp"
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const int windowWidth = 1200;
|
||||||
|
const int windowHeight = 900;
|
||||||
|
const std::string windowTitle = "OpenGL";
|
||||||
|
const GLint windowResizable = GL_FALSE;
|
||||||
|
const int windowSamples = 4;
|
||||||
|
|
||||||
|
const int MAX_FPS = 60;
|
||||||
|
|
||||||
|
static bool renderWireframe = false;
|
||||||
|
|
||||||
|
static const int CHUNK_SIZE = 16;
|
||||||
|
static const int CHUNK_HEIGHT = 256;
|
||||||
|
|
||||||
|
static const int TEXTURE_WIDTH = 16;
|
||||||
|
static const int TEXTURE_HEIGHT = 16;
|
||||||
|
|
||||||
|
static const int ATLAS_WIDTH = 128;
|
||||||
|
static const int ATLAS_HEIGHT = 128;
|
||||||
|
|
||||||
|
static const double CELL_WIDTH = 1.0 / ATLAS_WIDTH * TEXTURE_WIDTH;
|
||||||
|
static const double CELL_HEIGHT = 1.0 / ATLAS_HEIGHT * TEXTURE_HEIGHT;
|
||||||
|
|
||||||
|
static const int RENDER_DISTANCE = 10;
|
||||||
|
|
||||||
|
static const int WORLD_WIDTH = 128;
|
||||||
|
static const int WORLD_HEIGHT = 128;
|
||||||
|
|
||||||
|
static int SEED = 1234u;
|
||||||
|
|
||||||
|
static siv::PerlinNoise perlin{ static_cast<unsigned int>(SEED) };
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Preprocessor directives
|
|
||||||
#ifndef GLOOM_HPP
|
|
||||||
#define GLOOM_HPP
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// System Headers
|
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
// Standard headers
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
const int windowWidth = 1024;
|
|
||||||
const int windowHeight = 768;
|
|
||||||
const std::string windowTitle = "OpenGL";
|
|
||||||
const GLint windowResizable = GL_FALSE;
|
|
||||||
const int windowSamples = 4;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
175
gloom/src/gloom/old/Cube.cpp
Normal file
175
gloom/src/gloom/old/Cube.cpp
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
////
|
||||||
|
//// Created by Bram on 23/08/2024.
|
||||||
|
////
|
||||||
|
//
|
||||||
|
//#include "Cube.h"
|
||||||
|
//
|
||||||
|
//glm::vec3 unitVertices[8] = {
|
||||||
|
// glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
// glm::vec3(1.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
// glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(1.0f, 0.0f, 1.0f),
|
||||||
|
// glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f)
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//unsigned int faceVertices[6][6] = {
|
||||||
|
// // TOP (3, 2, 6, 3, 6, 7)
|
||||||
|
// {3, 2, 6, 3, 6, 7},
|
||||||
|
// // BOTTOM (1, 0, 4, 1, 4, 5)
|
||||||
|
// {1, 0, 4, 1, 4, 5},
|
||||||
|
// // LEFT (0, 3, 7, 0, 7, 4)
|
||||||
|
// {0, 3, 7, 0, 7, 4},
|
||||||
|
// // RIGHT (2, 1, 5, 2, 5, 6)
|
||||||
|
// {2, 1, 5, 2, 5, 6},
|
||||||
|
// // FRONT (0, 1, 2, 0, 2, 3)
|
||||||
|
// {0, 1, 2, 0, 2, 3},
|
||||||
|
// // BACK (5, 4, 7, 5, 7, 6)
|
||||||
|
// {5, 4, 7, 5, 7, 6}
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//void Cube::Draw(GLuint shaderProgram) {
|
||||||
|
// // Use the shader program
|
||||||
|
// glUseProgram(shaderProgram);
|
||||||
|
//
|
||||||
|
// // Transform the cube
|
||||||
|
// glm::mat4 model = glm::translate(glm::mat4(1.0f), position);
|
||||||
|
// GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
|
||||||
|
// glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
//
|
||||||
|
// if(renderWireframe) {
|
||||||
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
// } else {
|
||||||
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Draw the cube
|
||||||
|
// texture.bind(0);
|
||||||
|
// glBindVertexArray(VAO);
|
||||||
|
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
|
// glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
|
||||||
|
// glBindVertexArray(0);
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void Cube::setupCube() {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// std::array<CubeVertex, 24> cubeVertices = {
|
||||||
|
// // Front face (z = 1.0f)
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
|
||||||
|
//
|
||||||
|
// // Back face (z = -1.0f)
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f)), // Top-left
|
||||||
|
//
|
||||||
|
// // Left face (x = -1.0f)
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
|
||||||
|
//
|
||||||
|
// // Right face (x = 1.0f)
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec2(0.0f, 1.0f)), // Top-left
|
||||||
|
//
|
||||||
|
// // Bottom face (y = -1.0f)
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, -1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)), // Top-left
|
||||||
|
//
|
||||||
|
// // Top face (y = 1.0f)
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, -1.0f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 0.0f)), // Bottom-left
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, -1.0f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)), // Bottom-right
|
||||||
|
// CubeVertex(glm::vec3( 1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)), // Top-right
|
||||||
|
// CubeVertex(glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(0.5f, 0.5f, 0.5f), glm::vec2(0.0f, 1.0f)) // Top-left
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// glGenVertexArrays(1, &VAO);
|
||||||
|
// glGenBuffers(1, &VBO);
|
||||||
|
// glGenBuffers(1, &EBO);
|
||||||
|
//
|
||||||
|
// glBindVertexArray(VAO);
|
||||||
|
// glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
// glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices.data(), GL_STATIC_DRAW);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
|
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices.data(), GL_STATIC_DRAW);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // Position attribute
|
||||||
|
// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, position));
|
||||||
|
// glEnableVertexAttribArray(0);
|
||||||
|
//
|
||||||
|
// // Color attribute
|
||||||
|
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, color));
|
||||||
|
// glEnableVertexAttribArray(1);
|
||||||
|
//
|
||||||
|
// // Texture Coords
|
||||||
|
// glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(CubeVertex), (void *) offsetof(CubeVertex, texCoords));
|
||||||
|
// glEnableVertexAttribArray(2);
|
||||||
|
//
|
||||||
|
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
// glBindVertexArray(0);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//Cube::Cube(const glm::vec3 &position, BlockType blockType): position(position), texture("assets/dirt.png"), type(blockType) {
|
||||||
|
// setupCube();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void Cube::LoadFace(Face face, std::vector<CubeVertex> &vertices) {
|
||||||
|
//
|
||||||
|
// glm::vec3 normal;
|
||||||
|
// switch (face) {
|
||||||
|
// case Face::TOP:
|
||||||
|
// normal = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
// break;
|
||||||
|
// case Face::BOTTOM:
|
||||||
|
// normal = glm::vec3(0.0f, -1.0f, 0.0f);
|
||||||
|
// break;
|
||||||
|
// case Face::LEFT:
|
||||||
|
// normal = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||||
|
// break;
|
||||||
|
// case Face::RIGHT:
|
||||||
|
// normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
// break;
|
||||||
|
// case Face::FRONT:
|
||||||
|
// normal = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
// break;
|
||||||
|
// case Face::BACK:
|
||||||
|
// normal = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// glm::vec3 color = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
// glm::vec2 texCoords = glm::vec2(0.0f, 0.0f);
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < 6; i++) {
|
||||||
|
// CubeVertex vertex = {
|
||||||
|
// unitVertices[faceVertices[face][i]],
|
||||||
|
// color,
|
||||||
|
// texCoords
|
||||||
|
// };
|
||||||
|
// vertices.push_back(vertex);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void Cube::LoadAllFaces(std::vector<CubeVertex> &vertices) {
|
||||||
|
// LoadFace(Face::TOP, vertices);
|
||||||
|
// LoadFace(Face::BOTTOM, vertices);
|
||||||
|
// LoadFace(Face::LEFT, vertices);
|
||||||
|
// LoadFace(Face::RIGHT, vertices);
|
||||||
|
// LoadFace(Face::FRONT, vertices);
|
||||||
|
// LoadFace(Face::BACK, vertices);
|
||||||
|
//}
|
||||||
89
gloom/src/gloom/old/Cube.h
Normal file
89
gloom/src/gloom/old/Cube.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
////
|
||||||
|
//// Created by Bram on 23/08/2024.
|
||||||
|
////
|
||||||
|
//
|
||||||
|
//#ifndef GLOOM_CUBE_H
|
||||||
|
//#define GLOOM_CUBE_H
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//#include <glm/glm.hpp>
|
||||||
|
//#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
//#include <glm/gtc/type_ptr.hpp>
|
||||||
|
//#include <vector>
|
||||||
|
//#include <iostream>
|
||||||
|
//#include <array>
|
||||||
|
//#include "glad/glad.h"
|
||||||
|
//#include "gloom/Texture.h"
|
||||||
|
//#include "gloom/config.hpp"
|
||||||
|
//#include "Chunk.h"
|
||||||
|
//#include "gloom/Mesh.h"
|
||||||
|
//
|
||||||
|
//struct CubeVertex {
|
||||||
|
// CubeVertex(glm::vec3 pos, glm::vec3 color, glm::vec2 texCoords) : position(pos), color(color),
|
||||||
|
// texCoords(texCoords) {};
|
||||||
|
//
|
||||||
|
// glm::vec3 position;
|
||||||
|
// glm::vec3 color;
|
||||||
|
// glm::vec2 texCoords;
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//struct CubeFace {
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//static std::array<unsigned int, 36> cubeIndices = {
|
||||||
|
// // Front face
|
||||||
|
// 0, 1, 2, // First triangle (0, 1, 2)
|
||||||
|
// 0, 2, 3, // Second triangle (0, 2, 3)
|
||||||
|
//
|
||||||
|
// // Back face
|
||||||
|
// 4, 5, 6, // First triangle (4, 5, 6)
|
||||||
|
// 4, 6, 7, // Second triangle (4, 6, 7)
|
||||||
|
//
|
||||||
|
// // Left face
|
||||||
|
// 8, 9, 10, // First triangle (8, 9, 10)
|
||||||
|
// 8, 10, 11,// Second triangle (8, 10, 11)
|
||||||
|
//
|
||||||
|
// // Right face
|
||||||
|
// 12, 13, 14,// First triangle (12, 13, 14)
|
||||||
|
// 12, 14, 15,// Second triangle (12, 14, 15)
|
||||||
|
//
|
||||||
|
// // Bottom face
|
||||||
|
// 16, 17, 18,// First triangle (16, 17, 18)
|
||||||
|
// 16, 18, 19,// Second triangle (16, 18, 19)
|
||||||
|
//
|
||||||
|
// // Top face
|
||||||
|
// 20, 21, 22,// First triangle (20, 21, 22)
|
||||||
|
// 20, 22, 23 // Second triangle (20, 22, 23)
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//enum Face {
|
||||||
|
// TOP = 0x01, // 0000 0001
|
||||||
|
// BOTTOM = 0x02, // 0000 0010
|
||||||
|
// LEFT = 0x04, // 0000 0100
|
||||||
|
// RIGHT = 0x08, // 0000 1000
|
||||||
|
// FRONT = 0x10, // 0001 0000
|
||||||
|
// BACK = 0x20 // 0010 0000
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//class Cube {
|
||||||
|
//public:
|
||||||
|
// explicit Cube(const glm::vec3 &position, BlockType blockType);
|
||||||
|
//
|
||||||
|
// void Draw(GLuint shaderProgram);
|
||||||
|
//
|
||||||
|
// void LoadFace(Face face, std::vector<CubeVertex>& vertices);
|
||||||
|
// void LoadAllFaces(std::vector<CubeVertex>& vertices);
|
||||||
|
//
|
||||||
|
// Mesh mesh;
|
||||||
|
//private:
|
||||||
|
// GLuint VAO{}, VBO{}, EBO{};
|
||||||
|
// glm::vec3 position;
|
||||||
|
//
|
||||||
|
// Texture texture;
|
||||||
|
// BlockType type{ BlockType::AIR };
|
||||||
|
// void setupCube();
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//#endif //GLOOM_CUBE_H
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
#ifndef SHADER_HPP
|
|
||||||
#define SHADER_HPP
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// System headers
|
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
// Standard headers
|
|
||||||
#include <cassert>
|
|
||||||
#include <fstream>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Gloom
|
|
||||||
{
|
|
||||||
class Shader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Shader() { mProgram = glCreateProgram(); }
|
|
||||||
|
|
||||||
// Public member functions
|
|
||||||
void activate() { glUseProgram(mProgram); }
|
|
||||||
void deactivate() { glUseProgram(0); }
|
|
||||||
GLuint get() { return mProgram; }
|
|
||||||
void destroy() { glDeleteProgram(mProgram); }
|
|
||||||
|
|
||||||
/* Attach a shader to the current shader program */
|
|
||||||
void attach(std::string const &filename)
|
|
||||||
{
|
|
||||||
// Load GLSL Shader from source
|
|
||||||
std::ifstream fd(filename.c_str());
|
|
||||||
if (fd.fail())
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"Something went wrong when attaching the Shader file at \"%s\".\n"
|
|
||||||
"The file may not exist or is currently inaccessible.\n",
|
|
||||||
filename.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto src = std::string(std::istreambuf_iterator<char>(fd),
|
|
||||||
(std::istreambuf_iterator<char>()));
|
|
||||||
|
|
||||||
// Create shader object
|
|
||||||
const char * source = src.c_str();
|
|
||||||
auto shader = create(filename);
|
|
||||||
glShaderSource(shader, 1, &source, nullptr);
|
|
||||||
glCompileShader(shader);
|
|
||||||
|
|
||||||
// Display errors
|
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &mStatus);
|
|
||||||
if (!mStatus)
|
|
||||||
{
|
|
||||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &mLength);
|
|
||||||
std::unique_ptr<char[]> buffer(new char[mLength]);
|
|
||||||
glGetShaderInfoLog(shader, mLength, nullptr, buffer.get());
|
|
||||||
fprintf(stderr, "%s\n%s", filename.c_str(), buffer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(mStatus);
|
|
||||||
|
|
||||||
// Attach shader and free allocated memory
|
|
||||||
glAttachShader(mProgram, shader);
|
|
||||||
glDeleteShader(shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Links all attached shaders together into a shader program */
|
|
||||||
void link()
|
|
||||||
{
|
|
||||||
// Link all attached shaders
|
|
||||||
glLinkProgram(mProgram);
|
|
||||||
|
|
||||||
// Display errors
|
|
||||||
glGetProgramiv(mProgram, GL_LINK_STATUS, &mStatus);
|
|
||||||
if (!mStatus)
|
|
||||||
{
|
|
||||||
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &mLength);
|
|
||||||
std::unique_ptr<char[]> buffer(new char[mLength]);
|
|
||||||
glGetProgramInfoLog(mProgram, mLength, nullptr, buffer.get());
|
|
||||||
fprintf(stderr, "%s\n", buffer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(mStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Convenience function that attaches and links a vertex and a
|
|
||||||
fragment shader in a shader program */
|
|
||||||
void makeBasicShader(std::string const &vertexFilename,
|
|
||||||
std::string const &fragmentFilename)
|
|
||||||
{
|
|
||||||
attach(vertexFilename);
|
|
||||||
attach(fragmentFilename);
|
|
||||||
link();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Used for debugging shader programs (expensive to run) */
|
|
||||||
bool isValid()
|
|
||||||
{
|
|
||||||
// Validate linked shader program
|
|
||||||
glValidateProgram(mProgram);
|
|
||||||
|
|
||||||
// Display errors
|
|
||||||
glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &mStatus);
|
|
||||||
if (!mStatus)
|
|
||||||
{
|
|
||||||
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &mLength);
|
|
||||||
std::unique_ptr<char[]> buffer(new char[mLength]);
|
|
||||||
glGetProgramInfoLog(mProgram, mLength, nullptr, buffer.get());
|
|
||||||
fprintf(stderr, "%s\n", buffer.get());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper function for creating shaders */
|
|
||||||
GLuint create(std::string const &filename)
|
|
||||||
{
|
|
||||||
// Extract file extension and create the correct shader type
|
|
||||||
auto idx = filename.rfind(".");
|
|
||||||
auto ext = filename.substr(idx + 1);
|
|
||||||
if (ext == "comp") return glCreateShader(GL_COMPUTE_SHADER);
|
|
||||||
else if (ext == "frag") return glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
else if (ext == "geom") return glCreateShader(GL_GEOMETRY_SHADER);
|
|
||||||
else if (ext == "tcs") return glCreateShader(GL_TESS_CONTROL_SHADER);
|
|
||||||
else if (ext == "tes") return glCreateShader(GL_TESS_EVALUATION_SHADER);
|
|
||||||
else if (ext == "vert") return glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Disable copying and assignment
|
|
||||||
Shader(Shader const &) = delete;
|
|
||||||
Shader & operator =(Shader const &) = delete;
|
|
||||||
|
|
||||||
// Private member variables
|
|
||||||
GLuint mProgram;
|
|
||||||
GLint mStatus;
|
|
||||||
GLint mLength;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,82 +1,19 @@
|
|||||||
// Local headers
|
// Local headers
|
||||||
#include "gloom/gloom.hpp"
|
#include "gloom/config.hpp"
|
||||||
#include "program.hpp"
|
#include "Game.h"
|
||||||
|
|
||||||
// System headers
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
// Standard headers
|
// Standard headers
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
// A callback which allows GLFW to report errors whenever they occur
|
|
||||||
static void glfwErrorCallback(int error, const char *description)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "GLFW returned an error:\n\t%s (%i)\n", description, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GLFWwindow* initialise()
|
|
||||||
{
|
|
||||||
// Initialise GLFW
|
|
||||||
if (!glfwInit())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Could not start GLFW\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set core window options (adjust version numbers if needed)
|
int main(int argc, char *argb[]) {
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
srand(time(nullptr));
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
std::cout << "Seed: " << SEED << std::endl;
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
Game game;
|
||||||
|
game.run();
|
||||||
// Enable the GLFW runtime error callback function defined previously.
|
|
||||||
glfwSetErrorCallback(glfwErrorCallback);
|
|
||||||
|
|
||||||
// Set additional window options
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, windowResizable);
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, windowSamples); // MSAA
|
|
||||||
|
|
||||||
// Create window using GLFW
|
|
||||||
GLFWwindow* window = glfwCreateWindow(windowWidth,
|
|
||||||
windowHeight,
|
|
||||||
windowTitle.c_str(),
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
// Ensure the window is set up correctly
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Could not open GLFW window\n");
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the window be the current OpenGL context and initialise glad
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
gladLoadGL();
|
|
||||||
|
|
||||||
// Print various OpenGL information to stdout
|
|
||||||
printf("%s: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
|
|
||||||
printf("GLFW\t %s\n", glfwGetVersionString());
|
|
||||||
printf("OpenGL\t %s\n", glGetString(GL_VERSION));
|
|
||||||
printf("GLSL\t %s\n\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argb[])
|
|
||||||
{
|
|
||||||
// Initialise window using GLFW
|
|
||||||
GLFWwindow* window = initialise();
|
|
||||||
|
|
||||||
// Run an OpenGL application using this window
|
|
||||||
runProgram(window);
|
|
||||||
|
|
||||||
// Terminate GLFW (no need to call glfwDestroyWindow)
|
|
||||||
glfwTerminate();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
// Local headers
|
|
||||||
#include "program.hpp"
|
|
||||||
#include "gloom/gloom.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
void runProgram(GLFWwindow* window)
|
|
||||||
{
|
|
||||||
// Enable depth (Z) buffer (accept "closest" fragment)
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glDepthFunc(GL_LESS);
|
|
||||||
|
|
||||||
// Configure miscellaneous OpenGL settings
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
// Set default colour after clearing the colour buffer
|
|
||||||
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
|
|
||||||
|
|
||||||
// Set up your scene here (create Vertex Array Objects, etc.)
|
|
||||||
|
|
||||||
// Rendering Loop
|
|
||||||
while (!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
// Clear colour and depth buffers
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Draw your scene here
|
|
||||||
|
|
||||||
// Handle other events
|
|
||||||
glfwPollEvents();
|
|
||||||
handleKeyboardInput(window);
|
|
||||||
|
|
||||||
// Flip buffers
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void handleKeyboardInput(GLFWwindow* window)
|
|
||||||
{
|
|
||||||
// Use escape key for terminating the GLFW window
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
|
||||||
{
|
|
||||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#ifndef PROGRAM_HPP
|
|
||||||
#define PROGRAM_HPP
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
// System headers
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
// Main OpenGL program
|
|
||||||
void runProgram(GLFWwindow* window);
|
|
||||||
|
|
||||||
|
|
||||||
// Function for handling keypresses
|
|
||||||
void handleKeyboardInput(GLFWwindow* window);
|
|
||||||
|
|
||||||
|
|
||||||
// Checks for whether an OpenGL error occurred. If one did,
|
|
||||||
// it prints out the error type and ID
|
|
||||||
inline void printGLError() {
|
|
||||||
int errorID = glGetError();
|
|
||||||
|
|
||||||
if(errorID != GL_NO_ERROR) {
|
|
||||||
std::string errorString;
|
|
||||||
|
|
||||||
switch(errorID) {
|
|
||||||
case GL_INVALID_ENUM:
|
|
||||||
errorString = "GL_INVALID_ENUM";
|
|
||||||
break;
|
|
||||||
case GL_INVALID_OPERATION:
|
|
||||||
errorString = "GL_INVALID_OPERATION";
|
|
||||||
break;
|
|
||||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
||||||
errorString = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
|
||||||
break;
|
|
||||||
case GL_OUT_OF_MEMORY:
|
|
||||||
errorString = "GL_OUT_OF_MEMORY";
|
|
||||||
break;
|
|
||||||
case GL_STACK_UNDERFLOW:
|
|
||||||
errorString = "GL_STACK_UNDERFLOW";
|
|
||||||
break;
|
|
||||||
case GL_STACK_OVERFLOW:
|
|
||||||
errorString = "GL_STACK_OVERFLOW";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errorString = "[Unknown error ID]";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "An OpenGL error occurred (%i): %s.\n",
|
|
||||||
errorID, errorString.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user