Use cubemap for skyboxes

This commit is contained in:
Vincent Lejeune 2014-02-26 18:36:41 +01:00
parent 4d6b110e56
commit 61ea376ff2
5 changed files with 96 additions and 3 deletions

View File

@ -1171,7 +1171,9 @@ scene::ISceneNode *IrrDriver::addSkyDome(video::ITexture *texture,
scene::ISceneNode *IrrDriver::addSkyBox(const std::vector<video::ITexture*>
&texture)
{
assert(texture.size() == 6);
SkyboxTextures = texture;
SkyboxCubeMap = 0;
return m_scene_manager->addSkyBoxSceneNode(texture[0], texture[1],
texture[2], texture[3],
texture[4], texture[5]);
@ -1180,6 +1182,8 @@ scene::ISceneNode *IrrDriver::addSkyBox(const std::vector<video::ITexture*>
void IrrDriver::suppressSkyBox()
{
SkyboxTextures.clear();
glDeleteTextures(1, &SkyboxCubeMap);
SkyboxCubeMap = 0;
}
// ----------------------------------------------------------------------------

View File

@ -115,6 +115,8 @@ private:
core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_InvProjViewMatrix;
std::vector<video::ITexture *> SkyboxTextures;
GLuint SkyboxCubeMap;
/** Flag to indicate if a resolution change is pending (which will be
* acted upon in the next update). None means no change, yes means
@ -225,6 +227,7 @@ public:
~IrrDriver();
void initDevice();
void reset();
void generateSkyboxCubemap();
void renderSkybox();
void setPhase(STKRenderingPass);
STKRenderingPass getPhase() const;

View File

@ -918,6 +918,47 @@ static void createcubevao()
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
}
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
void IrrDriver::generateSkyboxCubemap()
{
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glGenTextures(1, &SkyboxCubeMap);
GLint w = 0, h = 0;
for (unsigned i = 0; i < 6; i++)
{
w = MAX2(w, SkyboxTextures[i]->getOriginalSize().Width);
h = MAX2(h, SkyboxTextures[i]->getOriginalSize().Height);
}
const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 };
char *rgba = new char[w * h * 4];
for (unsigned i = 0; i < 6; i++)
{
unsigned idx = texture_permutation[i];
video::IImage* image = getVideoDriver()->createImageFromData(
SkyboxTextures[idx]->getColorFormat(),
SkyboxTextures[idx]->getSize(),
SkyboxTextures[idx]->lock(),
false
);
SkyboxTextures[idx]->unlock();
image->copyToScaling(rgba, w, h);
glBindTexture(GL_TEXTURE_CUBE_MAP, SkyboxCubeMap);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba);
image->drop();
}
delete[] rgba;
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
void IrrDriver::renderSkybox()
{
if (SkyboxTextures.empty()) return;
@ -925,6 +966,8 @@ void IrrDriver::renderSkybox()
scene::ICameraSceneNode *camera = m_scene_manager->getActiveCamera();
if (!cubevao)
createcubevao();
if (!SkyboxCubeMap)
generateSkyboxCubemap();
glBindVertexArray(cubevao);
glDisable(GL_CULL_FACE);
assert(SkyboxTextures.size() == 6);
@ -937,13 +980,17 @@ void IrrDriver::renderSkybox()
core::matrix4 scale;
scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance));
transform *= translate * scale;
core::matrix4 invtransform;
transform.getInverse(invtransform);
for (unsigned i = 0; i < 6; i++)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, static_cast<irr::video::COpenGLTexture*>(SkyboxTextures[i])->getOpenGLTextureName());
glUseProgram(MeshShader::ObjectUnlitShader::Program);
MeshShader::ObjectUnlitShader::setUniforms(transform, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, SkyboxCubeMap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(MeshShader::SkyboxShader::Program);
MeshShader::SkyboxShader::setUniforms(transform, invtransform, core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (GLvoid*) (6 * i * sizeof(int)));
}
glBindVertexArray(0);

View File

@ -260,6 +260,7 @@ void Shaders::loadShaders()
MeshShader::ShadowShader::init();
MeshShader::RefShadowShader::init();
MeshShader::GrassShadowShader::init();
MeshShader::SkyboxShader::init();
ParticleShader::FlipParticleRender::init();
ParticleShader::HeightmapSimulationShader::init();
ParticleShader::SimpleParticleRender::init();
@ -1028,6 +1029,33 @@ namespace MeshShader
glUniform2f(uniform_dir2, dir2X, dir2Y);
glUniform1i(uniform_tex, TU_tex);
}
GLuint SkyboxShader::Program;
GLuint SkyboxShader::attrib_position;
GLuint SkyboxShader::attrib_texcoord;
GLuint SkyboxShader::uniform_MVP;
GLuint SkyboxShader::uniform_tex;
GLuint SkyboxShader::uniform_screen;
GLuint SkyboxShader::uniform_InvProjView;
void SkyboxShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/sky.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_InvProjView = glGetUniformLocation(Program, "InvProjView");
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_screen = glGetUniformLocation(Program, "screen");
}
void SkyboxShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_InvProjView, 1, GL_FALSE, InvProjView.pointer());
glUniform1i(uniform_tex, TU_tex);
glUniform2f(uniform_screen, screen.X, screen.Y);
}
}

View File

@ -280,6 +280,17 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &ModelViewMatrix, float dirX, float dirY, float dir2X, float dir2Y, unsigned TU_tex);
};
class SkyboxShader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord;
static GLuint uniform_MVP, uniform_InvProjView, uniform_tex, uniform_screen;
static void init();
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex);
};
}
namespace ParticleShader