TerraForge3D  2.3.1
3D Terrain And Landscape Generator
TextureBaker.cpp
1#include "Exporters/TextureBaker.h"
2#include "Data/ApplicationState.h"
3
4#include "imgui/imgui.h"
5
6TextureBaker::TextureBaker(ApplicationState *appState)
7 :appState(appState)
8{
9 previewFrameBuffer = new FrameBuffer(512, 512);
10}
11
12TextureBaker::~TextureBaker()
13{
14 delete previewFrameBuffer;
15}
16
17void TextureBaker::ShowSettings(bool *pOpen)
18{
19 ImGui::Begin("Texture Baker", pOpen);
20
21 if(ImGui::CollapsingHeader("Preview"))
22 {
23 ImGui::Image((ImTextureID)previewFrameBuffer->GetColorTexture(), ImVec2(256, 256));
24 }
25
26 if (ImGui::BeginCombo("Texture Slot##combo", textueBakerSlots[currentTextureSlot]))
27 {
28 for (int i = 0; i < IM_ARRAYSIZE(textueBakerSlots); i++)
29 {
30 bool is_selected = (currentTextureSlot == i);
31 if (ImGui::Selectable(textueBakerSlots[i], is_selected))
32 {
33 currentTextureSlot = i;
34 }
35
36 if (is_selected)
37 ImGui::SetItemDefaultFocus();
38 }
39 ImGui::EndCombo();
40 }
41
42 ImGui::Checkbox("Use Tiled Export", &useTiledExport);
43
44 if(useTiledExport)
45 {
46 ImGui::DragInt("Tile Resolution", &tileResolution);
47 ImGui::DragInt("Tile Count", &tileCount);
48
49 ImGui::InputInt("Tile X", &tileX);
50 ImGui::InputInt("Tile Y", &tileY);
51 }
52 else
53 {
54 ImGui::DragInt("Bake Resolution", &tileResolution);
55 }
56
57 if(currentTextureSlot == 0)
58 {
59 if(ImGui::Button("Calculate Heigt Map Min Max"))
60 {
61 while(appState->states.remeshing);
62 CalculateHeightMapMinMax();
63 }
64 ImGui::DragFloat2("Height Map Min Max", heightMapMinMax, 0.01f);
65 }
66
67 if(ImGui::Button("Bake"))
68 {
69 Bake();
70 }
71
72 ImGui::End();
73
74 Update();
75}
76
77void TextureBaker::CalculateHeightMapMinMax()
78{
79 float min = 10e10;
80 float max = -10e10;
81
82 Vert* vert = appState->models.coreTerrain->mesh->vert;
83 int vertCount = appState->models.coreTerrain->mesh->vertexCount;
84
85 for(int i = 0; i < vertCount; i++)
86 {
87 if(vert[i].position.y < min)
88 {
89 min = vert[i].position.y;
90 }
91 if(vert[i].position.y > max)
92 {
93 max = vert[i].position.y;
94 }
95 }
96
97 heightMapMinMax[0] = min;
98 heightMapMinMax[1] = max;
99
100}
101
102void TextureBaker::Bake()
103{
104 if(bakeFrameBuffer != nullptr)
105 {
106 delete bakeFrameBuffer;
107 }
108
109 if(useTiledExport)
110 {
111 std::string path = ShowSaveFileDialog(".png");
112 if(path.size() <= 3)
113 return;
114 std::string nameBase = "";
115 if(path.find_last_of(".png") == std::string::npos)
116 nameBase = path;
117 else
118 nameBase = path.substr(0, path.find_last_of(".png"));
119
120 if(tileCount < 0)
121 tileCount = -1 * tileCount;
122 if(tileCount == 0)
123 tileCount = 2;
124 if(tileCount % 2 != 0)
125 tileCount += 1;
126
127
128 bakeFrameBuffer = new FrameBuffer(tileResolution, tileResolution);
129
130 std::cout << "Starting to render tiles." << std::endl;
131 for(int i = -1 * tileCount + 1 ; i <= tileCount - 1 ; i+= 2)
132 {
133 for(int j = -1 * tileCount + 1 ; j <= tileCount - 1 ; j+= 2)
134 {
135 tileY = i;
136 tileX = j;
137 std::cout << "Rendering Tile : " << (i + tileCount) << ", " << (j + tileCount) << "\r";
138 bakeFrameBuffer->Begin();
139 glViewport(0, 0, tileResolution, tileResolution);
140 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
141 Render(false);
142 ExportTexture(bakeFrameBuffer->GetRendererID(), nameBase + "_" + std::to_string((i + tileCount)/2) + "_" + std::to_string((j + tileCount)/2) + ".png", tileResolution, tileResolution);
143 std::cout << "Rendered Tile : " << (i + tileCount) / 2 << ", " << (j + tileCount) / 2 << " to " << (nameBase + "_" + std::to_string((i + tileCount)/2) + "_" + std::to_string((j + tileCount)/2) + ".png") << std::endl;
144 }
145
146 }
147
148 glBindFramebuffer(GL_FRAMEBUFFER, 0);
149 delete bakeFrameBuffer;
150 bakeFrameBuffer = nullptr;
151 }
152 else
153 {
154 std::string path = ShowSaveFileDialog(".png");
155 if(path.size() <= 3)
156 return;
157 bakeFrameBuffer = new FrameBuffer(tileResolution, tileResolution);
158 bakeFrameBuffer->Begin();
159 glViewport(0, 0, tileResolution, tileResolution);
160 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
161 Render(false);
162 ExportTexture(bakeFrameBuffer->GetRendererID(), path, tileResolution, tileResolution);
163 glBindFramebuffer(GL_FRAMEBUFFER, 0);
164 delete bakeFrameBuffer;
165 bakeFrameBuffer = nullptr;
166 }
167}
168
169void TextureBaker::Update()
170{
171 previewFrameBuffer->Begin();
172 glViewport(0, 0, previewFrameBuffer->GetWidth(), previewFrameBuffer->GetHeight());
173 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
174 Render(true);
175 glBindFramebuffer(GL_FRAMEBUFFER, 0);
176}
177
178void TextureBaker::Render(bool isPreview)
179{
180 textureBakerCamera = appState->cameras.main;
181 textureBakerCamera.aspect = 1.0f;
182 textureBakerCamera.position[0] = textureBakerCamera.position[1] = textureBakerCamera.position[2] = 0.0f;
183 textureBakerCamera.position[2] = 1.0f;
184 textureBakerCamera.rotation[0] = textureBakerCamera.rotation[1] = textureBakerCamera.rotation[2] = 0.0f;
185 textureBakerCamera.perspective = false;
186 textureBakerCamera.UpdateCamera();
187
188 float tmp[3];
189
190 if(isPreview)
191 {
192 tmp[0] = tmp[1] = 512.0f;
193 }
194 else
195 {
196 tmp[0] = tileResolution;
197 tmp[1] = tileResolution;
198 }
199
200 tmp[2] = 1.0f;
201
202 Shader* shader = appState->shaders.terrain;
203 shader->Bind();
204 shader->SetMPV(textureBakerCamera.pv);
205 shader->SetUniformMat4("_Model", appState->models.coreTerrain->modelMatrix);
206 shader->SetLightCol(appState->lightManager->color);
207 shader->SetLightPos(appState->lightManager->position);
208 shader->SetUniform3f("_Resolution", tmp);
209 shader->SetUniform3f("_CameraPos", appState->cameras.main.position);
210 shader->SetUniform3f("_HMapMinMax", heightMapMinMax);
211 shader->SetUniformf("_SeaLevel", appState->seaManager->level);
212 shader->SetUniformf("_Scale", appState->globals.scale);
213 shader->SetUniformf("_TextureBake", 1.0f);
214 shader->SetUniformf("_CameraNear", appState->cameras.main.cNear);
215 shader->SetUniformf("_CameraFar", appState->cameras.main.cFar);
216 shader->SetUniformf("_Slot", static_cast<float>(currentTextureSlot));
217 shader->SetUniformf("_Tiled", useTiledExport ? 1.0f : 0.0f);
218 shader->SetUniformf("_NumTiles", static_cast<float>(tileCount));
219 shader->SetUniformf("_TileX", static_cast<float>(-1 * tileX));
220 shader->SetUniformf("_TileY", static_cast<float>(-1 * tileY));
221 appState->shadingManager->UpdateShaders();
222 appState->models.coreTerrain->Render();
223}
224
225nlohmann::json TextureBaker::Save()
226{
227 nlohmann::json data;
228 data["type"] = "TextureBaker";
229 data["useTiledExport"] = useTiledExport;
230 data["tileResolution"] = tileResolution;
231 data["tileCount"] = tileCount;
232 // data["autoCalculateHeightMapMinMax"] = autoCalculateHeightMapMinMax;
233 data["heightMapMinMax.x"] = heightMapMinMax[0];
234 data["heightMapMinMax.y"] = heightMapMinMax[1];
235 data["currentTextureSlot"] = currentTextureSlot;
236
237 return data;
238}
239
240void TextureBaker::Load(nlohmann::json data)
241{
242 useTiledExport = data["useTiledExport"];
243 tileResolution = data["tileResolution"];
244 tileCount = data["tileCount"];
245 // autoCalculateHeightMapMinMax = data["autoCalculateHeightMapMinMax"];
246 heightMapMinMax[0] = data["heightMapMinMax.x"];
247 heightMapMinMax[1] = data["heightMapMinMax.y"];
248 currentTextureSlot = data["currentTextureSlot"];
249}
Definition: Shader.h:7
a class to store JSON values
Definition: json.hpp:17860
Definition: Mesh.h:13