1#ifndef STB_IMAGE_WRITE_IMPLEMENTATION 
    2#define STB_IMAGE_WRITE_IMPLEMENTATION 
    5#include "VolumeTextureGenerator.h" 
    6#include "../../../OGLDef.h" 
    7#include "../../GLProgramHandle.h" 
    8#include "../../Render/GLMeshID.h" 
    9#include "../../Render/SMaterial.h" 
   10#include "../../Render/ShaderUtil.h" 
   11#include "../../Render/SEnvironmentMgr.h" 
   12#include "../../Render/STexture.h" 
   13#include "../../Loader/STB/stb_image_write.h" 
   14#include "../../AssetsDef.h" 
   18CSE::VolumeTextureGenerator::VolumeTextureGenerator() {
 
   19    m_handle = SResource::Create<GLProgramHandle>(
"File:Shader/SDF/ModelGenerator.shader");
 
   22CSE::VolumeTextureGenerator::~VolumeTextureGenerator() {
 
   25void CSE::VolumeTextureGenerator::SetupFramebuffer(
unsigned int& captureFBO, 
unsigned int& captureRBO, 
unsigned int& tex, 
unsigned int tex2d_size) {
 
   26    glGenRenderbuffers(1, &captureRBO);
 
   27    glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
 
   28    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, tex2d_size, tex2d_size);
 
   30    glGenFramebuffers(1, &captureFBO);
 
   31    glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
 
   32    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO);
 
   34    glGenTextures(1, &tex);
 
   35    glBindTexture(GL_TEXTURE_2D, tex);
 
   36    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex2d_size, tex2d_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 
   37    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 
   38    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
   39    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
   40    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
   42    glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
 
   43    glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
 
   44    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, tex2d_size, tex2d_size);
 
   45    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
 
   48void CSE::VolumeTextureGenerator::ProcessAxisRender(
unsigned int level, 
const GLMeshID& mesh, 
GLProgramHandle* handle, 
unsigned char* data, 
const CSE::mat4& view, 
const std::function<
int(
int, 
int, 
int, 
int)>& indexCalculator) {
 
   49    int size = level * level;
 
   50    unsigned int tex2d_size = size * level;
 
   52    if(handle->Uniforms.ViewMatrix >= 0)
 
   53        glUniformMatrix4fv(handle->Uniforms.ViewMatrix, 1, 0, view.Pointer());
 
   54    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   55    Render(level, mesh, handle);
 
   57    glViewport(0, 0, tex2d_size, tex2d_size);
 
   58    auto data_y = CaptureBuffer();
 
   59    const int file_size = tex2d_size * tex2d_size * 4;
 
   61    for (
int i = 0; i < file_size; i += 4) {
 
   62        unsigned char cur_alpha = data_y[i + 3];
 
   65        int y = (index / tex2d_size) % size;
 
   66        int z = (int)(index / size) % level + (index / (tex2d_size * size)) * level;
 
   68        int data_index = indexCalculator(level, x, y, z);
 
   71        if(data[data_index] <= 0)     data[data_index] = data_y[i];
 
   72        if(data[data_index + 1] <= 0) data[data_index + 1] = data_y[i + 1];
 
   73        if(data[data_index + 2] <= 0) data[data_index + 2] = data_y[i + 2];
 
   74        if(data[data_index + 3] <= 0) data[data_index + 3] = data_y[i + 3];
 
   80void CSE::VolumeTextureGenerator::GenerateVolumeTexture(
unsigned int level, 
const GLMeshID& mesh, 
const SMaterial& material) {
 
   81    unsigned int captureFBO, captureRBO, tex;
 
   82    int size = level * level;
 
   83    unsigned int tex2d_size = size * level;
 
   85    glDisable(GL_CULL_FACE);
 
   87    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
   89    SetupFramebuffer(captureFBO, captureRBO, tex, tex2d_size);
 
   91    const auto& handle = m_handle;
 
   92    mat4 view = mat4::Identity();
 
   93    glUseProgram(handle->Program);
 
   95    material.AttachElement(0);
 
   96    auto albedo_tex = handle->UniformLocation(
"texture.albedo");
 
   97    if(albedo_tex != 
nullptr && albedo_tex->id >= 0) {
 
   98        const auto& e = material.GetElement(
"texture.albedo");
 
  100            STexture* tex_resource = SResource::Get<STexture>(e->valueStr[0]);
 
  101            tex_resource->Bind(albedo_tex->id, 0);
 
  105    if(handle->Uniforms.ViewMatrix >= 0)
 
  106        glUniformMatrix4fv(handle->Uniforms.ViewMatrix, 1, 0, view.Pointer());
 
  108    glClearColor(0, 0, 0, 0);
 
  109    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
  110    Render(level, mesh, handle);
 
  112    unsigned char* data = 
new unsigned char[tex2d_size * tex2d_size * 4] {0};
 
  115    view = mat4::RotateY(180.f);
 
  116    ProcessAxisRender(level, mesh, handle, data, view, [=](
int level, 
int x, 
int y, 
int z) {
 
  117        return GetIndex(level, size - x, y, z / 2 + size / 4);
 
  121    view = mat4::RotateX(90.f);
 
  122    ProcessAxisRender(level, mesh, handle, data, view, [=](
int level, 
int x, 
int y, 
int z) {
 
  123        return GetIndex(level, x, z / 2 + size / 4, y);
 
  127    view = mat4::RotateY(-90.f);
 
  128    ProcessAxisRender(level, mesh, handle, data, view, [=](
int level, 
int x, 
int y, 
int z) {
 
  129        return GetIndex(level, z / 2 + size / 4, y, x);
 
  132    std::string save_str = CSE::AssetsPath() + 
"test" + 
".png";
 
  133    SavePng(save_str.c_str(), tex2d_size, tex2d_size, 4, data);
 
  135    glEnable(GL_CULL_FACE);
 
  137    glDeleteFramebuffers(1, &captureFBO);
 
  138    glDeleteRenderbuffers(1, &captureRBO);
 
  142int CSE::VolumeTextureGenerator::GetIndex(
int level, 
int x, 
int y, 
int z) {
 
  143    int size = level * level;
 
  144    int tex2d_size = size * level;
 
  145    ivec2 offset = 
ivec2{ (z % level), (z / level) };
 
  146    int result = z * size * size + y * size + x;
 
  152    int size = level * level;
 
  153    const auto& max_distance = mesh.m_maxSize + mesh.m_maxSize;
 
  154    const auto half_distance = max_distance / 2.f;
 
  155    const auto step = max_distance / size;
 
  157    for(
unsigned int i = 0; i < size; ++i) {
 
  158        glViewport((i % level) * size, (i / level) * size, size, size);
 
  159        mat4 projection = mat4::Ortho(-max_distance, max_distance,
 
  160                                      -max_distance, max_distance,
 
  161                                      -half_distance + i * step, -half_distance + (i + 1.f) * step);
 
  163        if(handle->Uniforms.ProjectionMatrix >= 0)
 
  164            glUniformMatrix4fv(handle->Uniforms.ProjectionMatrix, 1, 0, projection.Pointer());
 
  170unsigned char* CSE::VolumeTextureGenerator::CaptureBuffer() {
 
  172    glGetIntegerv(GL_VIEWPORT, viewport);
 
  176    int width = viewport[2];
 
  177    int height = viewport[3];
 
  179    unsigned char* data = 
new unsigned char[width * height * 4];
 
  182    glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
  183    glReadBuffer(GL_COLOR_ATTACHMENT0);
 
  184    glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
 
  189int CSE::VolumeTextureGenerator::SavePng(
const char* filename, 
int width, 
int height, 
int chennel, 
void* data) {
 
  190    int saved = stbi_write_png(filename, width, height, chennel, data, 0);
 
static void BindAttributeToShader(const GLProgramHandle &handle, const GLMeshID &meshId)
Binds the attributes to the shader.