Skip to content

Instantly share code, notes, and snippets.

@ishikawash
Created January 5, 2014 05:36
Show Gist options
  • Save ishikawash/8264836 to your computer and use it in GitHub Desktop.
Save ishikawash/8264836 to your computer and use it in GitHub Desktop.
Instanced rendering demo using openFrameworks Part 2. The shader program use vertex attributes instead of uniform variables.
#version 120
uniform vec3 light_direction;
varying vec3 vertex_normal;
varying vec3 vertex_color;
void main(void) {
vec3 N = normalize(vertex_normal);
vec3 L = normalize(light_direction);
float kd = clamp(dot(N, L), 0.0f, 1.0f);
vec3 color = kd * vertex_color;
gl_FragColor = vec4(color, 1.0f);
}
#version 120
#extension GL_EXT_gpu_shader4 : require
uniform vec3 colors[2];
varying vec3 vertex_normal;
varying vec3 vertex_color;
attribute mat4 model_matrix;
attribute mat3 normal_matrix;
void main(void) {
vertex_normal = normal_matrix * gl_Normal;
vertex_color = colors[gl_InstanceID % 2];
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * model_matrix * gl_Vertex;
}
#include "ofMain.h"
#include "testApp.h"
//========================================================================
int main( ){
ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp(new testApp());
}
#include "testApp.h"
using namespace std;
using namespace glm;
const int GRID_LENGTH = 10;
const float GRID_OFFSET = 20.0f;
const float BOX_SIZE = 20.0f;
void printMatrix4fv(const float *m) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
printf("%8.2f\t", m[4*i + j]);
}
printf("\n");
}
printf("\n");
}
void testApp::uniformMatrix4fv(const char *name, const float *m) {
GLint location = glGetUniformLocation(shader.getProgram(), name);
if (location != -1)
glUniformMatrix4fv(location, 1, GL_FALSE, m);
}
void testApp::uniformMatrix3fv(const char *name, const float *m) {
GLint location = glGetUniformLocation(shader.getProgram(), name);
if (location != -1)
glUniformMatrix3fv(location, 1, GL_FALSE, m);
}
void testApp::bindBuffers() {
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.model_matrix);
for (int i = 0; i < 4; i++) {
GLint location = attribLocation.model_matrix + i;
int offset = sizeof(vec4)*i;
glEnableVertexAttribArray(location);
glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (GLvoid*)offset);
glVertexAttribDivisorARB(location, 1);
}
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.normal_matrix);
for (int i = 0; i < 3; i++) {
GLint location = attribLocation.normal_matrix + i;
int offset = sizeof(vec3)*i;
glEnableVertexAttribArray(location);
glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, sizeof(mat3), (GLvoid*)offset);
glVertexAttribDivisorARB(location, 1);
}
}
void testApp::unbindBuffers() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
//--------------------------------------------------------------
void testApp::setup(){
ofEnableDepthTest();
bg_colors[0].set(255.0f);
bg_colors[1].set(96.0f);
box.set(BOX_SIZE);
vboMesh = box.getMesh();
const ivec3 grid_size(GRID_LENGTH);
nodes.resize(grid_size.x*grid_size.y*grid_size.z);
const vec3 grid_box_size(box.getWidth() + GRID_OFFSET, box.getHeight() + GRID_OFFSET, box.getDepth() + GRID_OFFSET);
const vec3 grid_center = 0.5f*vec3(grid_size.x*box.getWidth() + (grid_size.x - 1)*GRID_OFFSET,
grid_size.y*box.getHeight() + (grid_size.y - 1)*GRID_OFFSET,
grid_size.z*box.getDepth() + (grid_size.z - 1)*GRID_OFFSET);
for (int k = 0; k < grid_size.z; k++) {
for (int j = 0; j < grid_size.y; j++) {
for (int i = 0; i < grid_size.x; i++) {
ofNode &node = nodes[grid_size.x*grid_size.y*k + grid_size.x*j + i];
node.move(-grid_center.x, -grid_center.y, -grid_center.z);
node.move(grid_box_size.x*i, grid_box_size.y*j, grid_box_size.z*k);
node.setParent(parent);
}
}
}
camera.move(0.0f, 0.0f, 800.0f);
shader.load("box.vs", "box.fs");
shader.begin();
{
vec3 light_direction(0.0f, 1.0f, 1.0f);
shader.setUniform3fv("light_direction", value_ptr(light_direction));
vec3 box_colors[2];
box_colors[0] = vec3(0.0f, 0.0f, 0.0f);
box_colors[1] = vec3(1.0f, 1.0f, 1.0f);
char name[64];
for (int i = 0; i < 2; i++) {
snprintf(name, sizeof(name), "colors[%d]", i);
shader.setUniform3fv(name, value_ptr(box_colors[i]));
}
attribLocation.model_matrix = shader.getAttributeLocation("model_matrix");
attribLocation.normal_matrix = shader.getAttributeLocation("normal_matrix");
}
shader.end();
modelMatrices.resize(nodes.size());
glGenBuffers(1, &bufferHandle.model_matrix);
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.model_matrix);
glBufferData(GL_ARRAY_BUFFER, nodes.size() * sizeof(mat4), value_ptr(modelMatrices[0]), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
normalMatrices.resize(nodes.size());
glGenBuffers(1, &bufferHandle.normal_matrix);
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.normal_matrix);
glBufferData(GL_ARRAY_BUFFER, nodes.size() * sizeof(mat3), value_ptr(normalMatrices[0]), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//--------------------------------------------------------------
void testApp::update(){
float t = ofGetElapsedTimef();
float theta = 180.0f*ofGetLastFrameTime();
parent.rotate(theta, cosf(t), sinf(t), 0.0f);
shader.begin();
{
glGetFloatv(GL_MODELVIEW_MATRIX, buf);
mat4 view_matrix;
memcpy(&view_matrix[0][0], buf, sizeof(buf));
for (int i = 0; i < nodes.size(); i++) {
ofNode &node = nodes[i];
mat4 &model_matrix = modelMatrices[i];
memcpy(&model_matrix[0][0], node.getGlobalTransformMatrix().getPtr(), sizeof(mat4));
mat4 model_view_matrix = view_matrix*model_matrix;
normalMatrices[i] = mat3(transpose(inverse(model_view_matrix)));
}
}
shader.end();
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.model_matrix);
glBufferSubData(GL_ARRAY_BUFFER, 0, nodes.size()*sizeof(mat4), value_ptr(modelMatrices[0]));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, bufferHandle.normal_matrix);
glBufferSubData(GL_ARRAY_BUFFER, 0, nodes.size()*sizeof(mat3), value_ptr(normalMatrices[0]));
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//--------------------------------------------------------------
void testApp::draw(){
ofBackgroundGradient(bg_colors[0], bg_colors[1], OF_GRADIENT_BAR);
camera.begin();
{
shader.begin();
{
bindBuffers();
{
vboMesh.drawInstanced(OF_MESH_FILL, nodes.size());
}
unbindBuffers();
}
shader.end();
}
camera.end();
}
//--------------------------------------------------------------
void testApp::keyPressed(int key){
}
//--------------------------------------------------------------
void testApp::keyReleased(int key){
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){
}
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ofMain.h"
struct VertexBufferHandle {
GLuint model_matrix;
GLuint normal_matrix;
};
struct VertexAttribLocation {
GLint model_matrix;
GLint normal_matrix;
};
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
ofCamera camera;
ofNode parent;
std::vector<ofNode> nodes;
ofBoxPrimitive box;
ofShader shader;
ofVboMesh vboMesh;
VertexBufferHandle bufferHandle;
VertexAttribLocation attribLocation;
std::vector<glm::mat4> modelMatrices;
std::vector<glm::mat3> normalMatrices;
ofColor bg_colors[2];
float buf[16];
private:
void uniformMatrix3fv(const char *name, const float *m);
void uniformMatrix4fv(const char *name, const float *m);
void bindBuffers();
void unbindBuffers();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment