PeriDyno 1.0.0
Loading...
Searching...
No Matches
Envmap.cpp
Go to the documentation of this file.
1#include "Envmap.h"
3
4#include <glad/glad.h>
5
6#define STB_IMAGE_IMPLEMENTATION
7#include <stb/stb_image.h>
8
9#include <glm/gtc/matrix_transform.hpp>
10
11#include "envmap.vert.h"
12#include "envmap.frag.h"
13#include "screen.vert.h"
14#include "brdf.frag.h"
15
16using namespace dyno;
17
19{
20 image.tex.format = GL_RGB;
21 image.tex.internalFormat = GL_RGB32F;
22}
23
25{
26
27}
28
30{
31 image.tex.format = GL_RGB;
32 image.tex.internalFormat = GL_RGB32F;
33 image.tex.type = GL_FLOAT;
34 image.tex.maxFilter = GL_LINEAR;
35 image.tex.minFilter = GL_LINEAR_MIPMAP_LINEAR; // produce seam artifacts...
36 image.tex.create();
37 // wrapping
38 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
39 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
40
41 // initialize cubemaps
42 irradianceCube.create();
43 irradianceCube.bind();
44 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
45 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
46 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
47 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
48 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
49 for (unsigned int i = 0; i < 6; ++i) {
50 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, irradianceSize, irradianceSize, 0,
51 GL_RGB, GL_FLOAT, nullptr);
52 }
53 prefilteredCube.create();
54 prefilteredCube.bind();
55 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
56 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
57 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
58 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
59 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
60
61 for (unsigned int i = 0; i < 6; ++i) {
62 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, prefilteredSize, prefilteredSize, 0,
63 GL_RGB, GL_FLOAT, nullptr);
64 }
65 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
67
68
69 brdfLut.format = GL_RG;
70 brdfLut.internalFormat = GL_RG16F;
71 brdfLut.type = GL_FLOAT;
72 brdfLut.create();
73 brdfLut.bind();
74 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
77
79
80 cube = Mesh::Cube();
81
82 uboParams.create(GL_UNIFORM_BUFFER, GL_STATIC_DRAW);
83
84 // create programs
86 ENVMAP_VERT, sizeof(ENVMAP_VERT),
87 ENVMAP_FRAG, sizeof(ENVMAP_FRAG));
88
89 fb.create();
90
91 genLUT();
92}
93
95{
96 fb.release();
97
98 image.tex.release();
99
100 irradianceCube.release();
101 prefilteredCube.release();
102 brdfLut.release();
103
104 cube->release();
105 delete cube;
106
107 prog->release();
108 delete prog;
109
110 uboParams.release();
111}
112
113void Envmap::load(const char* path)
114{
115 this->path = path;
116 this->requireUpdate = true;
117
118 if (this->path) {
119 float* data = stbi_loadf(path, &image.width, &image.height, &image.component, 3);
120
121 if (data) {
122 // copy
123 int size = image.width * image.height * image.component;
124 image.data.resize(size);
125 memcpy(image.data.data(), data, size * sizeof(float));
126 stbi_image_free(data);
127 return;
128 }
129 }
130
131 // failed to load envmap...
132 this->path = 0;
133}
134
135void Envmap::draw(const RenderParams& rparams)
136{
137 if (this->path) {
138 if (requireUpdate) {
139 // update envmap
140 this->update();
141 this->requireUpdate = false;
142 }
143
144 glm::mat4 mvp =
145 rparams.transforms.proj *
146 glm::mat4(glm::mat3(rparams.transforms.view));
147
148 prog->use();
149 prog->setInt("mode", 0);
150
151 // set transform
152 GLuint mvpLoc = glGetUniformLocation(prog->id, "mvp");
153 glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &mvp[0][0]);
154
155 // bind texture
156 image.tex.bind(GL_TEXTURE1);
157 cube->draw();
158
159 glClear(GL_DEPTH_BUFFER_BIT);
160 }
161}
162
164{
165 if (this->path) {
166 if (requireUpdate) {
167 // update envmap
168 this->update();
169 this->requireUpdate = false;
170 }
171
172 //glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
173 irradianceCube.bind(GL_TEXTURE7);
174 prefilteredCube.bind(GL_TEXTURE8);
175 brdfLut.bind(GL_TEXTURE9);
176
177 uboParams.load(&params, sizeof(params));
178 uboParams.bindBufferBase(6);
179 glCheckError();
180 }
181}
182
184{
185 params.scale = scale;
186}
187
189{
190 image.tex.load(image.width, image.height, image.data.data());
191 image.tex.genMipmap();
192 glCheckError();
193
194 // preserve current framebuffer
195 GLint fbo;
196 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
197 GLint vp[4];
198 glGetIntegerv(GL_VIEWPORT, vp);
199
200 const glm::mat4 proj = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f);
201 //glm::mat4 proj = glm::perspective(90.0f, 1.0f, 0.1f, 10.0f);
202 const glm::mat4 views[] =
203 {
204 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
205 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
206 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
207 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)),
208 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
209 proj * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f))
210 };
211
212 fb.bind();
213 //const GLuint attachments = GL_COLOR_ATTACHMENT0;
214 //fb.drawBuffers(1, &attachments);
215 image.tex.bind(GL_TEXTURE1);
216 const GLuint mvpLoc = glGetUniformLocation(prog->id, "mvp");
217
218 // irradiance
219 prog->use();
220 prog->setInt("mode", 1);
221 glViewport(0, 0, irradianceSize, irradianceSize);
222 for (int i = 0; i < 6; i++) {
223 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
224 GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceCube.id, 0);
225 glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &views[i][0][0]);
226 cube->draw();
227 }
228
229 prog->setInt("mode", 2);
230 // prefiltered envmap
231 const int maxMipLevels = 5;
232 for (int mip = 0; mip < maxMipLevels; mip++) {
233 float roughness = float(mip) / float(maxMipLevels - 1);
234 int size = prefilteredSize >> mip;
235 prog->setFloat("roughness", roughness);
236 glViewport(0, 0, size, size);
237 for (int i = 0; i < 6; i++) {
238 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
239 GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilteredCube.id, mip);
240 glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &views[i][0][0]);
241 cube->draw();
242 }
243 }
244
245 // recover
246 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
247 glViewport(vp[0], vp[1], vp[2], vp[3]);
248 glCheckError();
249}
250
252{
253 auto brdfProgram = Program::createProgramSPIRV(
254 SCREEN_VERT, sizeof(SCREEN_VERT),
255 BRDF_FRAG, sizeof(BRDF_FRAG));
256
257 auto quad = Mesh::ScreenQuad();
258 brdfProgram->use();
259
260
261 // preserve current framebuffer
262 GLint fbo;
263 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
264
265 fb.bind();
266 fb.setTexture(GL_COLOR_ATTACHMENT0, &brdfLut);
267
268 glViewport(0, 0, brdfLutSize, brdfLutSize);
269 quad->draw();
270 glCheckError();
271
272 //fb.unbind();
273 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
274
275 quad->release();
276 delete quad;
277 brdfProgram->release();
278 delete brdfProgram;
279}
#define glCheckError()
void initialize()
Definition Envmap.cpp:29
struct dyno::Envmap::@233363266166374305147231242227134211245233355301 params
bool requireUpdate
Definition Envmap.h:36
void genLUT()
Definition Envmap.cpp:251
Mesh * cube
Definition Envmap.h:58
TextureCube prefilteredCube
Definition Envmap.h:47
Framebuffer fb
Definition Envmap.h:60
void update()
Definition Envmap.cpp:188
const int prefilteredSize
Definition Envmap.h:51
struct dyno::Envmap::@174122021220304153277233053023122306224165314251 image
void load(const char *path)
Definition Envmap.cpp:113
Program * prog
Definition Envmap.h:55
void setScale(float scale)
Definition Envmap.cpp:183
std::vector< float > data
Definition Envmap.h:42
const int brdfLutSize
Definition Envmap.h:52
Texture2D brdfLut
Definition Envmap.h:48
TextureCube irradianceCube
Definition Envmap.h:46
void bindIBL()
Definition Envmap.cpp:163
void release()
Definition Envmap.cpp:94
const int irradianceSize
Definition Envmap.h:50
const char * path
Definition Envmap.h:33
float scale
Definition Envmap.h:63
void draw(const RenderParams &rparams)
Definition Envmap.cpp:135
Buffer uboParams
Definition Envmap.h:65
static Mesh * Cube()
Definition Mesh.cpp:177
static Mesh * ScreenQuad()
Definition Mesh.cpp:134
static Program * createProgramSPIRV(const void *vs, size_t vs_len, const void *fs, size_t fs_len, const void *gs=0, size_t gs_len=0)
Definition Shader.cpp:202
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
struct dyno::RenderParams::Transform transforms