Texturing a vertex in OpenGL and GLSL
-
I'm trying to put a texture on a vertex using some tutorials i found on the internet, sadly none of those are showing the entire code (GLSL + Source code).
Tutorials i have used:
http://www.ozone3d.net/tutorials/glsl_texturing_p02.php#part_2 http://www.opengl.org/wiki/Sampler_(GLSL)#Binding_textures_to_samplers+'OpenGL Window Example', on which my code is based.
Header:
@#include <openglwindow.h>#include <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QScreen>#include <QtCore/qmath.h>
class TestWindow : public OpenGLWindow
{
public:
TestWindow();
~TestWindow();void initialize(); void render();
private:
GLuint loadShader(GLenum type, const char *source);GLuint m_posAttr; GLuint m_colAttr; GLuint m_matrixUniform; GLuint m_colorMap; QOpenGLShaderProgram *m_program; int m_frame; GLuint tex;
};@
Code:
@#include "testwindow.h"
#include <QFileDialog>
#include <QImage>#include <QtCore/QCoreApplication>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QPainter>
#include <GL/gl.h>#include <SimpleShaders.h>
#define TEST_TEXTURE
GLfloat TerrainVertices[]={
1, 1,
1, 0,
0, 1,
0, 0,
-1, 1,
-1, 0,
};GLfloat TerrainColor[]={
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
};TestWindow::TestWindow()
: m_program(0)
, m_frame(0)
{
}TestWindow::~TestWindow()
{}
GLuint TestWindow::loadShader(GLenum type, const char *source)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
return shader;
}void TestWindow::initialize()
{
m_program = new QOpenGLShaderProgram(this);#ifndef TEST_TEXTURE
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
#else
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, VS_TextureShader);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, FS_TextureShader);
#endifm_program->link(); m_posAttr = m_program->attributeLocation("posAttr");
#ifndef TEST_TEXTURE
m_colAttr = m_program->attributeLocation("colAttr");
#else
m_colorMap = m_program->uniformLocation("colorMap");
glEnable(GL_TEXTURE_2D);
#endifm_matrixUniform = m_program->uniformLocation("matrix");
}
void TestWindow::render()
{
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_program->bind();
//Camera view
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -3);
matrix.rotate(10.0f * m_frame / screen()->refreshRate(), 0, 1, 0);m_program->setUniformValue(m_matrixUniform, matrix); glEnableVertexAttribArray(m_colAttr); glEnableVertexAttribArray(m_posAttr);
#ifndef TEST_TEXTURE
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, TerrainColor);
#endif
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, TerrainVertices);#ifdef TEST_TEXTURE
glUniform1i(m_colorMap, 0);
glActiveTexture(GL_TEXTURE0+0);
glBindTexture(GL_TEXTURE_2D,tex);
GLuint sampler;
glGenSamplers(1,&sampler);
glBindSampler(0,sampler);uchar pixels[2*2*4]={255,000,000,255, 000,255,000,255, 000,000,255,255, 255,255,255,255}; glTexImage2D(GL_TEXTURE_2D, 0, 4, 2, 2, 0, GL_RGBA,GL_UNSIGNED_BYTE, (const GLvoid *)pixels);
#endif
glDrawArrays(GL_QUAD_STRIP, 0, 6);
#ifdef TEST_TEXTURE
glDeleteSamplers(1,&sampler);
glDeleteTextures(1,&tex);
#endifglDisableVertexAttribArray(m_colAttr); glDisableVertexAttribArray(m_posAttr); m_program->release(); ++m_frame;
}@
Shaders:
@static const char* vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix * posAttr;\n"
"}\n";static const char* fragmentShaderSource =
"varying lowp vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n";static const char* VS_TextureShader =
"attribute highp vec4 posAttr;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
" gl_Position = matrix * posAttr;\n"
"}\n";static const char* FS_TextureShader =
"uniform sampler2D colorMap;\n"
"void main (void){\n"
"gl_FragColor = texture( colorMap, gl_TexCoord[0].st);}";@If i define TEST_TEXTURE (to switch from colors to textures) all i get is a black/empty window, while it works without a problem when using colors.
What am i missing? Or is there a better approach to use OpenGL with Qt?
If you want to test the code yourself, you have change the openglwindow, instead of inheriting from QOpenGLFunctions it has to be QOpenGLFunctions_4_0_Core.
-
I'm still facing the same problem:
I've worked on my functions but it's doesn't work:
@float texPos[8]={1,1, 0,1,
0,0, 1,0};@Initialisation:
@m_program = new QOpenGLShaderProgram(this);
const char *vsrc =
"attribute highp vec4 vertex;\n"
"attribute mediump vec4 texCoord;\n"
"varying mediump vec4 texc;\n"
"uniform mediump mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
"}\n";const char *fsrc =
"uniform sampler2D texture;\n"
"varying mediump vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st);\n"
"}\n";m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,vsrc);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,fsrc);
m_program->link();
m_posAttr = m_program->attributeLocation("vertex");
m_texPos = m_program->attributeLocation("texCoord");m_program->setUniformValue("texture", 0);
m_colorMap = QGLContext::fromOpenGLContext(m_context)->bindTexture(QPixmap(QString("skybox01.png")), GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);@Rendering:
@const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_program->bind();
//Camera view
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -3);
matrix.rotate(10.0f * m_frame / screen()->refreshRate(), 0, 1, 0);m_program->setUniformValue(m_matrixUniform, matrix);
glEnableVertexAttribArray(m_posAttr);
glEnableVertexAttribArray(m_texPos);
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, TerrainVertices);
glVertexAttribPointer(m_texPos, 2, GL_FLOAT, GL_FALSE, 0, texPos);glBindTexture(GL_TEXTURE_2D, m_colorMap);
glDrawArrays(GL_QUAD_STRIP, 0, 6);glDisableVertexAttribArray(m_posAttr);
glDisableVertexAttribArray(m_texPos);m_program->release();
++m_frame;@
I still seem to be missing something.
-
Hi,
your texture is never created because you never call glGenTextures() for TestWindow::tex. Your code is a bit complicated for what you're intending to do because of copy/pastes from the examples you found, so it is very difficult to read. You should remove the OpenGL samplers, you don't need them -- be careful, I'm speaking about the samplers in your c++ code, not in the GLSL -- and the call to glActiveTexture() -- which is only useful for multitexturing. glTexImage2D() should be called during initialization instead of rendering. When using GLSL, you should precise the version in your code, e.g. with "#version 440" for GLSL 4.4. I think this "link":http://open.gl/textures is a good tutorial you can read.