[Chunk] Now using new renderer, but vertex attributes offset handling needs to be implemented in RenderTarget or VertexBuffer somehow.

This commit is contained in:
Quentin Bazin 2018-06-14 23:07:20 +02:00
parent 6d965a4312
commit 65df0259da
8 changed files with 98 additions and 221 deletions

View File

@ -23,6 +23,7 @@ class RenderTarget {
public:
void draw(const IDrawable &drawable, const RenderStates &states = RenderStates::Default);
void draw(const VertexBuffer &vertexBuffer, const RenderStates &states = RenderStates::Default);
void draw(const VertexBuffer &vertexBuffer, std::size_t firstVertex, std::size_t vertexCount, const RenderStates &states = RenderStates::Default);
};
#endif // RENDERTARGET_HPP_

View File

@ -31,20 +31,11 @@ class Chunk : public NonCopyable, public IDrawable {
void update();
void draw(const Shader &shader);
Block *getBlock(s8 x, s8 y, s8 z);
Block *getBlock(s8 x, s8 y, s8 z) const;
void setBlock(s8 x, s8 y, s8 z, u32 id);
void addBlock(const glm::vec3 &pos, u32 id);
u32 getCoordID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate);
u32 getVertexID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate);
u32 getTexCoordID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate);
bool vertexExists(u8 x, u8 y, u8 z, u8 i, u8 j);
s32 x() const { return m_x; }
s32 y() const { return m_y; }
s32 z() const { return m_z; }
@ -84,12 +75,8 @@ class Chunk : public NonCopyable, public IDrawable {
std::vector<std::unique_ptr<Block>> m_data;
std::vector<float> m_vertices;
std::vector<float> m_normals;
std::vector<float> m_texCoords;
std::map<u32, u32> m_verticesID;
std::map<u32, u32> m_extendedFaces;
std::size_t m_verticesCount;
std::size_t m_normalsCount;
VertexBuffer m_vbo{GL_QUADS, 0, 0};

View File

@ -26,6 +26,8 @@ class World : public IDrawable {
public:
World();
void updateChunks();
Chunk *getChunk(int cx, int cz) const;
Block *getBlock(int x, int y, int z);

View File

@ -14,6 +14,7 @@
#include "IDrawable.hpp"
#include "RenderTarget.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
#include "VertexBuffer.hpp"
void RenderTarget::draw(const IDrawable &drawable, const RenderStates &states) {
@ -21,6 +22,10 @@ void RenderTarget::draw(const IDrawable &drawable, const RenderStates &states) {
}
void RenderTarget::draw(const VertexBuffer &vertexBuffer, const RenderStates &states) {
draw(vertexBuffer, vertexBuffer.first(), vertexBuffer.count(), states);
}
void RenderTarget::draw(const VertexBuffer &vertexBuffer, std::size_t firstVertex, std::size_t vertexCount, const RenderStates &states) {
if (!states.shader) return;
Shader::bind(states.shader);
@ -35,7 +40,12 @@ void RenderTarget::draw(const VertexBuffer &vertexBuffer, const RenderStates &st
glVertexAttribPointer(states.shader->attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(vertexBuffer.mode(), vertexBuffer.first(), vertexBuffer.count());
if (states.texture)
Texture::bind(states.texture);
glDrawArrays(vertexBuffer.mode(), firstVertex, vertexCount);
Texture::bind(nullptr);
states.shader->disableVertexAttribArray("coord3d");

View File

@ -118,6 +118,8 @@ void GameState::onEvent(const SDL_Event &event) {
}
void GameState::update() {
m_world.updateChunks();
m_viewMatrix = m_camera.processInputs();
m_selectedBlock = findSelectedBlock(false);

View File

@ -29,6 +29,8 @@ Chunk::Chunk(s32 x, s32 y, s32 z, Texture &texture) : m_texture(texture) {
}
void Chunk::update() {
if (!m_isChanged || m_data.empty()) return;
m_isChanged = false;
static const float cubeCoords[6 * 4 * 3] = {
@ -63,16 +65,13 @@ void Chunk::update() {
0, 0, 0,
};
m_vertices.clear();
m_normals.clear();
m_texCoords.clear();
std::vector<float> vertices;
std::vector<float> normals;
std::vector<float> texCoords;
m_vertices.reserve(width * height * depth * 6 * 4 * 3);
m_normals.reserve(width * height * depth * 6 * 4 * 3);
m_texCoords.reserve(width * height * depth * 6 * 4 * 2);
m_verticesID.clear();
m_extendedFaces.clear();
vertices.reserve(width * height * depth * 6 * 4 * 3);
normals.reserve(width * height * depth * 6 * 4 * 3);
texCoords.reserve(width * height * depth * 6 * 4 * 2);
// Needed in the loop (avoid a lot of glm::vec3 creation)
glm::vec3 a, b, c, v1, v2, normal;
@ -88,7 +87,7 @@ void Chunk::update() {
const glm::vec4 &blockTexCoords = block->getTexCoords();
float texCoords[2 * 4 * 6] = {
float cubeTexCoords[2 * 4 * 6] = {
blockTexCoords.x, blockTexCoords.w,
blockTexCoords.z, blockTexCoords.w,
blockTexCoords.z, blockTexCoords.y,
@ -100,61 +99,32 @@ void Chunk::update() {
};
for(int i = 1 ; i < 6 ; i++) {
memcpy(&texCoords[2 * 4 * i], &texCoords[0], 2 * 4 * sizeof(float));
memcpy(&cubeTexCoords[2 * 4 * i], &cubeTexCoords[0], 2 * 4 * sizeof(float));
}
for(u8 i = 0 ; i < 6 ; i++) {
// Skip hidden faces
Block *surroundingBlocks[4] = {nullptr, nullptr, nullptr, nullptr};
if (m_surroundingChunks[0]) surroundingBlocks[0] = m_surroundingChunks[0]->getBlock(width - 1, y, z);
if (m_surroundingChunks[1]) surroundingBlocks[1] = m_surroundingChunks[1]->getBlock(0, y, z);
if (m_surroundingChunks[2]) surroundingBlocks[2] = m_surroundingChunks[2]->getBlock(x, y, depth - 1);
if (m_surroundingChunks[3]) surroundingBlocks[3] = m_surroundingChunks[3]->getBlock(x, y, 0);
if((x > 0 && getBlock(x - 1, y, z)->id() && i == 0)
|| (x < width - 1 && getBlock(x + 1, y, z)->id() && i == 1)
|| (y > 0 && getBlock(x, y - 1, z)->id() && i == 2)
|| (y < height - 1 && getBlock(x, y + 1, z)->id() && i == 3)
|| (z > 0 && getBlock(x, y, z - 1)->id() && i == 5)
|| (z < depth - 1 && getBlock(x, y, z + 1)->id() && i == 4)
|| (x == 0 && m_surroundingChunks[0] && m_surroundingChunks[0]->getBlock(width - 1, y, z)->id() && i == 0)
|| (x == width - 1 && m_surroundingChunks[1] && m_surroundingChunks[1]->getBlock(0, y, z)->id() && i == 1)
|| (z == 0 && m_surroundingChunks[2] && m_surroundingChunks[2]->getBlock(x, y, depth - 1)->id() && i == 5)
|| (z == depth - 1 && m_surroundingChunks[3] && m_surroundingChunks[3]->getBlock(x, y, 0)->id() && i == 4)
|| (x == 0 && surroundingBlocks[0] && surroundingBlocks[0]->id() && i == 0)
|| (x == width - 1 && surroundingBlocks[1] && surroundingBlocks[1]->id() && i == 1)
|| (z == 0 && surroundingBlocks[2] && surroundingBlocks[2]->id() && i == 5)
|| (z == depth - 1 && surroundingBlocks[3] && surroundingBlocks[3]->id() && i == 4)
) {
continue;
}
// Merge adjacent faces
// if(x > 0 && getBlock(x - 1, y, z)->id() && (i != 0 || i != 1) && vertexExists(x - 1, y, z, i, 0)) {
// m_vertices[getVertexID(x - 1, y, z, i, 1, 0)] += 1;
// m_vertices[getVertexID(x - 1, y, z, i, 2, 0)] += 1;
//
// m_texCoords[getTexCoordID(x - 1, y, z, i, 1, 0)] += 16 / 256 * 2;//1;
// m_texCoords[getTexCoordID(x - 1, y, z, i, 2, 0)] += 16 / 256 * 2;//1;
//
// m_extendedFaces[getCoordID(x, y, z, i, 0, 0)] = getCoordID(x - 1, y, z, i, 0, 0);
//
// continue;
// }
// if(z > 0 && getBlock(x, y, z - 1)->id() && (i == 0 || i == 1) && vertexExists(x, y, z - 1, i, 0)) {
// m_vertices[getVertexID(x, y, z - 1, i, 0, 2)] += 1;
// m_vertices[getVertexID(x, y, z - 1, i, 3, 2)] += 1;
//
// m_texCoords[getTexCoordID(x, y, z - 1, i, 1, 0)] += 16 / 256 * 2;//1;
// m_texCoords[getTexCoordID(x, y, z - 1, i, 2, 0)] += 16 / 256 * 2;//1;
//
// m_extendedFaces[getCoordID(x, y, z, i, 0, 0)] = getCoordID(x, y, z - 1, i, 0, 0);
//
// continue;
// }
/*if(y > 0 && getBlock(x, y - 1, z)->id() && (i == 2 || i == 3) && vertexExists(x, y - 1, z, i, 0)) {
m_vertices[getVertexID(x, y - 1, z, i, 0, 1)] += 1;
m_vertices[getVertexID(x, y - 1, z, i, 3, 1)] += 1;
m_texCoords[getTexCoordID(x, y - 1, z, i, 1, 1)] += 1;
m_texCoords[getTexCoordID(x, y - 1, z, i, 2, 1)] += 1;
m_extendedFaces[getCoordID(x, y, z, i, 0, 0)] = getCoordID(x, y - 1, z, i, 0, 0);
continue;
}*/
// Three points of the face
a.x = cubeCoords[i * 12 + 0];
a.y = cubeCoords[i * 12 + 1];
@ -177,132 +147,44 @@ void Chunk::update() {
// Store vertex information
for(u8 j = 0 ; j < 4 ; j++) {
m_vertices.push_back(x + cubeCoords[i * 12 + j * 3]);
m_vertices.push_back(y + cubeCoords[i * 12 + j * 3 + 1]);
m_vertices.push_back(z + cubeCoords[i * 12 + j * 3 + 2]);
vertices.push_back(x + cubeCoords[i * 12 + j * 3]);
vertices.push_back(y + cubeCoords[i * 12 + j * 3 + 1]);
vertices.push_back(z + cubeCoords[i * 12 + j * 3 + 2]);
m_normals.push_back(normal.x);
m_normals.push_back(normal.y);
m_normals.push_back(normal.z);
normals.push_back(normal.x);
normals.push_back(normal.y);
normals.push_back(normal.z);
m_texCoords.push_back(texCoords[i * 8 + j * 2]);
m_texCoords.push_back(texCoords[i * 8 + j * 2 + 1]);
m_verticesID[getCoordID(x, y, z, i, j, 0)] = m_vertices.size() - 3;
m_verticesID[getCoordID(x, y, z, i, j, 1)] = m_vertices.size() - 2;
m_verticesID[getCoordID(x, y, z, i, j, 2)] = m_vertices.size() - 1;
texCoords.push_back(cubeTexCoords[i * 8 + j * 2]);
texCoords.push_back(cubeTexCoords[i * 8 + j * 2 + 1]);
}
}
}
}
}
m_vertices.shrink_to_fit();
m_normals.shrink_to_fit();
m_texCoords.shrink_to_fit();
vertices.shrink_to_fit();
normals.shrink_to_fit();
texCoords.shrink_to_fit();
VertexBuffer::bind(&m_vbo);
m_vbo.setData((m_vertices.size() + m_normals.size() + m_texCoords.size()) * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
m_vbo.updateData(0, m_vertices.size() * sizeof(float), m_vertices.data());
m_vbo.updateData(m_vertices.size() * sizeof(float), m_normals.size() * sizeof(float), m_normals.data());
m_vbo.updateData((m_vertices.size() + m_normals.size()) * sizeof(float), m_texCoords.size() * sizeof(float), m_texCoords.data());
m_vbo.setData((vertices.size() + normals.size() + texCoords.size()) * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
m_vbo.updateData(0, vertices.size() * sizeof(float), vertices.data());
m_vbo.updateData(vertices.size() * sizeof(float), normals.size() * sizeof(float), normals.data());
m_vbo.updateData((vertices.size() + normals.size()) * sizeof(float), texCoords.size() * sizeof(float), texCoords.data());
VertexBuffer::bind(nullptr);
}
class Ray {
public:
Ray(const glm::vec3 &orig, const glm::vec3 &dir) : orig(orig), dir(dir)
{
invdir.x = 1 / dir.x;
invdir.y = 1 / dir.y;
invdir.z = 1 / dir.z;
sign[0] = (invdir.x < 0);
sign[1] = (invdir.y < 0);
sign[2] = (invdir.z < 0);
}
glm::vec3 orig, dir; // ray orig and dir
glm::vec3 invdir;
int sign[3];
};
class AxisAlignedBB {
public:
AxisAlignedBB(const glm::vec3 &vmin, const glm::vec3 &vmax)
{
bounds[0] = vmin;
bounds[1] = vmax;
}
glm::vec3 bounds[2];
bool intersect(const Ray &r) const
{
float tmin, tmax, tymin, tymax, tzmin, tzmax;
tmin = (bounds[r.sign[0]].x - r.orig.x) * r.invdir.x;
tmax = (bounds[1-r.sign[0]].x - r.orig.x) * r.invdir.x;
tymin = (bounds[r.sign[1]].y - r.orig.y) * r.invdir.y;
tymax = (bounds[1-r.sign[1]].y - r.orig.y) * r.invdir.y;
if ((tmin > tymax) || (tymin > tmax))
return false;
if (tymin > tmin)
tmin = tymin;
if (tymax < tmax)
tmax = tymax;
tzmin = (bounds[r.sign[2]].z - r.orig.z) * r.invdir.z;
tzmax = (bounds[1-r.sign[2]].z - r.orig.z) * r.invdir.z;
if ((tmin > tzmax) || (tzmin > tmax))
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
return true;
}
};
void Chunk::draw(const Shader &shader) {
if(m_isChanged) update();
if(m_vertices.size() == 0) return;
VertexBuffer::bind(&m_vbo);
shader.enableVertexAttribArray("coord3d");
shader.enableVertexAttribArray("normal");
shader.enableVertexAttribArray("texCoord");
glVertexAttribPointer(shader.attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(shader.attrib("normal"), 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(m_vertices.size() * sizeof(float)));
glVertexAttribPointer(shader.attrib("texCoord"), 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)((m_vertices.size() + m_normals.size()) * sizeof(float)));
Texture::bind(&m_texture);
glDrawArrays(GL_QUADS, 0, m_vertices.size() / 3);
Texture::bind(nullptr);
// for(u32 i = 0 ; i < m_vertices.size() / 3 ; i += 4) {
// glDrawArrays(GL_LINE_LOOP, i, 4);
// }
shader.disableVertexAttribArray("texCoord");
shader.disableVertexAttribArray("normal");
shader.disableVertexAttribArray("coord3d");
VertexBuffer::bind(nullptr);
m_verticesCount = vertices.size();
m_normalsCount = normals.size();
}
void Chunk::addBlock(const glm::vec3 &pos, u32 id) {
m_data.push_back(std::unique_ptr<Block>(new Block(pos, id)));
}
Block *Chunk::getBlock(s8 x, s8 y, s8 z) {
Block *Chunk::getBlock(s8 x, s8 y, s8 z) const {
u16 i = y + x * height + z * height * width;
if(i < m_data.size()) {
return m_data[i].get();
@ -327,56 +209,37 @@ void Chunk::setBlock(s8 x, s8 y, s8 z, u32 id) {
if(z == depth - 1 && back()) { back()->m_isChanged = true; }
}
u32 Chunk::getCoordID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate) {
return (j + i * 4 + x * 4 * 6 + y * 4 * 6 * Chunk::width + z * 4 * 6 * Chunk::width * Chunk::height) * 3 + coordinate;
}
u32 Chunk::getVertexID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate) {
u32 id = getCoordID(x, y, z, i, j, coordinate);
while(m_extendedFaces.count(id - j * 3 - coordinate)) {
id = m_extendedFaces[id - j * 3 - coordinate] + j * 3 + coordinate;
}
return m_verticesID[id];
}
u32 Chunk::getTexCoordID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate) {
return float(getVertexID(x, y, z, i, j, coordinate)) / 3 * 2;
}
bool Chunk::vertexExists(u8 x, u8 y, u8 z, u8 i, u8 j) {
return (m_verticesID.count(getCoordID(x, y, z, i, j, 0))
|| m_extendedFaces.count(getCoordID(x, y, z, i, j, 0)));
}
// FIXME: Remove old func when this one works
// FIXME: Implement vertex attributes in VertexBuffer and remove most of the code here
void Chunk::draw(RenderTarget &target, RenderStates states) const {
// if(m_isChanged) update();
//
// if(m_vertices.size() == 0) return;
//
if(m_verticesCount == 0) return;
VertexBuffer::bind(&m_vbo);
states.shader->enableVertexAttribArray("coord3d");
states.shader->enableVertexAttribArray("normal");
states.shader->enableVertexAttribArray("texCoord");
glVertexAttribPointer(states.shader->attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(states.shader->attrib("normal"), 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(m_verticesCount * sizeof(float)));
glVertexAttribPointer(states.shader->attrib("texCoord"), 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)((m_verticesCount + m_normalsCount) * sizeof(float)));
states.texture = &m_texture;
target.draw(m_vbo, 0, m_verticesCount / 3, states);
states.shader->disableVertexAttribArray("texCoord");
states.shader->disableVertexAttribArray("normal");
// Shader::bind(states.shader);
// VertexBuffer::bind(&m_vbo);
//
// shader->enableVertexAttribArray("coord3d");
// shader->enableVertexAttribArray("normal");
// shader->enableVertexAttribArray("texCoord");
// states.shader->enableVertexAttribArray("coord3d");
//
// glVertexAttribPointer(shader>attrib("normal"), 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(m_vertices.size() * sizeof(float)));
// glVertexAttribPointer(shader>attrib("texCoord"), 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)((m_vertices.size() + m_normals.size()) * sizeof(float)));
// for(u32 i = 0 ; i < m_verticesCount / 3 ; i += 4) {
// glDrawArrays(GL_LINE_LOOP, i, 4);
// }
//
// Texture::bind(&m_texture);
//
// glDrawArrays(GL_QUADS, 0, m_vertices.size() / 3);
//
// Texture::bind(nullptr);
//
// // for(u32 i = 0 ; i < m_vertices.size() / 3 ; i += 4) {
// // glDrawArrays(GL_LINE_LOOP, i, 4);
// // }
//
// shader.disableVertexAttribArray("normal");
// shader.disableVertexAttribArray("coord3d");
// states.shader->disableVertexAttribArray("coord3d");
//
// VertexBuffer::bind(nullptr);
}

View File

@ -41,6 +41,13 @@ World::World() {
}
}
void World::updateChunks() {
// FIXME
for (auto &it : m_chunks) {
it->update();
}
}
void World::draw(RenderTarget &target, RenderStates states) const {
float ud = 1000.0;
int ux = 0;
@ -100,8 +107,8 @@ void World::draw(RenderTarget &target, RenderStates states) const {
}
Shader::bind(states.shader);
states.shader->setUniform("u_modelMatrix", modelMatrix);
it->draw(*states.shader);
// states.shader->setUniform("u_modelMatrix", modelMatrix);
target.draw(*it, states);
Shader::bind(nullptr);
}

View File

@ -36,6 +36,11 @@ void TerrainGenerator::generate(Chunk &chunk) const {
chunk.setGenerated(true);
chunk.setChanged(true);
if (chunk.getSurroundingChunk(0) && chunk.getSurroundingChunk(0)->isGenerated()) chunk.getSurroundingChunk(0)->setChanged(true);
if (chunk.getSurroundingChunk(1) && chunk.getSurroundingChunk(1)->isGenerated()) chunk.getSurroundingChunk(1)->setChanged(true);
if (chunk.getSurroundingChunk(2) && chunk.getSurroundingChunk(2)->isGenerated()) chunk.getSurroundingChunk(2)->setChanged(true);
if (chunk.getSurroundingChunk(3) && chunk.getSurroundingChunk(3)->isGenerated()) chunk.getSurroundingChunk(3)->setChanged(true);
}
float TerrainGenerator::noise2d(float x, float y, int octaves, float persistence) {