aboutsummaryrefslogtreecommitdiff
path: root/src/shaders/simple_shaders.hpp
blob: c308ab3c791590f493bbb7dce51264babd4f4bc3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#ifndef SHADERS_SIMPLE_SHADERS_HPP
#define SHADERS_SIMPLE_SHADERS_HPP

#include <algorithm>
#include <cmath>
#include "fb/pixfb.hpp"
#include "math/vector.hpp"
#include "math/mat4.hpp"
#include "o3d/vertex.hpp"

namespace engine::shaders {

class SimpleShaders {
    public:
        using fb_type = engine::fb::PixelFrameBuffer;

        engine::math::Matrix4 model_mat, view_mat, proj_mat, final_mat;
        int w, h;
        unsigned char* pixels;

        SimpleShaders(int w, int h, unsigned char* pixels);
        void set_view(const engine::math::Matrix4& view_mat, const engine::math::Matrix4& proj_mat);
        void set_model(const engine::math::Matrix4& model_mat);

        constexpr engine::o3d::Vertex vertex(const engine::math::Vector3& vertex, const engine::math::Vector3& normal, const engine::math::Vector2& uv) const & {
            return { final_mat * engine::math::Vector4 { vertex, 1.f }, (model_mat * engine::math::Vector4 { normal, 0.f }).xyz(), uv };
        }

        constexpr engine::math::Vector4 fragment(int /* x */, int /* y */, const engine::math::Vector3& /* loc */, const engine::math::Vector3& /* normal */,
                const engine::math::Vector2& uv) const & {
            // auto u = vd.world_loc - camera->transform.loc;
            // float u_len_sq = u.length_squared();
            // u = u.normalize();
            // float attenuation = camera->transform.rot.rot({ 0.f, 0.f, -1.f }).dot(u);
            // if (attenuation < .7f) attenuation = 0.f;
            // else if (attenuation > .8f) attenuation = 1.f;
            // else attenuation = (attenuation - .7f) / .1f;
            // float light = -normal.normalize().dot(u) / u_len_sq;
            // if (light < 0.f) light = 0.f;
            // float final_light = .003f + light * attenuation * .8f * .997f;
            // if (final_light > 1.f) final_light = 1.f;
            // // gamma correction
            // // TODO: improve, we shouldn't do it here
            // if (final_light <= .0031308f)
            //     final_light = final_light * 12.92f;
            // else
            //     final_light = 1.055f * pow(final_light, 1.f / 2.4f) - .055f;
            // std::uint32_t c = (int) (final_light * 255.f);
            // pixels_vector[x + y * w] = 0xff000000 | c << 16 | c << 8 | c;
            float txf, tyf;
            float fac_x = std::modf(uv.x * static_cast<float>(w) - .5f, &txf);
            float fac_y = std::modf(uv.y * static_cast<float>(h) - .5f, &tyf);
            int tx0 = std::clamp(static_cast<int>(txf) + 0, 0, w);
            int tx1 = std::clamp(static_cast<int>(txf) + 1, 0, w);
            int ty0 = std::clamp(static_cast<int>(tyf) + 0, 0, h);
            int ty1 = std::clamp(static_cast<int>(tyf) + 1, 0, h);
            float r00 = static_cast<float>(pixels[(tx0 + ty0 * w) * 4 + 0]) / 255.f;
            float r10 = static_cast<float>(pixels[(tx1 + ty0 * w) * 4 + 0]) / 255.f;
            float r01 = static_cast<float>(pixels[(tx0 + ty1 * w) * 4 + 0]) / 255.f;
            float r11 = static_cast<float>(pixels[(tx1 + ty1 * w) * 4 + 0]) / 255.f;
            float r = (1.f - fac_x) * (1.f - fac_y) * r00 + fac_x * (1.f - fac_y) * r10 + (1.f - fac_x) * fac_y * r01 + fac_x * fac_y * r11;
            float g00 = static_cast<float>(pixels[(tx0 + ty0 * w) * 4 + 1]) / 255.f;
            float g10 = static_cast<float>(pixels[(tx1 + ty0 * w) * 4 + 1]) / 255.f;
            float g01 = static_cast<float>(pixels[(tx0 + ty1 * w) * 4 + 1]) / 255.f;
            float g11 = static_cast<float>(pixels[(tx1 + ty1 * w) * 4 + 1]) / 255.f;
            float g = (1.f - fac_x) * (1.f - fac_y) * g00 + fac_x * (1.f - fac_y) * g10 + (1.f - fac_x) * fac_y * g01 + fac_x * fac_y * g11;
            float b00 = static_cast<float>(pixels[(tx0 + ty0 * w) * 4 + 2]) / 255.f;
            float b10 = static_cast<float>(pixels[(tx1 + ty0 * w) * 4 + 2]) / 255.f;
            float b01 = static_cast<float>(pixels[(tx0 + ty1 * w) * 4 + 2]) / 255.f;
            float b11 = static_cast<float>(pixels[(tx1 + ty1 * w) * 4 + 2]) / 255.f;
            float b = (1.f - fac_x) * (1.f - fac_y) * b00 + fac_x * (1.f - fac_y) * b10 + (1.f - fac_x) * fac_y * b01 + fac_x * fac_y * b11;
            float a00 = static_cast<float>(pixels[(tx0 + ty0 * w) * 4 + 3]) / 255.f;
            float a10 = static_cast<float>(pixels[(tx1 + ty0 * w) * 4 + 3]) / 255.f;
            float a01 = static_cast<float>(pixels[(tx0 + ty1 * w) * 4 + 3]) / 255.f;
            float a11 = static_cast<float>(pixels[(tx1 + ty1 * w) * 4 + 3]) / 255.f;
            float a = (1.f - fac_x) * (1.f - fac_y) * a00 + fac_x * (1.f - fac_y) * a10 + (1.f - fac_x) * fac_y * a01 + fac_x * fac_y * a11;
            return engine::math::Vector4 { r, g, b, a };
        }
};

}

#endif // SHADERS_SIMPLE_SHADERS_HPP