3 #include <glm/gtc/type_ptr.hpp>
5 Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") {
6 Program equiProg("equirectangularvert.glsl", "equirectangularfrag.glsl");
7 glUseProgram(equiProg.progId);
10 glGenTextures(1, &equiTexId);
11 glBindTexture(GL_TEXTURE_2D, equiTexId);
13 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_SHORT, (unsigned short*)img.data());
15 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
16 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
17 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
18 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
20 // generate framebuffers to store cubemap in
21 GLuint captureFBO, captureRBO;
22 glGenFramebuffers(1, &captureFBO);
23 glGenRenderbuffers(1, &captureRBO);
25 glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
26 glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
27 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512);
28 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureFBO);
30 // generate and setup cubemap texture
31 glGenTextures(1, &texId);
32 glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
33 for (GLuint i = 0; i < 6; i++)
34 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr);
35 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
36 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
37 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
38 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
39 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
41 // generate cube to render
42 glGenVertexArrays(1, &vao);
43 glBindVertexArray(vao);
46 glGenBuffers(1, &vbo);
48 auto vertices = cube();
50 glBindBuffer(GL_ARRAY_BUFFER, vbo);
51 glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
53 GLuint posLoc = glGetAttribLocation(program.progId, "pos");
54 glEnableVertexAttribArray(posLoc);
55 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
58 glm::mat4 captureProj = glm::perspective(glm::radians(90.f), 1.f, 0.1f, 10.f);
59 glm::mat4 captureViews[] = {
60 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 1, 0, 0), glm::vec3(0, -1, 0)),
61 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(-1, 0, 0), glm::vec3(0, -1, 0)),
62 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 1, 0), glm::vec3(0, 0, 1)),
63 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, -1, 0), glm::vec3(0, 0, -1)),
64 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 0, 1), glm::vec3(0, -1, 0)),
65 glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 0, -1), glm::vec3(0, -1, 0))
68 glUniform1i(glGetUniformLocation(equiProg.progId, "equirectangularMap"), 0);
69 glUniformMatrix4fv(glGetUniformLocation(equiProg.progId, "projection"), 1, GL_FALSE, glm::value_ptr(captureProj));
70 glActiveTexture(GL_TEXTURE0);
71 glBindTexture(GL_TEXTURE_2D, equiTexId);
73 glViewport(0, 0, 512, 512);
74 glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
75 for (GLuint i = 0; i < 6; i++) {
76 glUniformMatrix4fv(glGetUniformLocation(equiProg.progId, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i]));
77 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, texId, 0);
78 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
79 glDrawArrays(GL_TRIANGLES, 0, 36);
83 // switch back to regular skybox shader
84 glUseProgram(program.progId);
85 glDepthFunc(GL_LEQUAL);
87 glGenVertexArrays(1, &vao);
88 glBindVertexArray(vao);
90 glGenBuffers(1, &vbo);
92 // reverse so facing inside out
93 std::reverse(vertices.begin(), vertices.end());
95 glBindBuffer(GL_ARRAY_BUFFER, vbo);
96 glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
98 posLoc = glGetAttribLocation(program.progId, "pos");
99 glEnableVertexAttribArray(posLoc);
100 glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
102 // restore default framebuffer
103 glBindFramebuffer(GL_FRAMEBUFFER, 0);
106 void Skybox::draw(glm::mat4 proj, glm::mat4 view) const {
107 glUseProgram(program.progId);
109 glBindVertexArray(vao);
111 GLuint projLoc = glGetUniformLocation(program.progId, "projection");
112 glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
114 GLuint viewLoc = glGetUniformLocation(program.progId, "view");
115 view = glm::mat4(glm::mat3(view));
116 glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
118 glActiveTexture(GL_TEXTURE0);
119 glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
120 glDrawArrays(GL_TRIANGLES, 0, 36);
122 if (glGetError()) exit(1);
125 GLuint Skybox::getTexture() const {