terrain-gen/src/skybox.cpp

176 lines
4.8 KiB
C++

#include "skybox.h"
SkyBox::SkyBox(GLsizei resolution): m_resolution(resolution)
{
}
SkyBox::~SkyBox()
{
glDeleteVertexArrays(1, &m_vao);
glDeleteBuffers(1, &m_vbo);
glDeleteTextures(1, &m_textureId);
}
void SkyBox::initGl(Shader* program)
{
initializeOpenGLFunctions();
m_program = program;
glGenBuffers(1, &m_vbo);
glGenVertexArrays(1, &m_vao);
int locationPos = m_program->attributeLocation("in_position");
loadMesh();
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(GLuint(locationPos), 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(0));
glEnableVertexAttribArray(GLuint(locationPos));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glGenTextures(1, &m_textureId);
QTime t;
t.start();
qDebug() << "Generating skybox...";
generateCubeMap();
qDebug() << "Skybox generated in" << t.elapsed() / 1000.f << "s";
}
void SkyBox::generateCubeMap() {
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_textureId);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (GLuint i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, m_resolution, m_resolution, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
}
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureId, 0);
GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawBuffers);
Shader skyboxShader("nightsky", true);
skyboxShader.bind();
QMatrix4x4 projection;
projection.perspective(90, 1, 0.01f, 100);
QMatrix4x4 viewProjection[6];
GLfloat matArray[6 * 16];
viewProjection[0].lookAt(QVector3D(0,0,0), QVector3D(1,0,0), QVector3D(0, -1, 0));
viewProjection[1].lookAt(QVector3D(0,0,0), QVector3D(-1, 0, 0), QVector3D(0, -1, 0));
viewProjection[2].lookAt(QVector3D(0,0,0), QVector3D(0, 1, 0), QVector3D(0, 0, 1));
viewProjection[3].lookAt(QVector3D(0,0,0), QVector3D(0, -1, 0), QVector3D(0, 0, -1));
viewProjection[4].lookAt(QVector3D(0,0,0), QVector3D(0, 0, 1), QVector3D(0, -1, 0));
viewProjection[5].lookAt(QVector3D(0,0,0), QVector3D(0, 0, -1), QVector3D(0, -1, 0));
for (int i = 0; i < 6; i++) {
viewProjection[i] = projection * viewProjection[i];
for (int j = 0; j < 16; j++) {
matArray[i * 16 + j] = viewProjection[i].data()[j];
}
}
glUniformMatrix4fv(skyboxShader.uniformLocation("u_viewProjection"), 6, false, matArray);
glViewport(0, 0, m_resolution, m_resolution);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, GLsizei(3 * 12));
glBindVertexArray(0);
skyboxShader.release();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
}
void SkyBox::loadMesh()
{
GLfloat vertices[] = {
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
};
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER,
GLsizei(9 * 12 * sizeof(GLfloat)),
vertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void SkyBox::render()
{
//glDisable(GL_DEPTH_TEST);
m_program->setTexture("skyTexture", GL_TEXTURE0, m_textureId, GL_TEXTURE_CUBE_MAP);
m_program->bind();
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, GLsizei(3 * 12));
glBindVertexArray(0);
m_program->release();
//glEnable(GL_DEPTH_TEST);
}