← index
libmx2/libmx/gl_glitch_cube/glitch.cpp
Source: libmx2/libmx/gl_glitch_cube/glitch.cpp
#include"mx.hpp"

#include"argz.hpp"


#ifdef __EMSCRIPTEN__

#include <emscripten/emscripten.h>

#include <GLES3/gl3.h>

#endif


#include"gl.hpp"

#include"loadpng.hpp"

#include"model.hpp"


#define CHECK_GL_ERROR() \

    { GLenum err = glGetError(); \
      if (err != GL_NO_ERROR) \
        printf("OpenGL Error: %d at %s:%d\n", err, __FILE__, __LINE__); }
#if defined(__EMSCRIPTEN__) || defined(__ANDOIRD__)

const char *g_vSource = R"(#version 300 es
    precision highp float;
    layout (location = 0) in vec3 aPos;

    layout (location = 1) in vec3 aNormal;
    layout (location = 2) in vec2 aTexCoords;
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;

    uniform vec3 lightPos;
    uniform vec3 viewPos;
    uniform vec3 lightColor;
    uniform vec3 objectColor;

    out vec3 vertexColor;
    out vec2 TexCoords;

    void main()
    {
        vec4 worldPos = model * vec4(aPos, 1.0);
        gl_Position = projection * view * worldPos;
        vec3 norm = normalize(mat3(transpose(inverse(model))) * aNormal);
        vec3 lightDir = normalize(lightPos - vec3(worldPos));
        float ambientStrength = 0.8; 
        vec3 ambient = ambientStrength * lightColor;
        float diff = max(dot(norm, lightDir), 0.0);
        vec3 diffuse = diff * lightColor;
        float specularStrength = 1.0;    // Increase from 0.5 to 1.0 for more shine
        float shininess = 64.0;          // Increase this value for a tighter, shinier highlight
        vec3 viewDir = normalize(viewPos - vec3(worldPos));
        vec3 reflectDir = reflect(-lightDir, norm);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
        vec3 specular = specularStrength * spec * lightColor;
        vec3 finalColor = (ambient + diffuse + specular) * objectColor;
        vertexColor = finalColor;
        TexCoords = aTexCoords;
    }

    )";
    const char *g_fSource = R"(#version 300 es
    precision highp float;
    in vec3 vertexColor;
    in vec2 TexCoords;
    uniform sampler2D texture1;
    uniform vec2 iResolution; // Screen resolution for aspect
    uniform float time_f;     // Time for animation
    out vec4 FragColor;

    vec4 distort4(vec2 tc, sampler2D samp) { 
    vec4 ctx;
    vec2 uv = tc * 2.0 - 1.0;
    uv *= iResolution.y / iResolution.x;

    vec2 center = vec2(0.0, 0.0);
    vec2 offset = uv - center;
    float dist = length(offset);
    float pulse = sin(time_f * 2.0 + dist * 10.0) * 0.15;
    float expansion = cos(time_f * 3.0 - dist * 15.0) * 0.2;
    float spiral = sin(atan(offset.y, offset.x) * 3.0 + time_f * 2.0) * 0.1;

    vec2 morphUV = uv + normalize(offset) * (pulse + expansion);
    morphUV += vec2(cos(atan(offset.y, offset.x)), sin(atan(offset.y, offset.x))) * spiral;

    vec4 texColor = texture(samp, morphUV * 0.5 + 0.5);
    texColor.rgb *= 1.0 + 0.3 * sin(dist * 20.0 - time_f * 5.0);

    ctx = vec4(texColor.rgb, texColor.a);
    return ctx;
    }

    void main() {
    FragColor = vec4(vertexColor, 1.0) * texture(texture1, TexCoords);
    vec4 ctx = distort4(TexCoords, texture1);
    FragColor = ctx * FragColor;
    FragColor.a = 1.0;
    }
    )";
    #else
    const char *g_vSource = R"(#version 330 core
        layout (location = 0) in vec3 aPos;

        layout (location = 1) in vec3 aNormal;
        layout (location = 2) in vec2 aTexCoords;
        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;

        uniform vec3 lightPos;
        uniform vec3 viewPos;
        uniform vec3 lightColor;
        uniform vec3 objectColor;

        out vec3 vertexColor;
        out vec2 TexCoords;

        void main()
        {
            vec4 worldPos = model * vec4(aPos, 1.0);
            gl_Position = projection * view * worldPos;
            vec3 norm = normalize(mat3(transpose(inverse(model))) * aNormal);
            vec3 lightDir = normalize(lightPos - vec3(worldPos));
            float ambientStrength = 0.8; 
            vec3 ambient = ambientStrength * lightColor;
            float diff = max(dot(norm, lightDir), 0.0);
            vec3 diffuse = diff * lightColor;
            float specularStrength = 1.0;    
            float shininess = 64.0;          
            vec3 viewDir = normalize(viewPos - vec3(worldPos));
            vec3 reflectDir = reflect(-lightDir, norm);
            float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
            vec3 specular = specularStrength * spec * lightColor;
            vec3 finalColor = (ambient + diffuse + specular) * objectColor;
            vertexColor = finalColor;
            TexCoords = aTexCoords;
        }

    )";
    const char *g_fSource = R"(#version 330 core
in vec3 vertexColor;
in vec2 TexCoords;
uniform sampler2D texture1;
uniform vec2 iResolution; // Screen resolution for aspect
uniform float time_f;     // Time for animation
out vec4 FragColor;

vec4 distort4(vec2 tc, sampler2D samp) { 
    vec4 ctx;
    vec2 uv = tc * 2.0 - 1.0;
    uv *= iResolution.y / iResolution.x;

    vec2 center = vec2(0.0, 0.0);
    vec2 offset = uv - center;
    float dist = length(offset);
    float pulse = sin(time_f * 2.0 + dist * 10.0) * 0.15;
    float expansion = cos(time_f * 3.0 - dist * 15.0) * 0.2;
    float spiral = sin(atan(offset.y, offset.x) * 3.0 + time_f * 2.0) * 0.1;

    vec2 morphUV = uv + normalize(offset) * (pulse + expansion);
    morphUV += vec2(cos(atan(offset.y, offset.x)), sin(atan(offset.y, offset.x))) * spiral;

    vec4 texColor = texture(samp, morphUV * 0.5 + 0.5);
    texColor.rgb *= 1.0 + 0.3 * sin(dist * 20.0 - time_f * 5.0);

    ctx = vec4(texColor.rgb, texColor.a);
    return ctx;
}

void main() {
    FragColor = vec4(vertexColor, 1.0) * texture(texture1, TexCoords);
    vec4 ctx = distort4(TexCoords, texture1);
    FragColor = ctx * FragColor;
    FragColor.a = 1.0;
}
)";
#endif


class Cube : public gl::GLObject {
public:
    gl::ShaderProgram shaderProgram;
    GLuint VAO, VBO;
    GLuint texture;
    mx::Model cube;        
    mx::Font font;
    Cube() = default;
    virtual ~Cube() override {
    }

    std::vector<GLfloat> cubeData;

    virtual void load(gl::GLWindow *win) override {     
        font.loadFont(win->util.getFilePath("data/font.ttf"), 18);
        if(cube.openModel(win->util.getFilePath("data/cube.mxmod.z")) == false) {
            throw mx::Exception("Error loading model");
        }
        if (!shaderProgram.loadProgramFromText(g_vSource, g_fSource)) {
            throw mx::Exception("Failed to load shader program");
        }
        shaderProgram.useProgram();
        cube.setTextures(win, win->util.getFilePath("data/cube.tex"), win->util.getFilePath("data"));
    }

    virtual void draw(gl::GLWindow *win) override {
        shaderProgram.useProgram();
        CHECK_GL_ERROR();
#ifdef __EMSCRIPTEN__

        static Uint32 lastTime = emscripten_get_now(); 
        float currentTime = emscripten_get_now();
        float deltaTime = (currentTime - lastTime) / 1000.0f;
        lastTime = currentTime;
#else

        static Uint32 lastTime = SDL_GetTicks(); 
        Uint32 currentTime = SDL_GetTicks();
        float deltaTime = (currentTime - lastTime) / 1000.0f;
        lastTime = currentTime;
#endif

        static float rotationAngle = 0.0f;
        rotationAngle += deltaTime * 50.0f; 
        cube.setShaderProgram(&shaderProgram, "texture1");
        shaderProgram.useProgram();
        cameraPosition = glm::vec3(0.0f, 2.0f, 5.0f);
        glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
        glm::vec3 upVector = glm::vec3(0.0f, 1.0f, 0.0f);
        modelMatrix = glm::mat4(1.0f);
        modelMatrix = glm::scale(modelMatrix, glm::vec3(2.0f, 2.0f, 2.0f));
        modelMatrix = glm::rotate(modelMatrix, glm::radians(rotationAngle), glm::vec3(rot_x, 1.0f, 0.0f));
        viewMatrix = glm::lookAt(cameraPosition, cameraTarget, upVector);
        float aspectRatio = static_cast<float>(win->w) / static_cast<float>(win->h);
        projectionMatrix = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f);      
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram.id(), "model"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram.id(), "view"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram.id(), "projection"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
        glUniform3f(glGetUniformLocation(shaderProgram.id(), "lightPos"), lightPos.x, lightPos.y, lightPos.z);
        glUniform3f(glGetUniformLocation(shaderProgram.id(), "viewPos"), cameraPosition.x, cameraPosition.y, cameraPosition.z);
        glUniform3f(glGetUniformLocation(shaderProgram.id(), "lightColor"), 2.0f, 2.0f, 2.0f);
        glUniform3f(glGetUniformLocation(shaderProgram.id(), "objectColor"), 1.0f, 1.0f, 1.0f); 
        glUniform2f(glGetUniformLocation(shaderProgram.id(), "iResolution"), 
                    static_cast<float>(win->w), static_cast<float>(win->h));
        glUniform1f(glGetUniformLocation(shaderProgram.id(), "time_f"), 
                    static_cast<float>(currentTime) / 1000.0f);
        CHECK_GL_ERROR();
        glDisable(GL_BLEND);
        cube.drawArrays();
        win->text.setColor({255, 255, 255, 255});
        win->text.printText_Solid(font, 25.0f, 25.0f, "Press Arrow keys / Page Up Down to move light source Enter to reset");
        win->text.printText_Solid(font, 25.0f, 60.0f, "Press Space to rotate cube");
    }
  
    void event(gl::GLWindow *win, SDL_Event &e) override {
        if (e.type == SDL_KEYDOWN) {
            float moveSpeed = 0.05f; 
            switch (e.key.keysym.sym) {
                case SDLK_LEFT:
                    lightPos.x -= moveSpeed;
                    break;
                case SDLK_RIGHT:
                    lightPos.x += moveSpeed;
                    break;
                case SDLK_UP:
                    lightPos.z -= moveSpeed;
                    break;
                case SDLK_DOWN:
                    lightPos.z += moveSpeed;
                    break;
                case SDLK_PAGEUP:
                    lightPos.y += moveSpeed;
                    break;
                case SDLK_PAGEDOWN:
                    lightPos.y -= moveSpeed;
                    break;
                case SDLK_RETURN:
                    lightPos = glm::vec3(0.0f, 5.0f, 0.0f);
                    break;
                case SDLK_SPACE:
                    if(rot_x >  0) rot_x = 0; else rot_x = 1.0f;
                    break;
            }
            std::cout << "Light Position: " << lightPos.x << ", " << lightPos.y << ", " << lightPos.z << "\n";
        }
    }
private:
    glm::mat4 modelMatrix{1.0f};
    glm::mat4 viewMatrix{1.0f};
    glm::mat4 projectionMatrix{1.0f};
    glm::vec3 cameraPosition{0.0f, 2.0f, 5.0f};
    glm::vec3 lightPos{0.0f, 5.0f, 0.0f};
    float rot_x =  1.0f;
};

class MainWindow : public gl::GLWindow {
public:
    MainWindow(std::string path, int tw, int th) : gl::GLWindow("Transparent Rotating Cube", tw, th) {
        setPath(path);
        setObject(new Cube());
		object->load(this);
    }
    
    ~MainWindow() override {}
    
    virtual void event(SDL_Event &e) override {}

    virtual void draw() override {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        glViewport(0, 0, w, h);

        object->draw(this);
        swap();
    }
private:
};

MainWindow *main_w = nullptr;

void eventProc() {
    main_w->proc();
}

int main(int argc, char **argv) {
#ifdef __EMSCRIPTEN__

    try {
        MainWindow main_window("", 1920, 1080);
        main_w = &main_window;
        emscripten_set_main_loop(eventProc, 0, 1);
    } catch(const mx::Exception &e) {
        mx::system_err << "mx: Exception: " << e.text() << "\n";
        mx::system_err.flush();
        exit(EXIT_FAILURE);
    }   
#else

    Arguments args = proc_args(argc, argv);
    try {
        MainWindow main_window(args.path, args.width, args.height);
        main_window.loop();
    } catch(const mx::Exception &e) {
        mx::system_err << "mx: Exception: " << e.text() << "\n";
        mx::system_err.flush();
        exit(EXIT_FAILURE);
    } 
#endif

    return 0;
}