How to creating a skybox using samplerCube and the QOpenGLTexture class?
-
Hi, I'm trying to create a skybox using the samplerCube mapping in the shader program. As I understand it, it should be possible to use the coordinates of the skybox vertices for mapping the texture to the skybox. I would like to do this using the QOpenGLTexture class.
Does any one know how to setup the QOpenGLTexture to use samplerCube mapping? I would like to use a texture that looks like this one: http://www.keithlantz.net/wp-content/uploads/2011/10/skybox_texture.jpg (from http://www.keithlantz.net/2011/10/rendering-a-skybox-using-a-cube-map-with-opengl-and-glsl/) Guess I should use QOpenGLTexture::BindingTargetCubeMap somehow(?).
Here is a short example program where I try to implement a skybox:
main.cpp
@
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
// Setup OpenGL window
OpenGLWindow window;
return app.exec();
}
@OpenGLWindow.hpp
@
#include "Skybox.hpp"class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECTSkybox* m_skybox;
bool m_update_pending;
bool m_animating;QOpenGLContext *m_context;
QOpenGLShaderProgram m_program;QMatrix4x4 m_projectionMatrix;
QOpenGLVertexArrayObject m_vao;
public:
explicit OpenGLWindow(QWindow *parent = 0)
: QWindow(parent)
, m_update_pending(false)
, m_animating(true)
, m_context(0)
{
setSurfaceType(OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setMajorVersion(3);
format.setMinorVersion(3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
resize(640, 480);
show();
create();m_context = new QOpenGLContext(this);
m_context->setFormat(format);
m_context->create();
m_context->makeCurrent(this);initializeOpenGLFunctions();
m_vao.create();
m_vao.bind();m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, "simple.vert");
m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, "simple.frag");
m_program.link()m_skybox = new Skybox(m_program);
m_projectionMatrix.setToIdentity();
m_projectionMatrix.perspective(90.0f, 640.0f/480.0f, 0.1f, 30.0f);glViewport(0, 0, width(), height());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glEnable(GL_CULL_FACE);
m_program.bind();
glDisable(GL_DEPTH_TEST);
// Set camera position
QMatrix4x4 viewMatrix;
viewMatrix.setToIdentity();
QVector3D eye(0.0f, 0.0f, 0.0f);
QVector3D center(1.0f, 1.0f, 1.0f);
QVector3D up(0.0f, 1.0f, 0.0f);
viewMatrix.lookAt(eye, center, up);// Render skybox
m_skybox->draw(viewMatrix, m_projectionMatrix);glEnable(GL_DEPTH_TEST);
// Render other stuff .....
}void setAnimating(bool animating)
{
m_animating = animating;if (animating)
renderLater();
}public slots:
void renderLater()
{
if (!m_update_pending)
{
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}void renderNow()
{
if (!isExposed())
return;m_context->makeCurrent(this);
render();
m_context->swapBuffers(this);
if (m_animating)
renderLater();
}protected:
bool event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
m_update_pending = false;
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);if (isExposed())
renderNow();
}
};
@Skybox.hpp
@
#define NUMB_VER 36class Skybox
{
private:
static QOpenGLBuffer m_vertexPositionBuffer;
static const GLfloat m_vertices[NUMB_VER*3];
QOpenGLShaderProgram& m_program;
QOpenGLTexture m_texture;public:
~Skybox(){};explicit Skybox(QOpenGLShaderProgram& program)
: m_program(program)
, m_texture(QImage(QString("skybox_texture.jpg")).mirrored())
{
m_vertexPositionBuffer.create();
m_vertexPositionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
m_vertexPositionBuffer.bind();
m_vertexPositionBuffer.allocate(m_vertices, NUMB_VER3sizeof(GLfloat));m_texture.setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
m_texture.setMagnificationFilter(QOpenGLTexture::Linear);
}inline void draw(const QMatrix4x4& viewMatrix, const QMatrix4x4& projectionMatrix)
{
// Remove translates but keep rotations of the camera
QMatrix4x4 modelViewMatrix = viewMatrix;
modelViewMatrix.setColumn(3, QVector4D(0.0f, 0.0f, 0.0f, 1.0f));const QMatrix3x3 normalMatrix = modelViewMatrix.normalMatrix();
const QMatrix4x4 mvp = projectionMatrix * modelViewMatrix;m_program.bind();
m_program.setUniformValue("modelViewMatrix", modelViewMatrix);
m_program.setUniformValue("normalMatrix", normalMatrix);
m_program.setUniformValue("projectionMatrix", projectionMatrix);
m_program.setUniformValue("mvp", mvp);m_vertexPositionBuffer.bind();
m_program.enableAttributeArray("vertexPosition");
m_program.setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 3);m_texture.bind();
glDrawArrays(GL_TRIANGLES, 0, NUMB_VER);
}
};
@Skybox.cpp
@
#include "Skybox.hpp"QOpenGLBuffer Skybox::m_vertexPositionBuffer;
const GLfloat Skybox::m_vertices[NUMB_VER*3] =
{
-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
};
@Thanks in advance!
-
... and here are the shader programs
simple.vert
@
#version 330in vec3 vertexPosition;
uniform mat4 modelViewMatrix;
uniform mat4 normalMatrix;
uniform mat4 projectionMatrix;
uniform mat4 mvp;//uniform sampler2D texUnit1;
uniform samplerCube texUnit1;out vec3 position;
void main()
{
position = vertexPosition;gl_Position = mvp*vec4(vertexPosition, 1.0);
}
@simple.frag
@
#version 330in vec3 position;
//uniform sampler2D texUnit1;
uniform samplerCube texUnit1;out vec4 gl_Color;
void main()
{
gl_Color = texture(texUnit1, position);
}
@ -
You need to use manual upload of each cube face using:
-
Hi,
Do you find a way to use it ? I tried it, but impossible I have a read access violation ... Could you please send an example ?