Episode 4 - Water

This commit is contained in:
WSAL Evan 2024-10-18 10:07:14 -04:00
parent 117e2c321d
commit 4e1c4fe98a
22 changed files with 1007 additions and 298 deletions

View File

@ -180,6 +180,7 @@
<ClInclude Include="src\Planet.h" />
<ClInclude Include="src\Shader.h" />
<ClInclude Include="src\SurfaceFeature.h" />
<ClInclude Include="src\Vertex.h" />
<ClInclude Include="vendor\imgui\imconfig.h" />
<ClInclude Include="vendor\imgui\imgui.h" />
<ClInclude Include="vendor\imgui\imgui_impl_glfw.h" />
@ -193,8 +194,14 @@
<ClInclude Include="vendor\stb_image.h" />
</ItemGroup>
<ItemGroup>
<None Include="assets\shaders\fragment_shader.glsl" />
<None Include="assets\shaders\vertex_shader.glsl" />
<None Include="assets\shaders\billboard_frag.glsl" />
<None Include="assets\shaders\billboard_vert.glsl" />
<None Include="assets\shaders\framebuffer_frag.glsl" />
<None Include="assets\shaders\framebuffer_vert.glsl" />
<None Include="assets\shaders\main_frag.glsl" />
<None Include="assets\shaders\main_vert.glsl" />
<None Include="assets\shaders\water_frag.glsl" />
<None Include="assets\shaders\water_vert.glsl" />
</ItemGroup>
<ItemGroup>
<Image Include="assets\sprites\block_map.png" />

View File

@ -131,10 +131,19 @@
<ClInclude Include="src\SurfaceFeature.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Vertex.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="assets\shaders\vertex_shader.glsl" />
<None Include="assets\shaders\fragment_shader.glsl" />
<None Include="assets\shaders\main_vert.glsl" />
<None Include="assets\shaders\main_frag.glsl" />
<None Include="assets\shaders\water_frag.glsl" />
<None Include="assets\shaders\water_vert.glsl" />
<None Include="assets\shaders\billboard_vert.glsl" />
<None Include="assets\shaders\billboard_frag.glsl" />
<None Include="assets\shaders\framebuffer_vert.glsl" />
<None Include="assets\shaders\framebuffer_frag.glsl" />
</ItemGroup>
<ItemGroup>
<Image Include="assets\sprites\block_map.png">

View File

@ -0,0 +1,27 @@
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D tex;
const vec3 ambient = vec3(.5);
const vec3 lightDirection = vec3(0.8, 1, 0.7);
const vec3 normal = vec3( 0, -1, 0);
void main()
{
vec3 lightDir = normalize(-lightDirection);
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diff * vec3(1);
vec4 result = vec4(ambient + diffuse, 1.0);
vec4 texResult = texture(tex, TexCoord);
if (texResult.a == 0)
discard;
FragColor = texResult * result;
}

View File

@ -0,0 +1,19 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
out vec3 Normal;
uniform float texMultiplier;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = aTexCoord * texMultiplier;
}

View File

@ -0,0 +1,32 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
uniform sampler2D depthTexture;
uniform bool underwater;
const vec3 fogColor = vec3(0, 0, 0.25);
const float fogNear = 0.9;
const float fogFar = 1.0;
void main()
{
vec3 color = texture(screenTexture, TexCoords).rgb;
float depth = texture(depthTexture, TexCoords).r;
vec3 finalColor = color;
// Calculate fog
if (underwater)
{
float fogFactor = (fogFar - depth) / (fogFar - fogNear);
fogFactor = clamp(fogFactor, 0.0, 1.0);
finalColor = mix(fogColor, color, fogFactor);
}
FragColor = vec4(vec3(finalColor), 1.0);
}

View File

@ -0,0 +1,12 @@
#version 330 core
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inTexCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(inPos.x, inPos.y, 0.0, 1.0);
TexCoords = inTexCoords;
}

View File

@ -1,6 +1,5 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in int aDirection;
@ -13,6 +12,7 @@ uniform float texMultiplier;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform float time;
// Array of possible normals based on direction
const vec3 normals[] = vec3[](

View File

@ -0,0 +1,26 @@
#version 330 core
in vec2 TexCoord;
in vec3 Normal;
out vec4 FragColor;
uniform sampler2D tex;
vec3 ambient = vec3(.5);
vec3 lightDirection = vec3(0.8, 1, 0.7);
void main()
{
vec3 lightDir = normalize(-lightDirection);
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = diff * vec3(1);
vec4 result = vec4(ambient + diffuse, 1.0);
vec4 texResult = texture(tex, TexCoord);
if (texResult.a == 0)
discard;
FragColor = texResult * result;
}

View File

@ -0,0 +1,47 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in int aDirection;
layout (location = 3) in int aTop;
out vec2 TexCoord;
out vec3 Normal;
uniform float texMultiplier;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform float time;
// Array of possible normals based on direction
const vec3 normals[] = vec3[](
vec3( 0, 0, 1), // 0
vec3( 0, 0, -1), // 1
vec3( 1, 0, 0), // 2
vec3(-1, 0, 0), // 3
vec3( 0, 1, 0), // 4
vec3( 0, -1, 0), // 5
vec3( 0, -1, 0) // 6
);
const int aFrames = 32;
const float animationTime = 5;
const int texNum = 16;
void main()
{
vec3 pos = aPos;
if (aTop == 1)
{
pos.y -= .1;
pos.y += (sin(pos.x * 3.1415926535 / 2 + time) + sin(pos.z * 3.1415926535 / 2 + time * 1.5)) * .05;
}
gl_Position = projection * view * model * vec4(pos, 1.0);
vec2 currentTex = aTexCoord;
currentTex.x += mod(floor(mod(time / animationTime, 1) * aFrames), texNum);
currentTex.y += floor(floor(mod(time / animationTime, 1) * aFrames) / texNum);
TexCoord = currentTex * texMultiplier;
Normal = normals[aDirection];
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -16,6 +16,7 @@
#include "Shader.h"
#include "Camera.h"
#include "Planet.h"
#include "Blocks.h"
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
@ -43,6 +44,18 @@ Camera camera;
// Window options
#define VSYNC 1 // 0 for off, 1 for on
float rectangleVertices[] =
{
// Coords // TexCoords
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f
};
int main()
{
// Initialize GLFW
@ -84,13 +97,71 @@ int main()
glEnable(GL_DEPTH_TEST);
// Create shader
Shader shader("assets/shaders/vertex_shader.glsl", "assets/shaders/fragment_shader.glsl");
// Create shaders
Shader shader("assets/shaders/main_vert.glsl", "assets/shaders/main_frag.glsl");
shader.use();
shader.setFloat("texMultiplier", .25f);
shader.setFloat("texMultiplier", 0.0625f);
// Create texture
Shader waterShader("assets/shaders/water_vert.glsl", "assets/shaders/water_frag.glsl");
waterShader.use();
waterShader.setFloat("texMultiplier", 0.0625f);
Shader billboardShader("assets/shaders/billboard_vert.glsl", "assets/shaders/billboard_frag.glsl");
billboardShader.use();
billboardShader.setFloat("texMultiplier", 0.0625f);
Shader framebufferShader("assets/shaders/framebuffer_vert.glsl", "assets/shaders/framebuffer_frag.glsl");
// Create post-processing framebuffer
unsigned int FBO;
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
unsigned int framebufferTexture;
glGenTextures(1, &framebufferTexture);
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, windowX, windowY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);
unsigned int depthTexture;
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, windowX, windowY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer error: " << fboStatus << '\n';
unsigned int rectVAO, rectVBO;
glGenVertexArrays(1, &rectVAO);
glGenBuffers(1, &rectVBO);
glBindVertexArray(rectVAO);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangleVertices), &rectangleVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
framebufferShader.use();
glUniform1i(glGetUniformLocation(framebufferShader.ID, "screenTexture"), 0);
glUniform1i(glGetUniformLocation(framebufferShader.ID, "depthTexture"), 1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Create terrain texture
unsigned int texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
@ -122,7 +193,7 @@ int main()
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Planet::planet = new Planet();
Planet::planet = new Planet(&shader, &waterShader, &billboardShader);
// Initialize ImGui
IMGUI_CHECKVERSION();
@ -158,11 +229,19 @@ int main()
fpsStartTime = currentTimePoint;
}
waterShader.use();
waterShader.setFloat("time", currentFrame);
// Input
processInput(window);
// Rendering
glEnable(GL_DEPTH_TEST);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// New ImGui frame
ImGui_ImplOpenGL3_NewFrame();
@ -173,15 +252,69 @@ int main()
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection;
projection = glm::perspective(glm::radians(camera.Zoom), windowX / windowY, 0.1f, 100.0f);
projection = glm::perspective(glm::radians(camera.Zoom), windowX / windowY, 0.1f, 1000.0f);
shader.use();
unsigned int viewLoc = glGetUniformLocation(shader.ID, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
unsigned int projectionLoc = glGetUniformLocation(shader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
unsigned int modelLoc = glGetUniformLocation(shader.ID, "model");
waterShader.use();
viewLoc = glGetUniformLocation(waterShader.ID, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
projectionLoc = glGetUniformLocation(waterShader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
Planet::planet->Update(camera.Position.x, camera.Position.y, camera.Position.z, modelLoc);
billboardShader.use();
viewLoc = glGetUniformLocation(billboardShader.ID, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
projectionLoc = glGetUniformLocation(billboardShader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
Planet::planet->Update(camera.Position.x, camera.Position.y, camera.Position.z);
framebufferShader.use();
// Check if player is underwater
int blockX = camera.Position.x < 0 ? camera.Position.x - 1 : camera.Position.x;
int blockY = camera.Position.y < 0 ? camera.Position.y - 1 : camera.Position.y;
int blockZ = camera.Position.z < 0 ? camera.Position.z - 1 : camera.Position.z;
int chunkX = blockX < 0 ? floorf(blockX / (float)Planet::chunkSize) : blockX / (int)Planet::chunkSize;
int chunkY = blockY < 0 ? floorf(blockY / (float)Planet::chunkSize) : blockY / (int)Planet::chunkSize;
int chunkZ = blockZ < 0 ? floorf(blockZ / (float)Planet::chunkSize) : blockZ / (int)Planet::chunkSize;
int localBlockX = blockX - (chunkX * Planet::chunkSize);
int localBlockY = blockY - (chunkY * Planet::chunkSize);
int localBlockZ = blockZ - (chunkZ * Planet::chunkSize);
Chunk* chunk = Planet::planet->GetChunk(chunkX, chunkY, chunkZ);
if (chunk != nullptr)
{
unsigned int blockType = chunk->GetBlockAtPos(
localBlockX,
localBlockY,
localBlockZ);
if (Blocks::blocks[blockType].blockType == Block::LIQUID)
{
framebufferShader.setBool("underwater", true);
}
else
{
framebufferShader.setBool("underwater", false);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(rectVAO);
glDisable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Draw ImGui UI
ImGui::Begin("Test");

View File

@ -1,7 +1,7 @@
#include "Block.h"
Block::Block(char minX, char minY, char maxX, char maxY, bool transparent, bool billboard)
: transparent(transparent), billboard(billboard)
Block::Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType)
: blockType(blockType)
{
topMinX = minX;
topMinY = minY;
@ -21,8 +21,8 @@ Block::Block(char minX, char minY, char maxX, char maxY, bool transparent, bool
Block::Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, bool transparent, bool billboard)
: transparent(transparent), billboard(billboard)
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType)
: blockType(blockType)
{
this->topMinX = topMinX;
this->topMinY = topMinY;

View File

@ -3,14 +3,23 @@
struct Block
{
public:
enum BLOCK_TYPE
{
SOLID,
TRANSPARENT,
LEAVES,
BILLBOARD,
LIQUID
};
char topMinX, topMinY, topMaxX, topMaxY;
char bottomMinX, bottomMinY, bottomMaxX, bottomMaxY;
char sideMinX, sideMinY, sideMaxX, sideMaxY;
bool transparent;
bool billboard;
BLOCK_TYPE blockType;
Block(char minX, char minY, char maxX, char maxY, bool transparent = false, bool billboard = false);
Block(char minX, char minY, char maxX, char maxY, BLOCK_TYPE blockType);
Block(char topMinX, char topMinY, char topMaxX, char topMaxY,
char bottomMinX, char bottomMinY, char bottomMaxX, char bottomMaxY,
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, bool transparent = false, bool billboard = false);
char sideMinX, char sideMinY, char sideMaxX, char sideMaxY, BLOCK_TYPE blockType);
};

View File

@ -7,27 +7,28 @@
namespace Blocks
{
const std::vector<Block> blocks{
Block(0, 0, 0, 0, true), // Air block
Block(0, 0, 1, 1), // Dirt block
Block(0, 0, 0, 0, Block::TRANSPARENT), // Air block
Block(0, 0, 1, 1, Block::SOLID), // Dirt block
Block(1, 1, 2, 2, // Grass block
Block(1, 1, 2, 2, // Grass block
0, 0, 1, 1,
1, 0, 2, 1),
1, 0, 2, 1, Block::SOLID),
Block(0, 1, 1, 2), // Stone block
Block(0, 1, 1, 2, Block::SOLID), // Stone block
Block(2, 1, 3, 2, // Log
Block(2, 1, 3, 2, // Log
2, 1, 3, 2,
2, 0, 3, 1),
2, 0, 3, 1, Block::SOLID),
Block(0, 2, 1, 3, true), // Leaves
Block(1, 2, 2, 3, true, true), // Grass
Block(3, 0, 4, 1, true, true), // Tall Grass Bottom
Block(3, 1, 4, 2, true, true), // Tall Grass Top
Block(0, 3, 1, 4, true, true), // Poppy
Block(2, 2, 3, 3, true, true), // White Tulip
Block(3, 2, 4, 3, true, true), // Pink Tulip
Block(1, 3, 2, 4, true, true), // Orange Tulip
Block(0, 2, 1, 3, Block::LEAVES), // Leaves
Block(1, 2, 2, 3, Block::BILLBOARD), // Grass
Block(3, 0, 4, 1, Block::BILLBOARD), // Tall Grass Bottom
Block(3, 1, 4, 2, Block::BILLBOARD), // Tall Grass Top
Block(0, 3, 1, 4, Block::BILLBOARD), // Poppy
Block(2, 2, 3, 3, Block::BILLBOARD), // White Tulip
Block(3, 2, 4, 3, Block::BILLBOARD), // Pink Tulip
Block(1, 3, 2, 4, Block::BILLBOARD), // Orange Tulip
Block(0, 4, 1, 5, Block::LIQUID) // Water
};
enum BLOCKS
@ -45,5 +46,6 @@ namespace Blocks
WHITE_TULIP = 10,
PINK_TULIP = 11,
ORANGE_TULIP = 12,
WATER = 13
};
}

View File

@ -2,18 +2,17 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include "Planet.h"
#include "Blocks.h"
#include "WorldGen.h"
Chunk::Chunk(unsigned int chunkSize, glm::vec3 chunkPos)
Chunk::Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader)
: chunkSize(chunkSize), chunkPos(chunkPos)
{
this->chunkSize = chunkSize;
this->chunkPos = chunkPos;
worldPos = glm::vec3(chunkPos.x * chunkSize, chunkPos.y * chunkSize, chunkPos.z * chunkSize);
ready = false;
@ -26,9 +25,17 @@ Chunk::~Chunk()
if (chunkThread.joinable())
chunkThread.join();
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteVertexArrays(1, &vertexArrayObject);
glDeleteBuffers(1, &mainVBO);
glDeleteBuffers(1, &mainEBO);
glDeleteVertexArrays(1, &mainVAO);
glDeleteBuffers(1, &waterVBO);
glDeleteBuffers(1, &waterEBO);
glDeleteVertexArrays(1, &waterVAO);
glDeleteBuffers(1, &billboardVBO);
glDeleteBuffers(1, &billboardEBO);
glDeleteVertexArrays(1, &billboardVAO);
}
void Chunk::GenerateChunk()
@ -48,6 +55,8 @@ void Chunk::GenerateChunk()
//std::cout << "Got chunk data in thread: " << std::this_thread::get_id() << '\n';
unsigned int currentVertex = 0;
unsigned int currentLiquidVertex = 0;
unsigned int currentBillboardVertex = 0;
for (char x = 0; x < chunkSize; x++)
{
for (char z = 0; z < chunkSize; z++)
@ -60,59 +69,48 @@ void Chunk::GenerateChunk()
const Block* block = &Blocks::blocks[chunkData[index]];
if (block->billboard)
int topBlock;
if (y < chunkSize - 1)
{
vertices.push_back(Vertex(x + .85355f, y + 0, z + .85355f, block->sideMinX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .14645f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .85355f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY, 6));
vertices.push_back(Vertex(x + .14645f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY, 6));
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1);
topBlock = chunkData[blockIndex];
}
else
{
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0;
topBlock = upData[blockIndex];
}
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
const Block* topBlockType = &Blocks::blocks[topBlock];
char waterTopValue = topBlockType->blockType == Block::TRANSPARENT ? 1 : 0;
vertices.push_back(Vertex(x + .14645f, y + 0, z + .14645f, block->sideMinX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .85355f, y + 0, z + .85355f, block->sideMaxX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .14645f, y + 1, z + .14645f, block->sideMinX, block->sideMaxY, 6));
vertices.push_back(Vertex(x + .85355f, y + 1, z + .85355f, block->sideMaxX, block->sideMaxY, 6));
if (block->blockType == Block::BILLBOARD)
{
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 0, z + .85355f, block->sideMinX, block->sideMinY));
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY));
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY));
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
billboardIndices.push_back(currentBillboardVertex + 0);
billboardIndices.push_back(currentBillboardVertex + 3);
billboardIndices.push_back(currentBillboardVertex + 1);
billboardIndices.push_back(currentBillboardVertex + 0);
billboardIndices.push_back(currentBillboardVertex + 2);
billboardIndices.push_back(currentBillboardVertex + 3);
currentBillboardVertex += 4;
vertices.push_back(Vertex(x + .14645f, y + 0, z + .85355f, block->sideMinX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .85355f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .14645f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY, 6));
vertices.push_back(Vertex(x + .85355f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY, 6));
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 0, z + .85355f, block->sideMinX, block->sideMinY));
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 0, z + .14645f, block->sideMaxX, block->sideMinY));
billboardVertices.push_back(BillboardVertex(x + .14645f, y + 1, z + .85355f, block->sideMinX, block->sideMaxY));
billboardVertices.push_back(BillboardVertex(x + .85355f, y + 1, z + .14645f, block->sideMaxX, block->sideMaxY));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
vertices.push_back(Vertex(x + .85355f, y + 0, z + .14645f, block->sideMinX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .14645f, y + 0, z + .85355f, block->sideMaxX, block->sideMinY, 6));
vertices.push_back(Vertex(x + .85355f, y + 1, z + .14645f, block->sideMinX, block->sideMaxY, 6));
vertices.push_back(Vertex(x + .14645f, y + 1, z + .85355f, block->sideMaxX, block->sideMaxY, 6));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
billboardIndices.push_back(currentBillboardVertex + 0);
billboardIndices.push_back(currentBillboardVertex + 3);
billboardIndices.push_back(currentBillboardVertex + 1);
billboardIndices.push_back(currentBillboardVertex + 0);
billboardIndices.push_back(currentBillboardVertex + 2);
billboardIndices.push_back(currentBillboardVertex + 3);
currentBillboardVertex += 4;
}
else
{
@ -132,20 +130,41 @@ void Chunk::GenerateChunk()
const Block* northBlockType = &Blocks::blocks[northBlock];
if (northBlockType->transparent)
if (northBlockType->blockType == Block::LEAVES
|| northBlockType->blockType == Block::TRANSPARENT
|| northBlockType->blockType == Block::BILLBOARD
|| (northBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
{
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0));
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0));
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0));
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0));
if (block->blockType == Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0, 0));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0, waterTopValue));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0, waterTopValue));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
else
{
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMinX, block->sideMinY, 0));
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMaxX, block->sideMinY, 0));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMinX, block->sideMaxY, 0));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 0));
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
}
@ -165,20 +184,41 @@ void Chunk::GenerateChunk()
const Block* southBlockType = &Blocks::blocks[southBlock];
if (southBlockType->transparent)
if (southBlockType->blockType == Block::LEAVES
|| southBlockType->blockType == Block::TRANSPARENT
|| southBlockType->blockType == Block::BILLBOARD
|| (southBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
{
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1));
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1));
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1));
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1));
if (block->blockType == Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1, 0));
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1, waterTopValue));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1, waterTopValue));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
else
{
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMinX, block->sideMinY, 1));
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMaxX, block->sideMinY, 1));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMinX, block->sideMaxY, 1));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 1));
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
}
@ -198,20 +238,41 @@ void Chunk::GenerateChunk()
const Block* westBlockType = &Blocks::blocks[westBlock];
if (westBlockType->transparent)
if (westBlockType->blockType == Block::LEAVES
|| westBlockType->blockType == Block::TRANSPARENT
|| westBlockType->blockType == Block::BILLBOARD
|| (westBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
{
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2));
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2));
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2));
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2));
if (block->blockType == Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2, waterTopValue));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2, waterTopValue));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
else
{
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->sideMinX, block->sideMinY, 2));
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->sideMaxX, block->sideMinY, 2));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->sideMinX, block->sideMaxY, 2));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->sideMaxX, block->sideMaxY, 2));
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
}
@ -231,20 +292,41 @@ void Chunk::GenerateChunk()
const Block* eastBlockType = &Blocks::blocks[eastBlock];
if (eastBlockType->transparent)
if (eastBlockType->blockType == Block::LEAVES
|| eastBlockType->blockType == Block::TRANSPARENT
|| eastBlockType->blockType == Block::BILLBOARD
|| (eastBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
{
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3));
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3));
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3));
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3));
if (block->blockType == Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3, 0));
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3, 0));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3, waterTopValue));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3, waterTopValue));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
else
{
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->sideMinX, block->sideMinY, 3));
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->sideMaxX, block->sideMinY, 3));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->sideMinX, block->sideMaxY, 3));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->sideMaxX, block->sideMaxY, 3));
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
}
@ -264,52 +346,93 @@ void Chunk::GenerateChunk()
const Block* bottomBlockType = &Blocks::blocks[bottomBlock];
if (bottomBlockType->transparent)
if (bottomBlockType->blockType == Block::LEAVES
|| bottomBlockType->blockType == Block::TRANSPARENT
|| bottomBlockType->blockType == Block::BILLBOARD
|| (bottomBlockType->blockType == Block::LIQUID && block->blockType != Block::LIQUID))
{
vertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4));
vertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4));
vertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4));
vertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4));
if (block->blockType == Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4, 0));
waterVertices.push_back(WaterVertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4, 0));
waterVertices.push_back(WaterVertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4, 0));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
currentVertex += 4;
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
else
{
mainVertices.push_back(Vertex(x + 1, y + 0, z + 1, block->bottomMinX, block->bottomMinY, 4));
mainVertices.push_back(Vertex(x + 0, y + 0, z + 1, block->bottomMaxX, block->bottomMinY, 4));
mainVertices.push_back(Vertex(x + 1, y + 0, z + 0, block->bottomMinX, block->bottomMaxY, 4));
mainVertices.push_back(Vertex(x + 0, y + 0, z + 0, block->bottomMaxX, block->bottomMaxY, 4));
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
}
// Top
{
int topBlock;
if (y < chunkSize - 1)
if (block->blockType == Block::LIQUID)
{
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + (y + 1);
topBlock = chunkData[blockIndex];
if (topBlockType->blockType != Block::LIQUID)
{
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5, 1));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5, 1));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5, 1));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5, 1));
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 1, block->topMinX, block->topMinY, 5, 1));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 1, block->topMaxX, block->topMinY, 5, 1));
waterVertices.push_back(WaterVertex(x + 1, y + 1, z + 0, block->topMinX, block->topMaxY, 5, 1));
waterVertices.push_back(WaterVertex(x + 0, y + 1, z + 0, block->topMaxX, block->topMaxY, 5, 1));
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 3);
waterIndices.push_back(currentLiquidVertex + 1);
waterIndices.push_back(currentLiquidVertex + 0);
waterIndices.push_back(currentLiquidVertex + 2);
waterIndices.push_back(currentLiquidVertex + 3);
currentLiquidVertex += 4;
}
}
else
else if (topBlockType->blockType == Block::LEAVES
|| topBlockType->blockType == Block::TRANSPARENT
|| topBlockType->blockType == Block::BILLBOARD
|| topBlockType->blockType == Block::LIQUID)
{
int blockIndex = x * chunkSize * chunkSize + z * chunkSize + 0;
topBlock = upData[blockIndex];
}
mainVertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5));
mainVertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5));
mainVertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5));
const Block* topBlockType = &Blocks::blocks[topBlock];
if (topBlockType->transparent)
{
vertices.push_back(Vertex(x + 0, y + 1, z + 1, block->topMinX, block->topMinY, 5));
vertices.push_back(Vertex(x + 1, y + 1, z + 1, block->topMaxX, block->topMinY, 5));
vertices.push_back(Vertex(x + 0, y + 1, z + 0, block->topMinX, block->topMaxY, 5));
vertices.push_back(Vertex(x + 1, y + 1, z + 0, block->topMaxX, block->topMaxY, 5));
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 3);
indices.push_back(currentVertex + 1);
indices.push_back(currentVertex + 0);
indices.push_back(currentVertex + 2);
indices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 3);
mianIndices.push_back(currentVertex + 1);
mianIndices.push_back(currentVertex + 0);
mianIndices.push_back(currentVertex + 2);
mianIndices.push_back(currentVertex + 3);
currentVertex += 4;
}
}
@ -325,31 +448,78 @@ void Chunk::GenerateChunk()
//std::cout << "Generated: " << generated << '\n';
}
void Chunk::Render(unsigned int modelLoc)
void Chunk::Render(Shader* mainShader, Shader* billboardShader)
{
if (!ready)
{
if (generated)
{
numTriangles = indices.size();
// Solid
numTrianglesMain = mianIndices.size();
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glGenVertexArrays(1, &mainVAO);
glGenBuffers(1, &mainVBO);
glGenBuffers(1, &mainEBO);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
glBindVertexArray(mainVAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
glBindBuffer(GL_ARRAY_BUFFER, mainVBO);
glBufferData(GL_ARRAY_BUFFER, mainVertices.size() * sizeof(Vertex), mainVertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mianIndices.size() * sizeof(unsigned int), mianIndices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, posX));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texGridX));
glEnableVertexAttribArray(1);
glVertexAttribIPointer(2, 1, GL_BYTE, sizeof(Vertex), (void*)offsetof(Vertex, direction));
glEnableVertexAttribArray(2);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
// Water
numTrianglesWater = waterIndices.size();
glGenVertexArrays(1, &waterVAO);
glGenBuffers(1, &waterVBO);
glGenBuffers(1, &waterEBO);
glBindVertexArray(waterVAO);
glBindBuffer(GL_ARRAY_BUFFER, waterVBO);
glBufferData(GL_ARRAY_BUFFER, waterVertices.size() * sizeof(WaterVertex), waterVertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, waterEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, waterIndices.size() * sizeof(unsigned int), waterIndices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, posX));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, texGridX));
glEnableVertexAttribArray(1);
glVertexAttribIPointer(2, 1, GL_BYTE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, direction));
glEnableVertexAttribArray(2);
glVertexAttribIPointer(3, 1, GL_BYTE, sizeof(WaterVertex), (void*)offsetof(WaterVertex, top));
glEnableVertexAttribArray(3);
ready = true;
// Billboard
numTrianglesBillboard = billboardIndices.size();
glGenVertexArrays(1, &billboardVAO);
glGenBuffers(1, &billboardVBO);
glGenBuffers(1, &billboardEBO);
glBindVertexArray(billboardVAO);
glBindBuffer(GL_ARRAY_BUFFER, billboardVBO);
glBufferData(GL_ARRAY_BUFFER, billboardVertices.size() * sizeof(BillboardVertex), billboardVertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, billboardEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, billboardIndices.size() * sizeof(unsigned int), billboardIndices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(BillboardVertex), (void*)offsetof(BillboardVertex, posX));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_BYTE, GL_FALSE, sizeof(BillboardVertex), (void*)offsetof(BillboardVertex, texGridX));
glEnableVertexAttribArray(1);
ready = true;
}
@ -359,11 +529,54 @@ void Chunk::Render(unsigned int modelLoc)
//std::cout << "Rendering chunk " << chunkPos.x << ", " << chunkPos.y << ", " << chunkPos.z << '\n'
// << "Chunk VAO: " << vertexArrayObject << '\n' << "Triangles: " << numTriangles << '\n';
glBindVertexArray(vertexArrayObject);
// Calculate model matrix
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, worldPos);
// Render main mesh
mainShader->use();
modelLoc = glGetUniformLocation(mainShader->ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(mainVAO);
glDrawElements(GL_TRIANGLES, numTrianglesMain, GL_UNSIGNED_INT, 0);
// Render billboard mesh
billboardShader->use();
modelLoc = glGetUniformLocation(billboardShader->ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDisable(GL_CULL_FACE);
glBindVertexArray(billboardVAO);
glDrawElements(GL_TRIANGLES, numTrianglesBillboard, GL_UNSIGNED_INT, 0);
glEnable(GL_CULL_FACE);
}
void Chunk::RenderWater(Shader* shader)
{
if (!ready)
return;
//std::cout << "Rendering chunk " << chunkPos.x << ", " << chunkPos.y << ", " << chunkPos.z << '\n'
// << "Chunk VAO: " << vertexArrayObject << '\n' << "Triangles: " << numTriangles << '\n';
modelLoc = glGetUniformLocation(shader->ID, "model");
glBindVertexArray(waterVAO);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, worldPos);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, numTriangles, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, numTrianglesWater, GL_UNSIGNED_INT, 0);
}
unsigned int Chunk::GetBlockAtPos(int x, int y, int z)
{
if (!ready)
return 0;
int index = x * chunkSize * chunkSize + z * chunkSize + y;
return chunkData[index];
}

View File

@ -4,33 +4,19 @@
#include <thread>
#include <glm/glm.hpp>
struct Vertex
{
float posX, posY, posZ;
char texGridX, texGridY;
char direction;
Vertex(float _posX, float _posY, float _posZ, char _texGridX, char _texGridY, char _direction)
{
posX = _posX;
posY = _posY;
posZ = _posZ;
texGridX = _texGridX;
texGridY = _texGridY;
direction = _direction;
}
};
#include "Shader.h"
#include "Vertex.h"
class Chunk
{
public:
Chunk(unsigned int chunkSize, glm::vec3 chunkPos);
Chunk(unsigned int chunkSize, glm::vec3 chunkPos, Shader* shader, Shader* waterShader);
~Chunk();
void GenerateChunk();
void Render(unsigned int modelLoc);
void Render(Shader* mainShader, Shader* billboardShader);
void RenderWater(Shader* shader);
unsigned int GetBlockAtPos(int x, int y, int z);
public:
std::vector<unsigned int> chunkData;
@ -39,13 +25,19 @@ public:
bool generated;
private:
unsigned int vertexArrayObject;
unsigned int vbo, ebo;
unsigned int chunkSize;
unsigned int numTriangles;
glm::vec3 worldPos;
std::thread chunkThread;
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Vertex> mainVertices;
std::vector<unsigned int> mianIndices;
std::vector<WaterVertex> waterVertices;
std::vector<unsigned int> waterIndices;
std::vector<BillboardVertex> billboardVertices;
std::vector<unsigned int> billboardIndices;
unsigned int mainVAO, waterVAO, billboardVAO;
unsigned int mainVBO, mainEBO, waterVBO, waterEBO, billboardVBO, billboardEBO;
unsigned int numTrianglesMain, numTrianglesWater, numTrianglesBillboard;
unsigned int modelLoc;
};

View File

@ -1,11 +1,14 @@
#include "Planet.h"
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
Planet* Planet::planet = nullptr;
// Public
Planet::Planet()
Planet::Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader)
: solidShader(solidShader), waterShader(waterShader), billboardShader(billboardShader)
{
}
@ -31,7 +34,7 @@ std::vector<unsigned int> Planet::GetChunkData(int chunkX, int chunkY, int chunk
}
}
void Planet::Update(float camX, float camY, float camZ, unsigned int modelLoc)
void Planet::Update(float camX, float camY, float camZ)
{
int camChunkX = camX < 0 ? floor(camX / chunkSize) : camX / chunkSize;
int camChunkY = camY < 0 ? floor(camY / chunkSize) : camY / chunkSize;
@ -132,11 +135,13 @@ void Planet::Update(float camX, float camY, float camZ, unsigned int modelLoc)
if (chunks.find(chunkTuple) == chunks.end())
{
chunks.try_emplace(chunkTuple,
chunkSize, next
chunkSize, next, solidShader, waterShader
);
}
}
glDisable(GL_BLEND);
chunksLoading = 0;
numChunks = 0;
numChunksRendered = 0;
@ -154,14 +159,39 @@ void Planet::Update(float camX, float camY, float camZ, unsigned int modelLoc)
abs(chunkY - camChunkY) > renderDistance ||
abs(chunkZ - camChunkZ) > renderDistance))
{
it->second.~Chunk();
it = chunks.erase(it);
}
else
{
numChunksRendered++;
it->second.Render(modelLoc);
it->second.Render(solidShader, billboardShader);
++it;
}
}
glEnable(GL_BLEND);
waterShader->use();
for (auto it = chunks.begin(); it != chunks.end(); )
{
int chunkX = it->second.chunkPos.x;
int chunkY = it->second.chunkPos.y;
int chunkZ = it->second.chunkPos.z;
it->second.RenderWater(waterShader);
++it;
}
}
Chunk* Planet::GetChunk(int chunkX, int chunkY, int chunkZ)
{
std::tuple<int, int, int> chunkTuple{ chunkX, chunkY, chunkZ };
if (chunks.find(chunkTuple) == chunks.end())
{
return nullptr;
}
else
{
return &chunks.at(chunkTuple);
}
}

View File

@ -13,23 +13,29 @@ class Planet
{
// Methods
public:
Planet();
Planet(Shader* solidShader, Shader* waterShader, Shader* billboardShader);
~Planet();
std::vector<unsigned int> GetChunkData(int chunkX, int chunkY, int chunkZ);
void Update(float camX, float camY, float camZ, unsigned int modelLoc);
void Update(float camX, float camY, float camZ);
Chunk* GetChunk(int chunkX, int chunkY, int chunkZ);
// Variables
public:
static Planet* planet;
unsigned int numChunks = 0, numChunksRendered = 0;
static const unsigned int chunkSize = 32;
private:
std::unordered_map<std::tuple<int, int, int>, Chunk> chunks;
std::queue<glm::vec3> chunkQueue;
int renderDistance = 3;
int renderHeight = 1;
unsigned int chunkSize = 32;
unsigned int chunksLoading = 0;
int lastCamX = -100, lastCamY = -100, lastCamZ = -100;
Shader* solidShader;
Shader* waterShader;
Shader* billboardShader;
};

View File

@ -0,0 +1,58 @@
#pragma once
struct Vertex
{
char posX, posY, posZ;
char texGridX, texGridY;
char direction;
Vertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY, char _direction)
{
posX = _posX;
posY = _posY;
posZ = _posZ;
texGridX = _texGridX;
texGridY = _texGridY;
direction = _direction;
}
};
struct WaterVertex
{
char posX, posY, posZ;
char texGridX, texGridY;
char direction;
char top;
WaterVertex(char _posX, char _posY, char _posZ, char _texGridX, char _texGridY, char _direction, char _top)
{
posX = _posX;
posY = _posY;
posZ = _posZ;
texGridX = _texGridX;
texGridY = _texGridY;
direction = _direction;
top = _top;
}
};
struct BillboardVertex
{
float posX, posY, posZ;
char texGridX, texGridY;
BillboardVertex(float _posX, float _posY, float _posZ, char _texGridX, char _texGridY)
{
posX = _posX;
posY = _posY;
posZ = _posZ;
texGridX = _texGridX;
texGridY = _texGridY;
}
};

View File

@ -15,7 +15,7 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
// Init noise settings
static NoiseSettings surfaceSettings[]{
{ 0.01f, 20.0f, 0 },
{ 0.1f, 3.0f, 0 }
{ 0.05f, 3.0f, 0 }
};
static int surfaceSettingsLength = sizeof(surfaceSettings) / sizeof(*surfaceSettings);
@ -30,70 +30,151 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
static int oreSettingsLength = sizeof(oreSettings) / sizeof(*oreSettings);
static SurfaceFeature surfaceFeatures[]{
// Pond
{
{ 0.43f, 1.0f, 2.35f, .85f, 1, 0 }, // Noise
{ // Blocks
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 13, 13, 0, 0,
0, 0, 13, 13, 13, 0, 0,
0, 0, 0, 13, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 2, 13, 13, 2, 0, 0,
0, 2, 13, 13, 13, 2, 0,
2, 13, 13, 13, 13, 13, 2,
2, 13, 13, 13, 13, 13, 2,
2, 13, 13, 13, 13, 13, 2,
0, 2, 13, 13, 13, 2, 0,
0, 0, 2, 13, 2, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
{ // Replace?
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, true, true, false, false,
false, false, true, true, true, false, false,
false, false, false, true, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, true, true, false, false, false,
false, false, true, true, true, false, false,
false, true, true, true, true, true, false,
false, true, true, true, true, true, false,
false, true, true, true, true, true, false,
false, false, true, true, true, false, false,
false, false, false, true, false, false, false,
false, false, true, true, false, false, false,
false, false, true, true, true, true, false,
false, true, true, true, true, true, false,
false, true, true, true, true, true, false,
false, true, true, true, true, true, false,
false, false, true, true, true, false, false,
false, false, false, true, false, false, false,
},
7, 3, 7, // Size
-3, -2, -3 // Offset
},
// Tree
{
{ 4.23f, 1.0f, 8.54f, .8f, 1, 0 },
{
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 5, 0,
0, 0, 0, 5, 5, 5, 5,
0, 0, 0, 5, 5, 5, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 4, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 5, 5,
1, 4, 4, 4, 4, 5, 5,
0, 0, 0, 5, 5, 5, 5,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 4, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 5, 0,
0, 0, 0, 5, 5, 5, 5,
0, 0, 0, 5, 5, 5, 0,
0, 0, 0, 5, 5, 0, 0,
0, 5, 5, 5, 0,
5, 5, 5, 5, 5,
5, 5, 4, 5, 5,
5, 5, 5, 5, 5,
0, 5, 5, 5, 0,
0, 5, 5, 5, 0,
5, 5, 5, 5, 5,
5, 5, 4, 5, 5,
5, 5, 5, 5, 5,
0, 5, 5, 5, 0,
0, 0, 0, 0, 0,
0, 0, 5, 0, 0,
0, 5, 5, 5, 0,
0, 0, 5, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 5, 0, 0,
0, 5, 5, 5, 0,
0, 0, 5, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 5, 5, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
{
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
true, true, true, true, true, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, true, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
},
5,
7,
@ -102,22 +183,6 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
0,
-2
},
// Grass
{
{ 2.65f, 1.0f, 8.54f, .5f, 1, 0 },
{
2, 6
},
{
false, false
},
1,
2,
1,
0,
0,
0
},
// Tall Grass
{
{ 1.23f, 1.0f, 4.34f, .6f, 1, 0 },
@ -134,6 +199,22 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
0,
0
},
// Grass
{
{ 2.65f, 1.0f, 8.54f, .5f, 1, 0 },
{
2, 6
},
{
false, false
},
1,
2,
1,
0,
0,
0
},
// Poppy
{
{ 5.32f, 1.0f, 3.67f, .8f, 1, 0 },
@ -201,6 +282,8 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
};
static int surfaceFeaturesLength = sizeof(surfaceFeatures) / sizeof(*surfaceFeatures);
static int waterLevel = 20;
// Set vector size
chunkData->reserve(chunkSize * chunkSize * chunkSize);
@ -249,9 +332,14 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
// Sky and Caves
if (y + startY > noiseY)
chunkData->push_back(0);
{
if (y + startY <= waterLevel)
chunkData->push_back(Blocks::WATER);
else
chunkData->push_back(Blocks::AIR);
}
else if (cave)
chunkData->push_back(0);
chunkData->push_back(Blocks::AIR);
// Ground
else
{
@ -308,6 +396,10 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (noiseY + surfaceFeatures[i].offsetY > startY + 32 || noiseY + surfaceFeatures[i].sizeY + surfaceFeatures[i].offsetY < startY)
continue;
// Check if it's in water
if (noiseY < waterLevel)
continue;
// Check if it's in a cave
bool cave = false;
for (int i = 0; i < caveSettingsLength; i++)
@ -361,9 +453,9 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
if (localZ >= 32 || localZ < 0)
continue;
int featureIndex = fX * surfaceFeatures[i].sizeZ * surfaceFeatures[i].sizeY +
fZ * surfaceFeatures[i].sizeY +
fY;
int featureIndex = fY * surfaceFeatures[i].sizeX * surfaceFeatures[i].sizeZ +
fX * surfaceFeatures[i].sizeZ +
fZ;
//std::cout << "Feature Index: " << featureIndex << '\n';
int localIndex = localX * chunkSize * chunkSize + localZ * chunkSize + localY;
//std::cout << "Local Index: " << localIndex << ", Max Index: " << chunkData->size() << '\n';
@ -373,11 +465,6 @@ void WorldGen::GenerateChunkData(int chunkX, int chunkY, int chunkZ, int chunkSi
}
}
}
//int index = x * chunkSize * chunkSize + z * chunkSize + noiseY;
//chunkData->at(index) = surfaceFeatures[i].block;
//index = x * chunkSize * chunkSize + z * chunkSize + noiseY + 1;
//chunkData->at(index) = surfaceFeatures[i].block;
}
}
}