Created
April 26, 2015 19:26
-
-
Save mantissa/8f390d497b52c601b9ce to your computer and use it in GitHub Desktop.
Drawing instanced meshes using matrices contained in textures (OpenFrameworks)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 120 | |
#extension GL_EXT_gpu_shader4 : require | |
void main(){ | |
gl_FragColor = gl_Color; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 120 | |
#extension GL_EXT_gpu_shader4 : require | |
uniform sampler2DRect matrixTexture; | |
uniform sampler2DRect colorTexture; | |
uniform mat4 mvpMatrix; | |
void main(){ | |
float y = 0; | |
float x = gl_InstanceID*4; | |
mat4 transformMatrix = mat4( | |
texture2DRect(matrixTexture, vec2((x+0.5), y+0.5)), | |
texture2DRect(matrixTexture, vec2((x+1.5), y+0.5)), | |
texture2DRect(matrixTexture, vec2((x+2.5), y+0.5)), | |
texture2DRect(matrixTexture, vec2((x+3.5), y+0.5))); | |
// Multiply the shape coordinates by the transformation matrix | |
// Offset by the position | |
vec4 vPos = transformMatrix * gl_Vertex; | |
// Set the front color to the color passed through with glColor | |
gl_FrontColor = texture2DRect(colorTexture, vec2((gl_InstanceID+0.5), 0.5)); | |
gl_BackColor = gl_FrontColor; | |
// Multiply by the model view and projection matrix | |
gl_Position = mvpMatrix * vPos; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ofApp.h" | |
//-------------------------------------------------------------- | |
void ofApp::setup(){ | |
ofEnableDepthTest(); | |
ofSetFrameRate(60); | |
// create a mesh | |
ofBoxPrimitive box; | |
box.set(5); | |
mesh = box.getMesh(); | |
instancingShader.load("DrawInstances"); | |
// how many shapes | |
nShapes = 300; | |
// create matrix texture (16 elements per shape) | |
// and color texture (4 elements per shape) | |
matrixTexture.allocate(nShapes*4, 1, OF_IMAGE_COLOR_ALPHA); | |
colorTexture.allocate(nShapes, 1, OF_IMAGE_COLOR_ALPHA); | |
// create the colors | |
unsigned char * shapePix = colorTexture.getPixels(); | |
for(int i=0; i<nShapes; i++){ | |
shapePix[i*4] = ofRandom(255); | |
shapePix[i*4+1] = ofRandom(255); | |
shapePix[i*4+2] = ofRandom(255); | |
shapePix[i*4+3] = 255; | |
} | |
colorTexture.update(); | |
} | |
//-------------------------------------------------------------- | |
void ofApp::update(){ | |
float * matPix = matrixTexture.getPixels(); | |
float t = ofGetElapsedTimef(); | |
for(int i=0; i<nShapes; i++){ | |
// create a matrix for each shape | |
// animate position, orientation and scale using perlin noise | |
ofVec3f pos; | |
pos.x = ofNoise(0.001*t, i+0) * 100 -50; | |
pos.y = ofNoise(0.001*t, i+10) * 100 -50; | |
pos.z = ofNoise(0.001*t, i+20) * 100 -50; | |
float angle = ofNoise(0.05*t, i+60) * 360; | |
ofVec3f axis; | |
axis.x = ofNoise(0.02*t, i+30); | |
axis.y = ofNoise(0.02*t, i+40); | |
axis.z = ofNoise(0.02*t, i+50); | |
float scale = ofNoise(0.02*t, i+70) * 2.0 + 0.5; | |
ofMatrix4x4 mat = ofMatrix4x4::newTranslationMatrix(ofVec3f()); | |
mat.rotate(angle, axis.x, axis.y, axis.z); | |
mat.scale(scale, scale, scale); | |
mat.translate(pos); | |
// update the elements of the matrix | |
// in the texture | |
float * ptr = mat.getPtr(); | |
int p = i * 16; | |
for(int j=0; j<16; j++){ | |
matPix[p+j] = ptr[j]; | |
} | |
} | |
matrixTexture.update(); | |
} | |
//-------------------------------------------------------------- | |
void ofApp::draw(){ | |
float t = ofGetElapsedTimef(); | |
// rotate camera based on time | |
ofVec3f camPos; | |
camPos.x = cos(t*3*DEG_TO_RAD ) * 100; | |
camPos.z = sin(t*3*DEG_TO_RAD ) * 100; | |
cam.setPosition( camPos ); | |
cam.lookAt(ofVec3f(0, 0, 0), ofVec3f(0, 1, 0)); | |
cam.begin(); | |
instancingShader.begin(); | |
// set the mvp matrix | |
// set transformation texture (mat4) | |
// set color texture | |
GLuint matLoc = glGetUniformLocation(instancingShader.getProgram(), "mvpMatrix"); | |
ofMatrix4x4 mvpMatrix = cam.getModelViewProjectionMatrix(); | |
if( matLoc != -1 ) glUniformMatrix4fv(matLoc, 1, GL_FALSE, mvpMatrix.getPtr()); | |
instancingShader.setUniformTexture("matrixTexture", matrixTexture.getTextureReference(), 0); | |
instancingShader.setUniformTexture("colorTexture", colorTexture.getTextureReference(), 1); | |
mesh.drawInstanced( OF_MESH_FILL, nShapes ); | |
instancingShader.end(); | |
mesh.draw(); | |
cam.end(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "ofMain.h" | |
class ofApp : public ofBaseApp{ | |
public: | |
void setup(); | |
void update(); | |
void draw(); | |
int nShapes; | |
ofVboMesh mesh; | |
ofShader instancingShader; | |
ofFloatImage matrixTexture; | |
ofImage colorTexture; | |
ofCamera cam; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment