C++ (Qt) glVertexPointer(3, GL_FLOAT, 0, VertexArray); glTexCoordPointer(2, GL_FLOAT, 0, TextureArray); glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, IndexArray);
C++ (Qt)#ifndef SIMPLETEXTURE_H#define SIMPLETEXTURE_H #include <QGLWidget> class QOpenGLShaderProgram;class QOpenGLVertexArrayObject;class QOpenGLTexture; class SimpleTexture : public QGLWidget{ Q_OBJECTpublic: explicit SimpleTexture(QWidget *parent = 0);// ~SimpleTexture(); signals: public slots: private: void initializeGL(); void paintGL(); void resizeGL(int w, int h); QOpenGLShaderProgram* program; QOpenGLTexture* texture;void generate_texture(float * data, int width, int height){ int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { data[(y * width + x) * 4 + 0] = (float)((x & y) & 0xFF) / 255.0f; data[(y * width + x) * 4 + 1] = (float)((x | y) & 0xFF) / 255.0f; data[(y * width + x) * 4 + 2] = (float)((x ^ y) & 0xFF) / 255.0f; data[(y * width + x) * 4 + 3] = 1.0f; } }} }; #endif // SIMPLETEXTURE_H
C++ (Qt)#include "simpletexture.h"#include <QOpenGLShader>#include <QOpenGLShaderProgram>#include <QOpenGLVertexArrayObject>#include <QPainter>#include <QOpenGLTexture> const char* vs_source = "#version 420 core \n" " \n" "void main(void) \n" "{ \n" " const vec4 vertices[] = vec4[](vec4( 0.75, -0.75, 0.5, 1.0), \n" " vec4(-0.75, -0.75, 0.5, 1.0), \n" " vec4( 0.75, 0.75, 0.5, 1.0)); \n" " \n" " gl_Position = vertices[gl_VertexID]; \n" "} \n";const char* fs_source = "#version 430 core \n" " \n" "uniform sampler2D s; \n" " \n" "out vec4 color; \n" " \n" "void main(void) \n" "{ \n" " color = texture(s, gl_FragCoord.xy / textureSize(s, 0)); \n" "} \n"; SimpleTexture::SimpleTexture(QWidget *parent) : QGLWidget(parent){ setWindowTitle("Simple Texture"); program = new QOpenGLShaderProgram(this); texture = new QOpenGLTexture(QOpenGLTexture::Target2D);} //SimpleTexture::~SimpleTexture()//{// delete texture;//} void SimpleTexture::initializeGL(){ glClearColor(0.0f, 0.25f, 0.0f, 1.0f); texture->create(); texture->bind(); texture->setMipLevels(8); texture->setFormat(QOpenGLTexture::RGBA32F); texture->setSize(256, 256); texture->allocateStorage(); float data[256 * 256 * 4]; generate_texture(data, 256, 256); texture->setData(QOpenGLTexture::RGBA, QOpenGLTexture::Float32, data); program->addShaderFromSourceCode(QOpenGLShader::Vertex, vs_source); program->addShaderFromSourceCode(QOpenGLShader::Fragment, fs_source); program->bind();} void SimpleTexture::paintGL(){ glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3);} void SimpleTexture::resizeGL(int w, int h){ glViewport(0, 0, w, h);}
C++ (Qt)#ifndef ALIENRAIN_H#define ALIENRAIN_H #include <QGLWidget> class QOpenGLShaderProgram;class QOpenGLFunctions_4_3_Compatibility;class QTime;class QOpenGLTexture;class QOpenGLBuffer; class AlienRain : public QGLWidget{ Q_OBJECT public: AlienRain(QWidget *parent = 0); ~AlienRain(); private: void initializeGL(); void resizeGL(int w, int h); void paintGL(); void timerEvent(QTimerEvent*); QOpenGLFunctions_4_3_Compatibility* ogl; QTime* time; QOpenGLShaderProgram* program; QOpenGLTexture* texture; QOpenGLBuffer* buffer; protected: float droplet_x_offset[256]; float droplet_rot_speed[256]; float droplet_fall_speed[256]; }; #endif // ALIENRAIN_H
C++ (Qt)#include "alienrain.h" #include <QOpenGLFunctions_4_3_Compatibility>#include <qopengltexture.h>#include <QDebug>#include <cmath>#include "ktx.h"#include <qdatetime.h>#include <QOpenGLShaderProgram>#include <QOpenGLShader>#include <QOpenGLTexture>#include <QOpenGLBuffer> typedef float vec4[4]; // Random number generatorstatic unsigned int seed = 0x13371337; static inline float random_float(){ float res; unsigned int tmp; seed *= 16807; tmp = seed ^ (seed >> 4) ^ (seed << 15); *((unsigned int *)&res) = (tmp >> 9) | 0x3F800000; return (res - 1.0f);} AlienRain::AlienRain(QWidget *parent) : QGLWidget(parent){ setWindowTitle("Alien Rain"); ogl = new QOpenGLFunctions_4_3_Compatibility; time = new QTime; time->start(); program = new QOpenGLShaderProgram; buffer = new QOpenGLBuffer(static_cast<QOpenGLBuffer::Type>(GL_UNIFORM_BUFFER)); texture = 0; startTimer(16);} AlienRain::~AlienRain(){ delete ogl; delete time; delete program; delete buffer; if (texture) delete texture;} void AlienRain::initializeGL(){ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); ogl->initializeOpenGLFunctions(); program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/alienrain.vert"); program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/alienrain.frag"); program->bind(); texture = ktx::load("D:/Docs/GLSL/media/textures/aliens.ktx"); texture->bind(); buffer->create(); buffer->bind(); buffer->setUsagePattern(QOpenGLBuffer::DynamicDraw); buffer->allocate(256 * sizeof(vec4)); for (int i = 0; i < 256; i++) { droplet_x_offset[i] = random_float() * 2.0f - 1.0f; droplet_rot_speed[i] = (random_float() + 0.5f) * ((i & 1) ? -3.0f : 3.0f); droplet_fall_speed[i] = random_float() + 0.2f; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} void AlienRain::resizeGL(int w, int h){ glViewport(0, 0, w, h);} void AlienRain::paintGL(){ float t = time->elapsed() / 1000.0f; glClear(GL_COLOR_BUFFER_BIT); program->bind(); ogl->glBindBufferBase(buffer->type(), 0, buffer->bufferId()); vec4* droplet = (vec4*) buffer->map(QOpenGLBuffer::WriteOnly); for (int i = 0; i < 256; i++) { droplet[i][0] = droplet_x_offset[i]; droplet[i][1] = 2.0f - fmodf((t + float(i)) * droplet_fall_speed[i], 4.31f); droplet[i][2] = t * droplet_rot_speed[i]; droplet[i][3] = 0.0f; } buffer->unmap(); int alien_index; for (alien_index = 0; alien_index < 256; alien_index++) { ogl->glVertexAttribI1i(0, alien_index); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); }} void AlienRain::timerEvent(QTimerEvent*){ updateGL();}
C++ (Qt)#version 410 core layout (location = 0) in int alien_index; out VS_OUT{ flat int alien; vec2 tc;} vs_out; struct droplet_t{ float x_offset; float y_offset; float orientation; float unused;}; layout (std140) uniform droplets{ droplet_t droplet[256];}; void main(void){ const vec2[4] position = vec2[4](vec2(-0.5, -0.5), vec2( 0.5, -0.5), vec2(-0.5, 0.5), vec2( 0.5, 0.5)); vs_out.tc = position[gl_VertexID].xy + vec2(0.5); float co = cos(droplet[alien_index].orientation); float so = sin(droplet[alien_index].orientation); mat2 rot = mat2(vec2(co, so), vec2(-so, co)); vec2 pos = 0.25 * rot * position[gl_VertexID]; gl_Position = vec4(pos.x + droplet[alien_index].x_offset, pos.y + droplet[alien_index].y_offset, 0.5, 1.0); vs_out.alien = alien_index % 64;}
C++ (Qt)#version 410 core layout (location = 0) out vec4 color; in VS_OUT{ flat int alien; vec2 tc;} fs_in; uniform sampler2DArray tex_aliens; void main(void){ color = texture(tex_aliens, vec3(fs_in.tc, float(fs_in.alien)));}
C++ (Qt)#ifndef KTX_H#define KTX_H class QOpenGLTexture; namespace ktx{ struct header { unsigned char identifier[12]; unsigned int endianness; unsigned int gltype; unsigned int gltypesize; unsigned int glformat; unsigned int glinternalformat; unsigned int glbaseinternalformat; unsigned int pixelwidth; unsigned int pixelheight; unsigned int pixeldepth; unsigned int arrayelements; unsigned int faces; unsigned int miplevels; unsigned int keypairbytes; }; union keyvaluepair { unsigned int size; unsigned char rawbytes[4]; }; QOpenGLTexture* load(const char * filename, unsigned int tex = 0); } #endif // KTX_H
C++ (Qt)#include "ktx.h"#include <QFile>#include <QOpenGLTexture>#include <QOpenGLFunctions_4_3_Core>#include <QDebug> namespace ktx{ static const unsigned char identifier[] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; static const unsigned int swap32(const unsigned int u32) { union { unsigned int u32; unsigned char u8[4]; } a, b; a.u32 = u32; for (int i = 0; i < 4; i++) b.u8[i] = a.u8[3 - i]; return b.u32; } QOpenGLTexture* load(const char * filename, unsigned int tex) { QOpenGLFunctions_4_3_Core ogl; ogl.initializeOpenGLFunctions(); QFile file(filename); GLuint temp = 0; header h; size_t data_start, data_end; QVector<unsigned char> data; QOpenGLTexture::Target target = static_cast<QOpenGLTexture::Target>(0); if (!file.open(QFile::ReadOnly)) { qDebug() << "KTX not opened"; return 0; } if (file.read(reinterpret_cast<char*>(&h), sizeof(h)) != sizeof(h)) { qDebug() << "KTX header read error"; return 0; } if (QString::compare( QByteArray(reinterpret_cast<const char*>(identifier), sizeof(identifier)), QByteArray(reinterpret_cast<const char*>(h.identifier), sizeof(h.identifier)))) { qDebug() << "KTX bad header"; return 0; } if (h.endianness == 0x01020304) { h.endianness = swap32(h.endianness); h.gltype = swap32(h.gltype); h.gltypesize = swap32(h.gltypesize); h.glformat = swap32(h.glformat); h.glinternalformat = swap32(h.glinternalformat); h.glbaseinternalformat = swap32(h.glbaseinternalformat); h.pixelwidth = swap32(h.pixelwidth); h.pixelheight = swap32(h.pixelheight); h.pixeldepth = swap32(h.pixeldepth); h.arrayelements = swap32(h.arrayelements); h.faces = swap32(h.faces); h.miplevels = swap32(h.miplevels); h.keypairbytes = swap32(h.keypairbytes); } else if (h.endianness != 0x04030201) { qDebug() << "KTX bad header"; return 0; } // Guess target (texture type) if (h.pixelheight == 0) { if (h.arrayelements == 0) target = QOpenGLTexture::Target1D; else target = QOpenGLTexture::Target1DArray; } else if (h.pixeldepth == 0) { if (h.arrayelements == 0) { if (h.faces == 0) target = QOpenGLTexture::Target2D; else target = QOpenGLTexture::TargetCubeMap; } else { if (h.faces == 0) target = QOpenGLTexture::Target2DArray; else target = QOpenGLTexture::TargetCubeMapArray; } } else target = QOpenGLTexture::Target3D; // Check for insanity... if (target == 0 || // Couldn't figure out target (h.pixelwidth == 0) || // Texture has no width??? (h.pixelheight == 0 && h.pixeldepth != 0)) // Texture has depth but no height??? { qDebug() << "KTX bad header"; return 0; } temp = tex; QOpenGLTexture* texture = new QOpenGLTexture(target); texture->create(); texture->bind(); tex = texture->textureId(); data_start = file.pos(); data_end = file.size(); data.resize(data_end - data_start); data.fill(0); file.read(reinterpret_cast<char*>(data.data()), data.size()); if (h.miplevels == 0) { h.miplevels = 1; } switch (target) { case QOpenGLTexture::Target1D: // glTexStorage1D(GL_TEXTURE_1D, h.miplevels, h.glinternalformat, h.pixelwidth); // glTexSubImage1D(GL_TEXTURE_1D, 0, 0, h.pixelwidth, h.glformat, h.glinternalformat, data); break; case QOpenGLTexture::Target2D: // glTexStorage2D(GL_TEXTURE_2D, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight); // { // unsigned char * ptr = data; // unsigned int height = h.pixelheight; // unsigned int width = h.pixelwidth; // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // for (unsigned int i = 0; i < h.miplevels; i++) // { // glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, width, height, h.glformat, h.gltype, ptr); // ptr += height * calculate_stride(h, width, 1); // height >>= 1; // width >>= 1; // if (!height) // height = 1; // if (!width) // width = 1; // } // } break; case QOpenGLTexture::Target3D: // glTexStorage3D(GL_TEXTURE_3D, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight, h.pixeldepth); // glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, h.pixelwidth, h.pixelheight, h.pixeldepth, h.glformat, h.gltype, data); break; case QOpenGLTexture::Target1DArray: // glTexStorage2D(GL_TEXTURE_1D_ARRAY, h.miplevels, h.glinternalformat, h.pixelwidth, h.arrayelements); // glTexSubImage2D(GL_TEXTURE_1D_ARRAY, 0, 0, 0, h.pixelwidth, h.arrayelements, h.glformat, h.gltype, data); break; case QOpenGLTexture::Target2DArray:// texture->setMipLevels(h.miplevels);// texture->setSize(h.pixelwidth, h.pixelheight, h.pixeldepth);// texture->setLayers(h.arrayelements);// texture->allocateStorage(); // texture->setData(static_cast<QOpenGLTexture::PixelFormat> (h.glformat),// static_cast<QOpenGLTexture::PixelType> (h.gltype),// data.data()); // glTexStorage3D(GL_TEXTURE_2D_ARRAY, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight, h.arrayelements); // glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, h.pixelwidth, h.pixelheight, h.arrayelements, h.glformat, h.gltype, data); ogl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight, h.arrayelements); ogl.glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, h.pixelwidth, h.pixelheight, h.arrayelements, h.glformat, h.gltype, data.data()); break; case QOpenGLTexture::TargetCubeMap: // glTexStorage2D(GL_TEXTURE_CUBE_MAP, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight); // glTexSubImage3D(GL_TEXTURE_CUBE_MAP, 0, 0, 0, 0, h.pixelwidth, h.pixelheight, h.faces, h.glformat, h.gltype, data); // { // unsigned int face_size = calculate_face_size(h); // for (unsigned int i = 0; i < h.faces; i++) // { // glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, h.pixelwidth, h.pixelheight, h.glformat, h.gltype, data + face_size * i); // } // } break; case QOpenGLTexture::TargetCubeMapArray: // glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, h.miplevels, h.glinternalformat, h.pixelwidth, h.pixelheight, h.arrayelements); // glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, h.pixelwidth, h.pixelheight, h.faces * h.arrayelements, h.glformat, h.gltype, data); break; } // if (h.miplevels == 1) // texture->generateMipMaps(); return texture; } }