Skip to content

File SDFField.cpp

File List > scene > SDFField.cpp

Go to the documentation of this file

#include "SDFField.h"
#include "xdz_math.h"
#include "macros.h"

#include "shaders/ComputeShader.h"

ChainedShader SDFField::sdf_shader = {};

SDFField::SDFField()
{

}

// width: x-axis, depth: y-axis, height: z-axis
SDFField::SDFField(GLuint width, GLuint height, GLuint depth)
    : sdf_width(width), sdf_depth(depth), sdf_height(height)
{
    o_type = GO_SDFFIELD;
    o_name = "SDF Field";

    sdf_data = StorageBuffer(FLOAT_LIST, 6);
    sdf_shader = ChainedShader::ImportShader("Empty.vert", "SDF_Construct.geom", "Empty.frag");

    ResetBuffer();
}

SDFField::~SDFField()
{

}

void SDFField::ResetBuffer()
{
    assert(sdf_width * sdf_depth * sdf_height > 0);

    std::vector<GLuint> buffer(sdf_width * sdf_depth * sdf_height, 999);
    SDFInfo info(o_position, o_scale, glm::vec3{ sdf_width, sdf_depth, sdf_height }, sdf_subdiv);

    sdf_data.GenStorageBuffers(info, buffer);
}

void SDFField::ResetDistance()
{
    static ComputeShader& reset_distance = ComputeShader::ImportShader("Reset_Distance", Uni("default_dist", 999.0f));
    reset_distance.UseShader();
    reset_distance.RunComputeShader(sdf_width, sdf_depth, sdf_height);
    reset_distance.UnuseShader();
}

// width: x-axis, depth: y-axis, height: z-axis
void SDFField::Resize(GLuint width, GLuint depth, GLuint height)
{
    sdf_width = width;
    sdf_depth = depth;
    sdf_height = height;

    ResetBuffer();
}

void SDFField::Bind(GLuint _base /*= -1*/)
{
    if (_base != -1)
        sdf_data.SetBufferBase(_base);

    sdf_data.BindBufferBase();
}

void SDFField::Unbind()
{
    sdf_data.UnbindBuffer();
}

void SDFField::BindShader()
{
    sdf_shader.UseShader();
    sdf_shader.SetValue("U_offset", glm::vec3(0));
}

void SDFField::BindTargetTrans(const glm::mat4& _trans, bool _is_closure)
{
    sdf_shader.SetValue("U_model", _trans);
    sdf_shader.SetValue("U_closure", (int)_is_closure);
}

void SDFField::UnbindShader()
{
    sdf_shader.UnuseShader();
}

void SDFField::Subdivide(GLuint _iter)
{
    assert(_iter > 0);

    sdf_subdiv = _iter;

    LOOP(_iter) {

    }

    ResetBuffer();
}

std::vector<float> SDFField::ReadSDF()
{
    assert(sdf_width * sdf_depth * sdf_height > 0);

    std::vector<float> result(sdf_width * sdf_depth * sdf_height);
    sdf_data.ReadStorageBuffer(result, sizeof(SDFInfo));

    return result;
}

float SDFField::ReadSDFAt(GLuint x, GLuint y, GLuint z)
{
    return -1;
}

void SDFField::LoadSDF(const std::vector<float>& _data)
{

}

GLuint SDFField::GetSDFIndex(GLuint x, GLuint y, GLuint z)
{
    return x + y * sdf_width + z * sdf_depth * sdf_width;
}

void SDFField::RenderSDF(const Camera* cam)
{

}


GLuint FloatFlip3(float fl)
{
    GLuint f = *(GLuint*)(&fl);
    return (f << 1) | (f >> 31);        //Rotate sign bit to least significant
}
float IFloatFlip3(GLuint f2)
{
    GLuint u = (f2 >> 1) | (f2 << 31);
    return *(float*)(&u);
}
void SDFField::SDFLinearGrad()
{

}

void SDFField::SDFRadialGrad()
{
    std::vector<GLuint> buffer(sdf_width * sdf_depth * sdf_height);
    SDFInfo info(o_position, o_scale, glm::vec3{ sdf_width, sdf_depth, sdf_height }, sdf_subdiv);

    LOOP_N(sdf_width, x) {
        LOOP_N(sdf_depth, y) {
            LOOP_N(sdf_height, z) {
                GLuint index = GetSDFIndex(x, y, z);
                glm::vec3 center = 0.5f * info.size - 0.5f;
                glm::vec3 dir = glm::vec3(x, y, z) - center;
                buffer.data()[index] = FloatFlip3(glm::length(dir) / glm::length(center));
            }
        }
    }

    sdf_data.GenStorageBuffers(info, buffer);
}