textures
- do I need to say anything? :)
+ okay, now I need a better solution for the crosshair ^^
font rendering
-Subproject commit 96db33a3047bf3f20f5b6d4464cf4a4ee238146d
+Subproject commit 449410ec8e8e4b4bd7878b99aef9dc77ed422ff1
e.Position(chunk, pos);
e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
e.WorldCollidable(true);
- e.SetShape(world.BlockTypes()[1].shape, color);
+ e.SetShape(world.BlockTypes()[1].shape, color, 2);
e.AngularVelocity(rot);
Controller *ctrl;
if (rand() % 2) {
namespace blank {
+class ArrayTexture;
class Font;
class Sound;
+class Texture;
class Assets {
Font LoadFont(const std::string &name, int size) const;
Sound LoadSound(const std::string &name) const;
+ Texture LoadTexture(const std::string &name) const;
+ void LoadTexture(const std::string &name, ArrayTexture &, int layer) const;
private:
std::string fonts;
std::string sounds;
+ std::string textures;
};
const World::Config &wc
)
: env(env)
-, world(wc)
+, world(env.assets, wc)
, spawner(world)
, interface(ic, env, world) {
#include "init.hpp"
#include "../audio/Sound.hpp"
+#include "../graphics/ArrayTexture.hpp"
#include "../graphics/Font.hpp"
+#include "../graphics/Texture.hpp"
#include "../world/BlockType.hpp"
#include "../world/Entity.hpp"
#include <iostream>
#include <stdexcept>
+#include <SDL_image.h>
using std::string;
Assets::Assets(const string &base)
: fonts(base + "fonts/")
-, sounds(base + "sounds/") {
+, sounds(base + "sounds/")
+, textures(base + "textures/") {
}
return Sound(full.c_str());
}
+Texture Assets::LoadTexture(const string &name) const {
+ string full = textures + name + ".png";
+ Texture tex;
+ SDL_Surface *srf = IMG_Load(full.c_str());
+ if (!srf) {
+ throw SDLError("IMG_Load");
+ }
+ tex.Bind();
+ tex.Data(*srf);
+ SDL_FreeSurface(srf);
+ return tex;
+}
+
+void Assets::LoadTexture(const string &name, ArrayTexture &tex, int layer) const {
+ string full = textures + name + ".png";
+ SDL_Surface *srf = IMG_Load(full.c_str());
+ if (!srf) {
+ throw SDLError("IMG_Load");
+ }
+ tex.Bind();
+ try {
+ tex.Data(layer, *srf);
+ } catch (...) {
+ SDL_FreeSurface(srf);
+ throw;
+ }
+ SDL_FreeSurface(srf);
+}
+
void FrameCounter::EnterFrame() noexcept {
last_enter = SDL_GetTicks();
--- /dev/null
+#ifndef BLANK_GRAPHICS_ARRAYTEXTURE_HPP_
+#define BLANK_GRAPHICS_ARRAYTEXTURE_HPP_
+
+#include "Format.hpp"
+
+#include <GL/glew.h>
+
+struct SDL_Surface;
+
+
+namespace blank {
+
+class ArrayTexture {
+
+public:
+ ArrayTexture();
+ ~ArrayTexture();
+
+ ArrayTexture(ArrayTexture &&) noexcept;
+ ArrayTexture &operator =(ArrayTexture &&) noexcept;
+
+ ArrayTexture(const ArrayTexture &) = delete;
+ ArrayTexture &operator =(const ArrayTexture &) = delete;
+
+public:
+ GLsizei Width() const noexcept { return width; }
+ GLsizei Height() const noexcept { return height; }
+ GLsizei Depth() const noexcept { return depth; }
+
+ void Bind() noexcept;
+
+ void Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &) noexcept;
+ void Data(GLsizei l, const SDL_Surface &);
+ void Data(GLsizei l, const Format &, GLvoid *data) noexcept;
+
+ void FilterNearest() noexcept;
+ void FilterLinear() noexcept;
+ void FilterTrilinear() noexcept;
+
+private:
+ GLuint handle;
+
+ GLsizei width, height, depth;
+
+ Format format;
+
+};
+
+}
+
+#endif
namespace blank {
+class ArrayTexture;
+
class BlockLighting {
public:
void Activate() noexcept;
+ void SetTexture(ArrayTexture &) noexcept;
void SetFogDensity(float) noexcept;
void SetM(const glm::mat4 &m) noexcept;
GLuint mv_handle;
GLuint mvp_handle;
+ GLuint sampler_handle;
GLuint light_direction_handle;
GLuint light_color_handle;
GLuint fog_density_handle;
namespace blank {
+class ArrayTexture;
+
class DirectionalLighting {
public:
void SetLightDirection(const glm::vec3 &) noexcept;
void SetLightColor(const glm::vec3 &) noexcept;
+ void SetTexture(ArrayTexture &) noexcept;
void SetFogDensity(float) noexcept;
void SetM(const glm::mat4 &m) noexcept;
GLuint m_handle;
GLuint mv_handle;
GLuint mvp_handle;
+ GLuint sampler_handle;
GLuint light_direction_handle;
GLuint light_color_handle;
GLuint fog_density_handle;
GLenum type;
GLenum internal;
- void ReadPixelFormat(const SDL_PixelFormat &);
+ SDL_PixelFormat sdl_format;
+
+ Format();
+ explicit Format(const SDL_PixelFormat &);
+
+ bool Compatible(const Format &other) const noexcept;
};
#ifndef BLANK_GRAPHICS_TEXTURE_HPP_
#define BLANK_GRAPHICS_TEXTURE_HPP_
-#include "Format.hpp"
-
#include <GL/glew.h>
struct SDL_Surface;
namespace blank {
+struct Format;
+
class Texture {
public:
-#include "BlendedSprite.hpp"
+#include "ArrayTexture.hpp"
#include "Font.hpp"
#include "Format.hpp"
#include "Texture.hpp"
#include "Viewport.hpp"
+#include "../app/init.hpp"
+
#include <algorithm>
#include <cstring>
#include <memory>
SDL_FreeSurface(srf);
}
-
-void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) {
+Format::Format()
+: format(GL_BGRA)
+, type(GL_UNSIGNED_INT_8_8_8_8_REV)
+, internal(GL_RGBA8) {
+ sdl_format.format = SDL_PIXELFORMAT_ARGB8888;
+ sdl_format.palette = nullptr;
+ sdl_format.BitsPerPixel = 32;
+ sdl_format.BytesPerPixel = 4;
+ sdl_format.Rmask = 0x00FF0000;
+ sdl_format.Gmask = 0x0000FF00;
+ sdl_format.Bmask = 0x000000FF;
+ sdl_format.Amask = 0xFF000000;
+ sdl_format.Rloss = 0;
+ sdl_format.Gloss = 0;
+ sdl_format.Bloss = 0;
+ sdl_format.Aloss = 0;
+ sdl_format.Rshift = 16;
+ sdl_format.Gshift = 8;
+ sdl_format.Bshift = 0;
+ sdl_format.Ashift = 24;
+ sdl_format.refcount = 1;
+ sdl_format.next = nullptr;
+}
+
+Format::Format(const SDL_PixelFormat &fmt)
+: sdl_format(fmt) {
if (fmt.BytesPerPixel == 4) {
if (fmt.Amask == 0xFF) {
if (fmt.Rmask == 0xFF00) {
}
}
+bool Format::Compatible(const Format &other) const noexcept {
+ return format == other.format && type == other.type && internal == other.internal;
+}
+
Texture::Texture()
: handle(0)
}
void Texture::Data(const SDL_Surface &srf, bool pad2) noexcept {
- Format format;
- format.ReadPixelFormat(*srf.format);
+ Format format(*srf.format);
if (!pad2 || (ispow2(srf.w) && ispow2(srf.h))) {
int align = UnpackAlignmentFromPitch(srf.pitch);
glPixelStorei(GL_UNPACK_ROW_LENGTH, i);
}
+
+ArrayTexture::ArrayTexture()
+: handle(0)
+, width(0)
+, height(0)
+, depth(0) {
+ glGenTextures(1, &handle);
+}
+
+ArrayTexture::~ArrayTexture() {
+ if (handle != 0) {
+ glDeleteTextures(1, &handle);
+ }
+}
+
+ArrayTexture::ArrayTexture(ArrayTexture &&other) noexcept
+: handle(other.handle) {
+ other.handle = 0;
+ width = other.width;
+ height = other.height;
+ depth = other.depth;
+}
+
+ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept {
+ std::swap(handle, other.handle);
+ width = other.width;
+ height = other.height;
+ depth = other.depth;
+ return *this;
+}
+
+
+void ArrayTexture::Bind() noexcept {
+ glBindTexture(GL_TEXTURE_2D_ARRAY, handle);
+}
+
+
+void ArrayTexture::Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &f) noexcept {
+ glTexStorage3D(
+ GL_TEXTURE_2D_ARRAY, // which
+ 1, // mipmap count
+ f.internal, // format
+ w, h, // dimensions
+ d // layer count
+ );
+ width = w;
+ height = h;
+ depth = d;
+ format = f;
+}
+
+void ArrayTexture::Data(GLsizei l, const SDL_Surface &srf) {
+ Format fmt(*srf.format);
+ if (format.Compatible(fmt)) {
+ Data(l, fmt, srf.pixels);
+ } else {
+ SDL_Surface *converted = SDL_ConvertSurface(
+ const_cast<SDL_Surface *>(&srf),
+ &format.sdl_format,
+ 0
+ );
+ if (!converted) {
+ throw SDLError("SDL_ConvertSurface");
+ }
+ Format new_fmt(*converted->format);
+ if (!format.Compatible(new_fmt)) {
+ SDL_FreeSurface(converted);
+ throw std::runtime_error("unable to convert texture input");
+ }
+ Data(l, new_fmt, converted->pixels);
+ SDL_FreeSurface(converted);
+ }
+}
+
+void ArrayTexture::Data(GLsizei l, const Format &f, GLvoid *data) noexcept {
+ glTexSubImage3D(
+ GL_TEXTURE_2D_ARRAY, // which
+ 0, // mipmap lavel
+ 0, 0, // dest X and Y offset
+ l, // layer offset
+ width, height,
+ 1, // layer count
+ f.format, f.type,
+ data
+ );
+}
+
+
+void ArrayTexture::FilterNearest() noexcept {
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+}
+
+void ArrayTexture::FilterLinear() noexcept {
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+void ArrayTexture::FilterTrilinear() noexcept {
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+}
+
}
#include "Program.hpp"
#include "Shader.hpp"
+#include "ArrayTexture.hpp"
#include "Texture.hpp"
#include "../app/init.hpp"
GL_VERTEX_SHADER,
"#version 330 core\n"
"layout(location = 0) in vec3 vtx_position;\n"
- "layout(location = 1) in vec3 vtx_color;\n"
- "layout(location = 2) in vec3 vtx_normal;\n"
+ "layout(location = 1) in vec3 vtx_tex_uv;\n"
+ "layout(location = 2) in vec3 vtx_color;\n"
+ "layout(location = 3) in vec3 vtx_normal;\n"
"uniform mat4 M;\n"
"uniform mat4 MV;\n"
"uniform mat4 MVP;\n"
+ "out vec3 frag_tex_uv;\n"
"out vec3 frag_color;\n"
"out vec3 vtx_viewspace;\n"
"out vec3 normal;\n"
"gl_Position = MVP * vec4(vtx_position, 1);\n"
"vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
"normal = (M * vec4(vtx_normal, 0)).xyz;\n"
+ "frag_tex_uv = vtx_tex_uv;\n"
"frag_color = vtx_color;\n"
"}\n"
);
program.LoadShader(
GL_FRAGMENT_SHADER,
"#version 330 core\n"
+ "in vec3 frag_tex_uv;\n"
"in vec3 frag_color;\n"
"in vec3 vtx_viewspace;\n"
"in vec3 normal;\n"
+ "uniform sampler2DArray tex_sampler;\n"
"uniform vec3 light_direction;\n"
"uniform vec3 light_color;\n"
"uniform float fog_density;\n"
"out vec3 color;\n"
"void main() {\n"
- "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n"
+ "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
+ "vec3 base_color = tex_color * frag_color;\n"
+ "vec3 ambient = vec3(0.1, 0.1, 0.1) * base_color;\n"
// this should be the same as the clear color, otherwise looks really weird
"vec3 fog_color = vec3(0, 0, 0);\n"
"float e = 2.718281828;\n"
"vec3 n = normalize(normal);\n"
"vec3 l = normalize(light_direction);\n"
"float cos_theta = clamp(dot(n, l), 0, 1);\n"
- "vec3 reflect_color = ambient + frag_color * light_color * cos_theta;\n"
+ "vec3 reflect_color = ambient + base_color * light_color * cos_theta;\n"
"float value = pow(e, -pow(fog_density * length(vtx_viewspace), 5));"
"color = mix(fog_color, reflect_color, value);\n"
"}\n"
m_handle = program.UniformLocation("M");
mv_handle = program.UniformLocation("MV");
mvp_handle = program.UniformLocation("MVP");
+ sampler_handle = program.UniformLocation("tex_sampler");
light_direction_handle = program.UniformLocation("light_direction");
light_color_handle = program.UniformLocation("light_color");
fog_density_handle = program.UniformLocation("fog_density");
program.Uniform(light_color_handle, col);
}
+void DirectionalLighting::SetTexture(ArrayTexture &tex) noexcept {
+ glActiveTexture(GL_TEXTURE0);
+ tex.Bind();
+ program.Uniform(sampler_handle, GLint(0));
+}
+
void DirectionalLighting::SetFogDensity(float f) noexcept {
program.Uniform(fog_density_handle, f);
}
GL_VERTEX_SHADER,
"#version 330 core\n"
"layout(location = 0) in vec3 vtx_position;\n"
- "layout(location = 1) in vec3 vtx_color;\n"
- "layout(location = 2) in float vtx_light;\n"
+ "layout(location = 1) in vec3 vtx_tex_uv;\n"
+ "layout(location = 2) in vec3 vtx_color;\n"
+ "layout(location = 3) in float vtx_light;\n"
"uniform mat4 MV;\n"
"uniform mat4 MVP;\n"
+ "out vec3 frag_tex_uv;\n"
"out vec3 frag_color;\n"
"out vec3 vtx_viewspace;\n"
"out float frag_light;\n"
"void main() {\n"
"gl_Position = MVP * vec4(vtx_position, 1);\n"
+ "frag_tex_uv = vtx_tex_uv;\n"
"frag_color = vtx_color;\n"
"vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
"frag_light = vtx_light;\n"
program.LoadShader(
GL_FRAGMENT_SHADER,
"#version 330 core\n"
+ "in vec3 frag_tex_uv;\n"
"in vec3 frag_color;\n"
"in vec3 vtx_viewspace;\n"
"in float frag_light;\n"
+ "uniform sampler2DArray tex_sampler;\n"
"uniform float fog_density;\n"
"out vec3 color;\n"
"void main() {\n"
- "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n"
+ "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
+ "vec3 base_color = tex_color * frag_color;\n"
"float light_power = clamp(pow(0.8, 15 - frag_light), 0, 1);\n"
"vec3 fog_color = vec3(0, 0, 0);\n"
"float e = 2.718281828;\n"
- //"vec3 reflect_color = ambient + frag_color * light_power;\n"
- "vec3 reflect_color = frag_color * light_power;\n"
+ "vec3 reflect_color = base_color * light_power;\n"
"float value = pow(e, -pow(fog_density * length(vtx_viewspace), 5));"
"color = mix(fog_color, reflect_color, value);\n"
"}\n"
mv_handle = program.UniformLocation("MV");
mvp_handle = program.UniformLocation("MVP");
+ sampler_handle = program.UniformLocation("tex_sampler");
fog_density_handle = program.UniformLocation("fog_density");
}
program.Use();
}
-void BlockLighting::SetM(const glm::mat4 &m) noexcept {
- program.Uniform(mv_handle, view * m);
- program.Uniform(mvp_handle, vp * m);
+void BlockLighting::SetTexture(ArrayTexture &tex) noexcept {
+ glActiveTexture(GL_TEXTURE0);
+ tex.Bind();
+ program.Uniform(sampler_handle, GLint(0));
}
void BlockLighting::SetFogDensity(float f) noexcept {
program.Uniform(fog_density_handle, f);
}
+void BlockLighting::SetM(const glm::mat4 &m) noexcept {
+ program.Uniform(mv_handle, view * m);
+ program.Uniform(mvp_handle, vp * m);
+}
+
void BlockLighting::SetProjection(const glm::mat4 &p) noexcept {
projection = p;
vp = p * view;
public:
using Position = glm::vec3;
+ using TexCoord = glm::vec3;
using Color = glm::vec3;
using Light = float;
using Index = unsigned int;
using Positions = std::vector<Position>;
+ using TexCoords = std::vector<TexCoord>;
using Colors = std::vector<Color>;
using Lights = std::vector<Light>;
using Indices = std::vector<Index>;
enum Attribute {
ATTRIB_VERTEX,
+ ATTRIB_TEXCOORD,
ATTRIB_COLOR,
ATTRIB_LIGHT,
ATTRIB_INDEX,
struct Buffer {
Positions vertices;
+ TexCoords tex_coords;
Colors colors;
Lights lights;
Indices indices;
void Clear() noexcept {
vertices.clear();
+ tex_coords.clear();
colors.clear();
lights.clear();
indices.clear();
void Reserve(size_t p, size_t i) {
vertices.reserve(p);
+ tex_coords.reserve(p);
colors.reserve(p);
lights.reserve(p);
indices.reserve(i);
public:
using Position = glm::vec3;
+ using TexCoord = glm::vec3;
using Color = glm::vec3;
using Normal = glm::vec3;
using Index = unsigned int;
using Positions = std::vector<Position>;
+ using TexCoords = std::vector<TexCoord>;
using Colors = std::vector<Color>;
using Normals = std::vector<Normal>;
using Indices = std::vector<Index>;
enum Attribute {
ATTRIB_VERTEX,
+ ATTRIB_TEXCOORD,
ATTRIB_COLOR,
ATTRIB_NORMAL,
ATTRIB_INDEX,
struct Buffer {
Positions vertices;
+ TexCoords tex_coords;
Colors colors;
Normals normals;
Indices indices;
void Clear() noexcept {
vertices.clear();
+ tex_coords.clear();
colors.clear();
normals.clear();
indices.clear();
void Reserve(size_t p, size_t i) {
vertices.reserve(p);
+ tex_coords.reserve(p);
colors.reserve(p);
normals.reserve(p);
indices.reserve(i);
#include "EntityModel.hpp"
#include "OutlineModel.hpp"
-#include <vector>
#include <glm/glm.hpp>
/// fill given buffers with this shape's elements with an
/// optional transform and offset
void Vertices(
- EntityModel::Positions &vertex,
- EntityModel::Normals &normal,
- EntityModel::Indices &index
+ EntityModel::Buffer &out,
+ float tex_offset = 0.0f
) const;
void Vertices(
- EntityModel::Positions &vertex,
- EntityModel::Normals &normal,
- EntityModel::Indices &index,
+ EntityModel::Buffer &out,
const glm::mat4 &transform,
+ float tex_offset = 0.0f,
EntityModel::Index idx_offset = 0
) const;
void Vertices(
- BlockModel::Positions &vertex,
- BlockModel::Indices &index,
+ BlockModel::Buffer &out,
const glm::mat4 &transform,
+ float tex_offset = 0.0f,
BlockModel::Index idx_offset = 0
) const;
/// fill given buffers with this shape's outline's elements with
/// an optional offset
void Outline(
- OutlineModel::Positions &vertex,
- OutlineModel::Indices &index,
+ OutlineModel::Buffer &out,
const OutlineModel::Position &offset = { 0.0f, 0.0f, 0.0f },
OutlineModel::Index idx_offset = 0
) const;
) const noexcept = 0;
protected:
- void SetShape(const EntityModel::Positions &pos, const EntityModel::Normals &nrm, const EntityModel::Indices &idx) {
- vtx_pos = pos;
- vtx_nrm = nrm;
- vtx_idx = idx;
- }
- void SetOutline(const OutlineModel::Positions &pos, const OutlineModel::Indices &idx) {
- out_pos = pos;
- out_idx = idx;
- }
+ void SetShape(
+ const EntityModel::Positions &pos,
+ const EntityModel::Normals &nrm,
+ const EntityModel::Indices &idx);
+ void SetTexture(
+ const BlockModel::TexCoords &tex_coords);
+ void SetOutline(
+ const OutlineModel::Positions &pos,
+ const OutlineModel::Indices &idx);
private:
EntityModel::Positions vtx_pos;
EntityModel::Normals vtx_nrm;
EntityModel::Indices vtx_idx;
+ BlockModel::TexCoords vtx_tex_coords;
+
OutlineModel::Positions out_pos;
OutlineModel::Indices out_idx;
void EntityModel::Update(const Buffer &buf) noexcept {
#ifndef NDEBUG
+ if (buf.tex_coords.size() < buf.vertices.size()) {
+ std::cerr << "EntityModel: not enough tex coords!" << std::endl;
+ }
if (buf.colors.size() < buf.vertices.size()) {
std::cerr << "EntityModel: not enough colors!" << std::endl;
}
vao.Bind();
vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
+ vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords);
vao.PushAttribute(ATTRIB_COLOR, buf.colors);
vao.PushAttribute(ATTRIB_NORMAL, buf.normals);
vao.PushIndices(ATTRIB_INDEX, buf.indices);
void BlockModel::Update(const Buffer &buf) noexcept {
#ifndef NDEBUG
+ if (buf.tex_coords.size() < buf.vertices.size()) {
+ std::cerr << "BlockModel: not enough tex coords!" << std::endl;
+ }
if (buf.colors.size() < buf.vertices.size()) {
std::cerr << "BlockModel: not enough colors!" << std::endl;
}
vao.Bind();
vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
+ vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords);
vao.PushAttribute(ATTRIB_COLOR, buf.colors);
vao.PushAttribute(ATTRIB_LIGHT, buf.lights);
vao.PushIndices(ATTRIB_INDEX, buf.indices);
namespace blank {
void Shape::Vertices(
- EntityModel::Positions &vertex,
- EntityModel::Normals &normal,
- EntityModel::Indices &index
+ EntityModel::Buffer &out,
+ float tex_offset
) const {
for (const auto &pos : vtx_pos) {
- vertex.emplace_back(pos);
+ out.vertices.emplace_back(pos);
+ }
+ for (const auto &coord : vtx_tex_coords) {
+ out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
}
for (const auto &nrm : vtx_nrm) {
- normal.emplace_back(nrm);
+ out.normals.emplace_back(nrm);
}
for (auto idx : vtx_idx) {
- index.emplace_back(idx);
+ out.indices.emplace_back(idx);
}
}
void Shape::Vertices(
- EntityModel::Positions &vertex,
- EntityModel::Normals &normal,
- EntityModel::Indices &index,
+ EntityModel::Buffer &out,
const glm::mat4 &transform,
+ float tex_offset,
EntityModel::Index idx_offset
) const {
for (const auto &pos : vtx_pos) {
- vertex.emplace_back(transform * glm::vec4(pos, 1.0f));
+ out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f));
+ }
+ for (const auto &coord : vtx_tex_coords) {
+ out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
}
for (const auto &nrm : vtx_nrm) {
- normal.emplace_back(transform * glm::vec4(nrm, 0.0f));
+ out.normals.emplace_back(transform * glm::vec4(nrm, 0.0f));
}
for (auto idx : vtx_idx) {
- index.emplace_back(idx_offset + idx);
+ out.indices.emplace_back(idx_offset + idx);
}
}
void Shape::Vertices(
- BlockModel::Positions &vertex,
- BlockModel::Indices &index,
+ BlockModel::Buffer &out,
const glm::mat4 &transform,
+ float tex_offset,
BlockModel::Index idx_offset
) const {
for (const auto &pos : vtx_pos) {
- vertex.emplace_back(transform * glm::vec4(pos, 1.0f));
+ out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f));
+ }
+ for (const auto &coord : vtx_tex_coords) {
+ out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
}
for (auto idx : vtx_idx) {
- index.emplace_back(idx_offset + idx);
+ out.indices.emplace_back(idx_offset + idx);
}
}
void Shape::Outline(
- OutlineModel::Positions &vertex,
- OutlineModel::Indices &index,
+ OutlineModel::Buffer &out,
const OutlineModel::Position &elem_offset,
OutlineModel::Index idx_offset
) const {
for (const auto &pos : out_pos) {
- vertex.emplace_back(elem_offset + pos);
+ out.vertices.emplace_back(elem_offset + pos);
}
for (auto idx : out_idx) {
- index.emplace_back(idx_offset + idx);
+ out.indices.emplace_back(idx_offset + idx);
}
}
+void Shape::SetShape(
+ const EntityModel::Positions &pos,
+ const EntityModel::Normals &nrm,
+ const EntityModel::Indices &idx
+) {
+ vtx_pos = pos;
+ vtx_nrm = nrm;
+ vtx_idx = idx;
+}
+
+void Shape::SetTexture(
+ const BlockModel::TexCoords &tex_coords
+) {
+ vtx_tex_coords = tex_coords;
+}
+
+void Shape::SetOutline(
+ const OutlineModel::Positions &pos,
+ const OutlineModel::Indices &idx
+) {
+ out_pos = pos;
+ out_idx = idx;
+}
+
NullShape::NullShape()
: Shape() {
16, 17, 18, 18, 17, 19, // left
20, 21, 22, 22, 21, 23, // right
});
+ SetTexture({
+ { 0.0f, 1.0f, 0.0f }, // front
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f }, // back
+ { 1.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f }, // top
+ { 0.0f, 1.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f }, // bottom
+ { 0.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f }, // left
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f }, // right
+ { 1.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ });
SetOutline({
{ bb.min.x, bb.min.y, bb.min.z }, // back
{ bb.max.x, bb.min.y, bb.min.z },
32, 33, 34, 34, 33, 35, // right, upper
36, 37, 38, 38, 37, 39, // right, lower
});
+ SetTexture({
+ { 0.0f, 0.5f, 0.0f }, // front, upper
+ { 1.0f, 0.5f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f }, // front, lower
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 0.5f, 0.0f },
+ { 1.0f, 0.5f, 0.0f },
+ { 1.0f, 1.0f, 0.0f }, // back
+ { 1.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f }, // top, upper
+ { 0.0f, 0.5f, 0.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 0.5f, 0.0f },
+ { 0.0f, 0.5f, 0.0f }, // top, lower
+ { 0.0f, 1.0f, 0.0f },
+ { 1.0f, 0.5f, 0.0f },
+ { 1.0f, 1.0f, 0.0f },
+ { 1.0f, 0.0f, 0.0f }, // bottom
+ { 0.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.5f, 0.0f }, // left, upper
+ { 0.5f, 0.5f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 0.5f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f }, // left, lower
+ { 1.0f, 1.0f, 0.0f },
+ { 0.0f, 0.5f, 0.0f },
+ { 1.0f, 0.5f, 0.0f },
+ { 1.0f, 0.5f, 0.0f }, // right, upper
+ { 1.0f, 0.0f, 0.0f },
+ { 0.5f, 0.5f, 0.0f },
+ { 0.5f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, 0.0f }, // right, lower
+ { 1.0f, 0.5f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.5f, 0.0f },
+ });
SetOutline({
{ bot.min.x, bot.min.y, bot.min.z }, // bottom
{ bot.max.x, bot.min.y, bot.min.z },
struct BlockType {
const Shape *shape;
+ float texture;
glm::vec3 color;
glm::vec3 outline_color;
}
-void Entity::SetShape(const Shape *s, const glm::vec3 &color) {
+void Entity::SetShape(const Shape *s, const glm::vec3 &color, float texture) {
shape = s;
model_buffer.Clear();
- shape->Vertices(model_buffer.vertices, model_buffer.normals, model_buffer.indices);
+ shape->Vertices(model_buffer, texture);
model_buffer.colors.resize(shape->VertexCount(), color);
model.Update(model_buffer);
}
bool HasShape() const noexcept { return shape; }
const Shape *GetShape() const noexcept { return shape; }
- void SetShape(const Shape *, const glm::vec3 &color);
+ void SetShape(const Shape *, const glm::vec3 &color, float texture);
void SetShapeless() noexcept;
const std::string &Name() const noexcept { return name; }
#include "World.hpp"
#include "WorldCollision.hpp"
+#include "../app/Assets.hpp"
+#include "../graphics/Format.hpp"
#include "../graphics/Viewport.hpp"
#include <iostream>
namespace blank {
-World::World(const Config &config)
+World::World(const Assets &assets, const Config &config)
: blockType()
, blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }})
, stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f })
, slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }})
+, block_tex()
, generate(config.gen)
, chunks(config.load, blockType, generate)
, player()
BlockType::Faces slab_fill = { false, true, false, false, false, false };
BlockType::Faces stair_fill = { false, true, false, false, false, true };
+ block_tex.Bind();
+ block_tex.Reserve(16, 16, 4, Format());
+ assets.LoadTexture("debug", block_tex, 0);
+ assets.LoadTexture("rock-1", block_tex, 1);
+ assets.LoadTexture("rock-2", block_tex, 2);
+ assets.LoadTexture("rock-3", block_tex, 3);
+ block_tex.FilterNearest();
+
{ // white block
BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape);
+ type.texture = 1;
type.label = "White Block";
type.block_light = true;
type.collision = true;
}
{ // white slab
BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape);
+ type.texture = 1;
type.label = "White Slab";
type.block_light = true;
type.collision = true;
}
{ // white stair
BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape);
+ type.texture = 1;
type.label = "White Stair";
type.block_light = true;
type.collision = true;
{ // red block
BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape);
+ type.texture = 3;
type.label = "Red Block";
type.block_light = true;
type.collision = true;
}
{ // red slab
BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape);
+ type.texture = 3;
type.label = "Red Slab";
type.block_light = true;
type.collision = true;
}
{ // red stair
BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape);
+ type.texture = 3;
type.label = "Red Stair";
type.block_light = true;
type.collision = true;
{ // green block
BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape);
+ type.texture = 1;
type.label = "Green Block";
type.block_light = true;
type.collision = true;
}
{ // green slab
BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape);
+ type.texture = 1;
type.label = "Green Slab";
type.block_light = true;
type.collision = true;
}
{ // green stair
BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape);
+ type.texture = 1;
type.label = "Green Stair";
type.block_light = true;
type.collision = true;
{ // blue block
BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape);
+ type.texture = 3;
type.label = "Blue Block";
type.block_light = true;
type.collision = true;
}
{ // blue slab
BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape);
+ type.texture = 3;
type.label = "Blue Slab";
type.block_light = true;
type.collision = true;
}
{ // blue stair
BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape);
+ type.texture = 3;
type.label = "Blue Stair";
type.block_light = true;
type.collision = true;
{ // glowing yellow block
BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape);
+ type.texture = 2;
type.label = "Light";
type.luminosity = 15;
type.block_light = true;
blockType.Add(type);
}
+ { // the mysterious debug cube
+ BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape);
+ type.texture = 0;
+ type.label = "Debug Cube";
+ type.luminosity = 0;
+ type.block_light = true;
+ type.collision = true;
+ type.collide_block = true;
+ type.fill = block_fill;
+ blockType.Add(type);
+ }
+
generate.Space(0);
generate.Light(13);
generate.Solids({ 1, 4, 7, 10 });
viewport.WorldPosition(player->Transform(player->ChunkCoords()));
BlockLighting &chunk_prog = viewport.ChunkProgram();
+ chunk_prog.SetTexture(block_tex);
chunk_prog.SetFogDensity(fog_density);
for (Chunk &chunk : chunks.Loaded()) {
#include "ChunkLoader.hpp"
#include "Entity.hpp"
#include "Generator.hpp"
+#include "../graphics/ArrayTexture.hpp"
#include "../model/shapes.hpp"
#include <list>
namespace blank {
+class Assets;
class Viewport;
class WorldCollision;
ChunkLoader::Config load = ChunkLoader::Config();
};
- explicit World(const Config &);
+ World(const Assets &, const Config &);
bool Intersection(
const Ray &,
StairShape stairShape;
CuboidShape slabShape;
+ ArrayTexture block_tex;
+
Generator generate;
ChunkLoader chunks;
BlockType::BlockType(bool v, const glm::vec3 &col, const Shape *s) noexcept
: shape(s)
+, texture(0)
, color(col)
, outline_color(-1, -1, -1)
, label("some block")
const glm::mat4 &transform,
EntityModel::Index idx_offset
) const noexcept {
- shape->Vertices(buf.vertices, buf.normals, buf.indices, transform, idx_offset);
+ shape->Vertices(buf, transform, texture, idx_offset);
buf.colors.insert(buf.colors.end(), shape->VertexCount(), color);
}
const glm::mat4 &transform,
BlockModel::Index idx_offset
) const noexcept {
- shape->Vertices(buf.vertices, buf.indices, transform, idx_offset);
+ shape->Vertices(buf, transform, texture, idx_offset);
buf.colors.insert(buf.colors.end(), shape->VertexCount(), color);
}
const glm::vec3 &pos_offset,
OutlineModel::Index idx_offset
) const noexcept {
- shape->Outline(buf.vertices, buf.indices, pos_offset, idx_offset);
+ shape->Outline(buf, pos_offset, idx_offset);
buf.colors.insert(buf.colors.end(), shape->OutlineCount(), outline_color);
}