feat: display a handheld item in first-person view (WIP)
This commit is contained in:
parent
fb17228eff
commit
b93668ba94
@ -101,7 +101,7 @@ void LevelScreen::saveWorldPreview() {
|
||||
Viewport viewport(previewSize * 1.5, previewSize);
|
||||
DrawContext ctx(&pctx, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, &camera, false, true, 0.0f, postProcessing.get());
|
||||
worldRenderer->draw(ctx, camera, false, true, 0.0f, postProcessing.get());
|
||||
auto image = postProcessing->toImage();
|
||||
image->flipY();
|
||||
imageio::write(paths->resolve("world:preview.png").u8string(), image.get());
|
||||
@ -164,7 +164,9 @@ void LevelScreen::draw(float delta) {
|
||||
Viewport viewport(Window::width, Window::height);
|
||||
DrawContext ctx(nullptr, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, camera.get(), hudVisible, hud->isPause(), delta, postProcessing.get());
|
||||
worldRenderer->draw(
|
||||
ctx, *camera, hudVisible, hud->isPause(), delta, postProcessing.get()
|
||||
);
|
||||
|
||||
if (hudVisible) {
|
||||
hud->draw(ctx);
|
||||
|
||||
@ -77,6 +77,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix,
|
||||
const texture_names_map* varTextures,
|
||||
bool backlight) {
|
||||
glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
gpos += lightsOffset;
|
||||
light_t light = chunks->getLight(
|
||||
std::floor(gpos.x),
|
||||
std::floor(std::min(CHUNK_H-1.0f, gpos.y)),
|
||||
@ -137,6 +138,10 @@ void ModelBatch::render() {
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
void ModelBatch::setLightsOffset(const glm::vec3& offset) {
|
||||
lightsOffset = offset;
|
||||
}
|
||||
|
||||
void ModelBatch::setTexture(const std::string& name,
|
||||
const texture_names_map* varTextures) {
|
||||
if (name.at(0) == '$') {
|
||||
|
||||
@ -34,6 +34,7 @@ class ModelBatch {
|
||||
Texture* texture = nullptr;
|
||||
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
|
||||
const EngineSettings* settings;
|
||||
glm::vec3 lightsOffset {};
|
||||
|
||||
static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f};
|
||||
|
||||
@ -96,4 +97,6 @@ public:
|
||||
const model::Model* model,
|
||||
const texture_names_map* varTextures);
|
||||
void render();
|
||||
|
||||
void setLightsOffset(const glm::vec3& offset);
|
||||
};
|
||||
|
||||
@ -78,17 +78,17 @@ WorldRenderer::WorldRenderer(
|
||||
WorldRenderer::~WorldRenderer() = default;
|
||||
|
||||
bool WorldRenderer::drawChunk(
|
||||
size_t index, Camera* camera, Shader* shader, bool culling
|
||||
size_t index, const Camera& camera, Shader* shader, bool culling
|
||||
) {
|
||||
auto chunk = level->chunks->getChunks()[index];
|
||||
if (!chunk->flags.lighted) {
|
||||
return false;
|
||||
}
|
||||
float distance = glm::distance(
|
||||
camera->position,
|
||||
camera.position,
|
||||
glm::vec3(
|
||||
(chunk->x + 0.5f) * CHUNK_W,
|
||||
camera->position.y,
|
||||
camera.position.y,
|
||||
(chunk->z + 0.5f) * CHUNK_D
|
||||
)
|
||||
);
|
||||
@ -113,7 +113,9 @@ bool WorldRenderer::drawChunk(
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
void WorldRenderer::drawChunks(
|
||||
Chunks* chunks, const Camera& camera, Shader* shader
|
||||
) {
|
||||
auto assets = engine->getAssets();
|
||||
auto atlas = assets->get<Atlas>("blocks");
|
||||
|
||||
@ -127,8 +129,8 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
if (chunks->getChunks()[i] == nullptr) continue;
|
||||
indices.emplace_back(i);
|
||||
}
|
||||
float px = camera->position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||
float pz = camera->position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||
float px = camera.position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||
float pz = camera.position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||
std::sort(indices.begin(), indices.end(), [chunks, px, pz](auto i, auto j) {
|
||||
const auto& chunksBuffer = chunks->getChunks();
|
||||
const auto a = chunksBuffer[i].get();
|
||||
@ -141,7 +143,7 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
});
|
||||
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
||||
if (culling) {
|
||||
frustumCulling->update(camera->getProjView());
|
||||
frustumCulling->update(camera.getProjView());
|
||||
}
|
||||
chunks->visible = 0;
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
@ -151,20 +153,20 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
|
||||
void WorldRenderer::setupWorldShader(
|
||||
Shader* shader,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float fogFactor
|
||||
) {
|
||||
shader->use();
|
||||
shader->uniformMatrix("u_model", glm::mat4(1.0f));
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniformMatrix("u_proj", camera.getProjection());
|
||||
shader->uniformMatrix("u_view", camera.getView());
|
||||
shader->uniform1f("u_timer", timer);
|
||||
shader->uniform1f("u_gamma", settings.graphics.gamma.get());
|
||||
shader->uniform1f("u_fogFactor", fogFactor);
|
||||
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
||||
shader->uniform1f("u_dayTime", level->getWorld()->getInfo().daytime);
|
||||
shader->uniform3f("u_cameraPos", camera->position);
|
||||
shader->uniform3f("u_cameraPos", camera.position);
|
||||
shader->uniform1i("u_cubemap", 1);
|
||||
|
||||
auto indices = level->content->getIndices();
|
||||
@ -186,7 +188,7 @@ void WorldRenderer::setupWorldShader(
|
||||
|
||||
void WorldRenderer::renderLevel(
|
||||
const DrawContext&,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float delta,
|
||||
bool pause
|
||||
@ -251,10 +253,10 @@ void WorldRenderer::renderBlockSelection() {
|
||||
}
|
||||
|
||||
void WorldRenderer::renderLines(
|
||||
Camera* camera, Shader* linesShader, const DrawContext& pctx
|
||||
const Camera& camera, Shader* linesShader, const DrawContext& pctx
|
||||
) {
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
linesShader->uniformMatrix("u_projview", camera.getProjView());
|
||||
if (player->selection.vox.id != BLOCK_VOID) {
|
||||
renderBlockSelection();
|
||||
}
|
||||
@ -268,7 +270,7 @@ void WorldRenderer::renderLines(
|
||||
}
|
||||
|
||||
void WorldRenderer::renderDebugLines(
|
||||
const DrawContext& pctx, Camera* camera, Shader* linesShader
|
||||
const DrawContext& pctx, const Camera& camera, Shader* linesShader
|
||||
) {
|
||||
DrawContext ctx = pctx.sub(lineBatch.get());
|
||||
const auto& viewport = ctx.getViewport();
|
||||
@ -280,7 +282,7 @@ void WorldRenderer::renderDebugLines(
|
||||
linesShader->use();
|
||||
|
||||
if (showChunkBorders) {
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
linesShader->uniformMatrix("u_projview", camera.getProjView());
|
||||
glm::vec3 coord = player->camera->position;
|
||||
if (coord.x < 0) coord.x--;
|
||||
if (coord.z < 0) coord.z--;
|
||||
@ -310,7 +312,7 @@ void WorldRenderer::renderDebugLines(
|
||||
-length,
|
||||
length
|
||||
) * model *
|
||||
glm::inverse(camera->rotation)
|
||||
glm::inverse(camera.rotation)
|
||||
);
|
||||
|
||||
ctx.setDepthTest(false);
|
||||
@ -327,9 +329,61 @@ void WorldRenderer::renderDebugLines(
|
||||
lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
void WorldRenderer::renderHands(const Camera& camera, const Assets& assets) {
|
||||
auto entityShader = assets.get<Shader>("entity");
|
||||
auto indices = level->content->getIndices();
|
||||
|
||||
// get current chosen item
|
||||
const auto& inventory = player->getInventory();
|
||||
int slot = player->getChosenSlot();
|
||||
const ItemStack& stack = inventory->getSlot(slot);
|
||||
const auto& def = indices->items.require(stack.getItemId());
|
||||
|
||||
// prepare modified HUD camera
|
||||
Camera hudcam = camera;
|
||||
hudcam.far = 100.0f;
|
||||
hudcam.setFov(1.2f);
|
||||
hudcam.position = {};
|
||||
|
||||
// configure model matrix
|
||||
const glm::vec3 itemOffset(0.08f, 0.035f, -0.1);
|
||||
|
||||
glm::mat4 matrix = glm::translate(glm::mat4(1.0f), itemOffset);
|
||||
matrix = glm::scale(matrix, glm::vec3(0.1f));
|
||||
matrix = camera.rotation * matrix *
|
||||
glm::rotate(
|
||||
glm::mat4(1.0f), -glm::pi<float>() * 0.5f, glm::vec3(0, 1, 0)
|
||||
);
|
||||
auto offset = -(camera.position - player->getPosition());
|
||||
float angle = glm::radians(player->cam.x - 90);
|
||||
float cos = glm::cos(angle);
|
||||
float sin = glm::sin(angle);
|
||||
|
||||
float newX = offset.x * cos - offset.z * sin;
|
||||
float newZ = offset.x * sin + offset.z * cos;
|
||||
matrix = matrix *
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(newX, offset.y, newZ));
|
||||
|
||||
// render
|
||||
texture_names_map map = {};
|
||||
modelBatch->setLightsOffset(camera.position);
|
||||
modelBatch->draw(
|
||||
matrix,
|
||||
glm::vec3(1.0f),
|
||||
assets.get<model::Model>(def.name + ".model"),
|
||||
&map
|
||||
);
|
||||
Window::clearDepth();
|
||||
setupWorldShader(entityShader, hudcam, engine->getSettings(), 0.0f);
|
||||
skybox->bind();
|
||||
modelBatch->render();
|
||||
modelBatch->setLightsOffset(glm::vec3());
|
||||
skybox->unbind();
|
||||
}
|
||||
|
||||
void WorldRenderer::draw(
|
||||
const DrawContext& pctx,
|
||||
Camera* camera,
|
||||
Camera& camera,
|
||||
bool hudVisible,
|
||||
bool pause,
|
||||
float delta,
|
||||
@ -338,7 +392,7 @@ void WorldRenderer::draw(
|
||||
timer += delta * !pause;
|
||||
auto world = level->getWorld();
|
||||
const Viewport& vp = pctx.getViewport();
|
||||
camera->aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
||||
camera.aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
||||
|
||||
const auto& settings = engine->getSettings();
|
||||
const auto& worldInfo = world->getInfo();
|
||||
@ -356,7 +410,7 @@ void WorldRenderer::draw(
|
||||
Window::clearDepth();
|
||||
|
||||
// Drawing background sky plane
|
||||
skybox->draw(pctx, camera, assets, worldInfo.daytime, worldInfo.fog);
|
||||
skybox->draw(pctx, &camera, assets, worldInfo.daytime, worldInfo.fog);
|
||||
|
||||
// Actually world render with depth buffer on
|
||||
{
|
||||
@ -367,6 +421,7 @@ void WorldRenderer::draw(
|
||||
// Debug lines
|
||||
if (hudVisible) {
|
||||
renderLines(camera, linesShader, ctx);
|
||||
renderHands(camera, *assets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ class Skybox;
|
||||
class PostProcessing;
|
||||
class DrawContext;
|
||||
class ModelBatch;
|
||||
class Assets;
|
||||
struct EngineSettings;
|
||||
|
||||
namespace model {
|
||||
@ -41,16 +42,20 @@ class WorldRenderer {
|
||||
std::unique_ptr<ModelBatch> modelBatch;
|
||||
float timer = 0.0f;
|
||||
|
||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling);
|
||||
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader);
|
||||
bool drawChunk(size_t index, const Camera& camera, Shader* shader, bool culling);
|
||||
void drawChunks(Chunks* chunks, const Camera& camera, Shader* shader);
|
||||
|
||||
/// @brief Render block selection lines
|
||||
void renderBlockSelection();
|
||||
|
||||
void renderHands(const Camera& camera, const Assets& assets);
|
||||
|
||||
/// @brief Render lines (selection and debug)
|
||||
/// @param camera active camera
|
||||
/// @param linesShader shader used
|
||||
void renderLines(Camera* camera, Shader* linesShader, const DrawContext& pctx);
|
||||
void renderLines(
|
||||
const Camera& camera, Shader* linesShader, const DrawContext& pctx
|
||||
);
|
||||
|
||||
/// @brief Render all debug lines (chunks borders, coord system guides)
|
||||
/// @param context graphics context
|
||||
@ -58,13 +63,13 @@ class WorldRenderer {
|
||||
/// @param linesShader shader used
|
||||
void renderDebugLines(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
Shader* linesShader
|
||||
);
|
||||
|
||||
void setupWorldShader(
|
||||
Shader* shader,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float fogFactor
|
||||
);
|
||||
@ -77,7 +82,7 @@ public:
|
||||
|
||||
void draw(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
Camera& camera,
|
||||
bool hudVisible,
|
||||
bool pause,
|
||||
float delta,
|
||||
@ -91,7 +96,7 @@ public:
|
||||
/// @param settings engine settings
|
||||
void renderLevel(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float delta,
|
||||
bool pause
|
||||
|
||||
@ -252,7 +252,7 @@ entityid_t Player::getSelectedEntity() const {
|
||||
return selectedEid;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Player::getInventory() const {
|
||||
const std::shared_ptr<Inventory>& Player::getInventory() const {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ public:
|
||||
|
||||
entityid_t getSelectedEntity() const;
|
||||
|
||||
std::shared_ptr<Inventory> getInventory() const;
|
||||
const std::shared_ptr<Inventory>& getInventory() const;
|
||||
|
||||
glm::vec3 getPosition() const {
|
||||
return position;
|
||||
|
||||
@ -29,21 +29,21 @@ void Camera::rotate(float x, float y, float z) {
|
||||
updateVectors();
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getProjection() {
|
||||
glm::mat4 Camera::getProjection() const {
|
||||
constexpr float epsilon = 1e-6f; // 0.000001
|
||||
float aspect_ratio = this->aspect;
|
||||
if (std::fabs(aspect_ratio) < epsilon) {
|
||||
aspect_ratio = (float)Window::width / (float)Window::height;
|
||||
}
|
||||
if (perspective)
|
||||
return glm::perspective(fov * zoom, aspect_ratio, 0.05f, 1500.0f);
|
||||
return glm::perspective(fov * zoom, aspect_ratio, near, far);
|
||||
else if (flipped)
|
||||
return glm::ortho(0.0f, fov * aspect_ratio, fov, 0.0f);
|
||||
else
|
||||
return glm::ortho(0.0f, fov * aspect_ratio, 0.0f, fov);
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getView(bool pos) {
|
||||
glm::mat4 Camera::getView(bool pos) const {
|
||||
glm::vec3 camera_pos = this->position;
|
||||
if (!pos) {
|
||||
camera_pos = glm::vec3(0.0f);
|
||||
@ -55,7 +55,7 @@ glm::mat4 Camera::getView(bool pos) {
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getProjView(bool pos) {
|
||||
glm::mat4 Camera::getProjView(bool pos) const {
|
||||
return getProjection() * getView(pos);
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ public:
|
||||
bool perspective = true;
|
||||
bool flipped = false;
|
||||
float aspect = 0.0f;
|
||||
float near = 0.05f;
|
||||
float far = 1500.0f;
|
||||
|
||||
Camera() {
|
||||
updateVectors();
|
||||
@ -27,9 +29,9 @@ public:
|
||||
void updateVectors();
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
glm::mat4 getProjection();
|
||||
glm::mat4 getView(bool position = true);
|
||||
glm::mat4 getProjView(bool position = true);
|
||||
glm::mat4 getProjection() const;
|
||||
glm::mat4 getView(bool position = true) const;
|
||||
glm::mat4 getProjView(bool position = true) const;
|
||||
|
||||
void setFov(float fov);
|
||||
float getFov() const;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user