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.