CSEngine
Loading...
Searching...
No Matches
VolumeTextureGenerator.cpp
1#ifndef STB_IMAGE_WRITE_IMPLEMENTATION
2#define STB_IMAGE_WRITE_IMPLEMENTATION
3#endif
4
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"
15
16using namespace CSE;
17
18CSE::VolumeTextureGenerator::VolumeTextureGenerator() {
19 m_handle = SResource::Create<GLProgramHandle>("File:Shader/SDF/ModelGenerator.shader");
20}
21
22CSE::VolumeTextureGenerator::~VolumeTextureGenerator() {
23}
24
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);
29
30 glGenFramebuffers(1, &captureFBO);
31 glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
32 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO);
33
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);
41
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);
46}
47
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;
51
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);
56
57 glViewport(0, 0, tex2d_size, tex2d_size);
58 auto data_y = CaptureBuffer();
59 const int file_size = tex2d_size * tex2d_size * 4;
60
61 for (int i = 0; i < file_size; i += 4) {
62 unsigned char cur_alpha = data_y[i + 3];
63 int index = i / 4;
64 int x = index % size;
65 int y = (index / tex2d_size) % size;
66 int z = (int)(index / size) % level + (index / (tex2d_size * size)) * level;
67
68 int data_index = indexCalculator(level, x, y, z);
69 data_index *= 4;
70
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];
75 }
76
77 delete[] data_y;
78}
79
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;
84
85 glDisable(GL_CULL_FACE);
86 glEnable(GL_BLEND);
87 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
88
89 SetupFramebuffer(captureFBO, captureRBO, tex, tex2d_size);
90
91 const auto& handle = m_handle;
92 mat4 view = mat4::Identity();
93 glUseProgram(handle->Program);
94
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");
99 if(e != nullptr) {
100 STexture* tex_resource = SResource::Get<STexture>(e->valueStr[0]);
101 tex_resource->Bind(albedo_tex->id, 0);
102 }
103 }
104
105 if(handle->Uniforms.ViewMatrix >= 0)
106 glUniformMatrix4fv(handle->Uniforms.ViewMatrix, 1, 0, view.Pointer());
107
108 glClearColor(0, 0, 0, 0);
109 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
110 Render(level, mesh, handle);
111
112 unsigned char* data = new unsigned char[tex2d_size * tex2d_size * 4] {0};
113
114 // X axis Render
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);
118 });
119
120 // Y axis Render
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);
124 });
125
126 // Z axis Render
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);
130 });
131
132 std::string save_str = CSE::AssetsPath() + "test" + ".png";
133 SavePng(save_str.c_str(), tex2d_size, tex2d_size, 4, data);
134
135 glEnable(GL_CULL_FACE);
136 glDisable(GL_BLEND);
137 glDeleteFramebuffers(1, &captureFBO);
138 glDeleteRenderbuffers(1, &captureRBO);
139 delete[] data;
140}
141
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;
147// int result = (offset.x * size) + (offset.y * tex2d_size * size) + x + y * tex2d_size;
148 return result;
149}
150
151void CSE::VolumeTextureGenerator::Render(int level, const GLMeshID& mesh, GLProgramHandle* handle) {
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;
156
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);
162// -100, 100);
163 if(handle->Uniforms.ProjectionMatrix >= 0)
164 glUniformMatrix4fv(handle->Uniforms.ProjectionMatrix, 1, 0, projection.Pointer());
165
167 }
168}
169
170unsigned char* CSE::VolumeTextureGenerator::CaptureBuffer() {
171 GLint viewport[4];
172 glGetIntegerv(GL_VIEWPORT, viewport);
173
174 int x = viewport[0];
175 int y = viewport[1];
176 int width = viewport[2];
177 int height = viewport[3];
178
179 unsigned char* data = new unsigned char[width * height * 4];
180
181
182 glPixelStorei(GL_PACK_ALIGNMENT, 1);
183 glReadBuffer(GL_COLOR_ATTACHMENT0);
184 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
185
186 return data;
187}
188
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);
191 return saved;
192}
static void BindAttributeToShader(const GLProgramHandle &handle, const GLMeshID &meshId)
Binds the attributes to the shader.