Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emscripten (and I guess GLES) compatibility #12

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions data/ofxVolumetrics/shaders/gles3/raycast.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#version 300 es

precision lowp float;
precision lowp sampler3D;
//#extension GL_ARB_texture_rectangle : enable

in vec3 v_texcoord;
in vec3 v_cameraPosition;

out vec4 out_color;

uniform sampler3D volume_tex;
uniform vec3 vol_d;
uniform vec3 vol_d_pot;
uniform vec2 bg_d;
uniform float zoffset;
uniform float quality;
uniform float threshold;
uniform float density;

struct Ray
{
vec3 Origin;
vec3 Dir;
};

struct BoundingBox
{
vec3 Min;
vec3 Max;
};

bool IntersectBox(Ray r, BoundingBox box, out float t0, out float t1)
{
vec3 invR = 1.0 / r.Dir;
vec3 tbot = invR * (box.Min - r.Origin);
vec3 ttop = invR * (box.Max - r.Origin);
vec3 tmin = min(ttop, tbot);
vec3 tmax = max(ttop, tbot);
vec2 t = max(tmin.xx, tmin.yz);
t0 = max(t.x, t.y);
t = min(tmax.xx, tmax.yz);
t1 = min(t.x, t.y);
return t0 <= t1;
}

void main()
{
vec3 minv = vec3(0.) + 1. / vol_d_pot;
vec3 maxv = (vol_d / vol_d_pot) - 1. / vol_d_pot;
vec3 vec;
vec3 vold = (maxv - minv) * vol_d;
float vol_l = length(vold);

vec4 col_acc = vec4(0, 0, 0, 0);
vec3 zOffsetVec = vec3(0.0, 0.0, zoffset / vol_d_pot.z);
vec3 backPos = v_texcoord;
vec3 lookVec = normalize(backPos - v_cameraPosition);

Ray eye = Ray(v_cameraPosition, lookVec);
BoundingBox box = BoundingBox(vec3(0.), vec3(1.));

float tnear, tfar;
IntersectBox(eye, box, tnear, tfar);
if (tnear < 0.15) tnear = 0.15;
if (tnear > tfar) discard;

vec3 rayStart = (eye.Origin + eye.Dir * tnear) * (maxv - minv) + minv; //vol_d/vol_d_pot;
vec3 rayStop = (eye.Origin + eye.Dir * tfar) * (maxv - minv) + minv; //vol_d/vol_d_pot;

vec3 dir = rayStop - rayStart; // starting position of the ray

vec = rayStart;
float dl = length(dir);
if (dl == clamp(dl, 0., vol_l))
{
int steps = int(floor(length(vold * dir) * quality));
vec3 delta_dir = dir / float(steps);
vec4 color_sample;
float aScale = density / quality;

float random = fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453);
vec += delta_dir * random;

//raycast
for (int i = 0; i < steps; i++)
{
vec3 vecz = vec + zOffsetVec;
if (vecz.z > maxv.z)
{
vecz.z -= maxv.z;
}

color_sample = texture(volume_tex, vecz);
if (color_sample.a > threshold)
{
float oneMinusAlpha = 1. - col_acc.a;
color_sample.a *= aScale;
col_acc.rgb = mix(col_acc.rgb, color_sample.rgb * color_sample.a, oneMinusAlpha);
col_acc.a += color_sample.a * oneMinusAlpha;
col_acc.rgb /= col_acc.a;
if (col_acc.a >= 1.0)
{
break; // terminate if opacity > 1
}
}
vec += delta_dir;
}
}

out_color = col_acc;
}
20 changes: 20 additions & 0 deletions data/ofxVolumetrics/shaders/gles3/raycast.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#version 300 es

in vec4 position;

out vec3 v_texcoord;
out vec3 v_cameraPosition;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrixInverse;

void main()
{
gl_Position = modelViewProjectionMatrix * position;

// as our vertex coordinates are normalized (0..1)
// we can reuse them as 3d texture coordinates
v_texcoord = position.xyz;

v_cameraPosition = (modelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
}
5 changes: 3 additions & 2 deletions ofxVolumetricsExample/src/ofApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ void ofApp::draw()
ofSetColor(255,255,255,255);
background.draw(0,0,ofGetWidth(),ofGetHeight());

cam.begin();
cam.begin();
ofRotateXDeg(90);
myVolume.drawVolume(0,0,0, ofGetHeight(), 0);
if (drawDebug) ofDrawAxis(100);
cam.end();
Expand Down Expand Up @@ -121,4 +122,4 @@ void ofApp::keyPressed(int key)
myVolume.setDrawDebugVolume(drawDebug);
break;
}
}
}
1 change: 1 addition & 0 deletions ofxVolumetricsGPUCopyExample/addons.make
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ofxVolumetrics
10 changes: 10 additions & 0 deletions ofxVolumetricsGPUCopyExample/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "ofMain.h"
#include "ofApp.h"

int main() {
ofGLWindowSettings settings;
settings.setGLVersion(3, 2);
settings.setSize(800, 600);
ofCreateWindow(settings);
ofRunApp(new ofApp());
}
103 changes: 103 additions & 0 deletions ofxVolumetricsGPUCopyExample/src/ofApp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "ofApp.h"


void ofApp::setup()
{
fbo.allocate(256, 256);

volWidth = 256;
volHeight = 256;
volDepth = 256;

cout << "setting up volume data buffer at " << volWidth << "x" << volHeight << "x" << volDepth <<"\n";

myVolume.setup(volWidth, volHeight, volDepth, ofVec3f(1,1,1),true);
myVolume.setRenderSettings(1.0, 1.0, 0.75, 0.1);
myVolume.setVolumeTextureFilterMode(GL_LINEAR);
linearFilter = true;

cam.setDistance(1000);
cam.enableMouseInput();
}


void ofApp::update()
{
ofSetWindowTitle(ofToString(ofGetFrameRate()));
}


void ofApp::draw()
{
ofSetColor(255,255,255,255);
cam.begin();
myVolume.drawVolume(0, 0, 0, ofGetHeight(), 0);
if (drawDebug) ofDrawAxis(100);
cam.end();

ofSetColor(0,0,0,64);
ofDrawRectangle(0,0,270,120);
ofSetColor(255,255,255,255);

ofDrawBitmapString("Volume dimensions: " + ofToString(myVolume.getVolumeWidth()) + "x" + ofToString(myVolume.getVolumeHeight()) + "x" + ofToString(myVolume.getVolumeDepth()) + "\n" +
"FBO quality (q/Q): " + ofToString(myVolume.getRenderWidth()) + "x" + ofToString(myVolume.getRenderHeight()) + "\n" +
"Z quality (z/Z): " + ofToString(myVolume.getZQuality()) + "\n" +
"Threshold (t/T): " + ofToString(myVolume.getThreshold()) + "\n" +
"Density (d/D): " + ofToString(myVolume.getDensity()) + "\n" +
"Filter mode (l/n): " + (linearFilter ? "linear" : "nearest") + "\n" +
"Draw debug (b): " + (drawDebug ? "on" : "off"), 20, 25);
fbo.begin();
for (int x = 0; x < volDepth; x++) {
ofClear(0);
ofSetColor(ofRandom(255), 12, 0);
ofDrawRectangle(ofRandom(20), ofRandom(20), 50, 50);
ofSetColor(50, ofRandom(255), 100);
ofDrawCircle(90 + ofRandom(20), 90 + ofRandom(20), 50);
myVolume.updateTexture(0, 0, x, 0, 0, fbo.getWidth(), fbo.getHeight());
}
fbo.end();
}


void ofApp::keyPressed(int key)
{
switch(key)
{
case 't':
myVolume.setThreshold(myVolume.getThreshold()-0.01);
break;
case 'T':
myVolume.setThreshold(myVolume.getThreshold()+0.01);
break;
case 'd':
myVolume.setDensity(myVolume.getDensity()-0.01);
break;
case 'D':
myVolume.setDensity(myVolume.getDensity()+0.01);
break;
case 'q':
myVolume.setXyQuality(myVolume.getXyQuality()-0.01);
break;
case 'Q':
myVolume.setXyQuality(myVolume.getXyQuality()+0.01);
break;
case 'z':
myVolume.setZQuality(myVolume.getZQuality()-0.01);
break;
case 'Z':
myVolume.setZQuality(myVolume.getZQuality()+0.01);
break;
case 'l':
myVolume.setVolumeTextureFilterMode(GL_LINEAR);
linearFilter = true;
break;
case 'n':
myVolume.setVolumeTextureFilterMode(GL_NEAREST);
linearFilter = false;
break;
case 'b':
drawDebug = !drawDebug;
myVolume.setDrawDebugVolume(drawDebug);
break;
}
}
22 changes: 22 additions & 0 deletions ofxVolumetricsGPUCopyExample/src/ofApp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once
#include "ofMain.h"
#include "ofxVolumetrics.h"

class ofApp : public ofBaseApp
{
public:

void setup();
void update();
void draw();
void keyPressed (int key);

ofEasyCam cam;

ofxVolumetrics myVolume;
int volWidth, volHeight, volDepth;
ofImage background;
ofFbo fbo;
bool linearFilter;
bool drawDebug;
};
2 changes: 1 addition & 1 deletion src/ofxImageSequencePlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ofxImageSequencePlayer : public ofImage {
public:
ofxImageSequencePlayer() {
};
void init(string prefix, int digits, string extension, int start) {
void init(std::string prefix, int digits, std::string extension, int start) {
curFrame = start;
startFrame = start;
fPrefix = prefix;
Expand Down
15 changes: 12 additions & 3 deletions src/ofxTexture3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ void ofxTexture3d::allocate(int w, int h, int d, int internalGlDataType) {
glTexParameteri(texData.textureTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(texData.textureTarget, GL_TEXTURE_WRAP_R, GL_REPEAT);

//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

#ifndef TARGET_EMSCRIPTEN
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#endif

glDisable(texData.textureTarget);

texData.width = w;
Expand Down Expand Up @@ -71,7 +73,7 @@ void ofxTexture3d::loadData(ofFloatPixels& pix, int d, int xOffset, int yOffset,

void ofxTexture3d::loadData(void* data, int w, int h, int d, int xOffset, int yOffset, int zOffset, int glFormat) {
if (glFormat != texData.glType) {
ofLogError() << "ofxTexture3d::loadData() failed to upload format " << ofGetGlInternalFormatName(glFormat) << " data to " << ofGetGlInternalFormatName(texData.glType) << " texture" << endl;
ofLogError() << "ofxTexture3d::loadData() failed to upload format " << ofGetGlInternalFormatName(glFormat) << " data to " << ofGetGlInternalFormatName(texData.glType) << " texture" << std::endl;
return;
}

Expand All @@ -88,6 +90,13 @@ void ofxTexture3d::loadData(void* data, int w, int h, int d, int xOffset, int yO

}

void ofxTexture3d::loadTexture(int xOffset, int yOffset, int zOffset, int x, int y, int width, int height) {
glEnable(texData.textureTarget);
glBindTexture(texData.textureTarget, (GLuint)texData.textureID);
glCopyTexSubImage3D(texData.textureTarget, 0, xOffset, yOffset, zOffset, x, y, width, height);
glDisable(texData.textureTarget);
}

void ofxTexture3d::clear() {
release(texData.textureID);
texData.textureID = 0;
Expand Down
1 change: 1 addition & 0 deletions src/ofxTexture3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ofxTexture3d {
void loadData(ofPixels& pix, int d, int xOffset, int yOffset, int zOffset);
void loadData(ofShortPixels& pix, int d, int xOffset, int yOffset, int zOffset);
void loadData(ofFloatPixels& pix, int d, int xOffset, int yOffset, int zOffset);
void loadTexture(int xOffset, int yOffset, int zOffset, int x, int y, int width, int height);
void bind();
void bindAsImage(GLuint unit, GLenum access, GLint level = 0, GLboolean layered = GL_TRUE, GLint layer = 0);
void unbind();
Expand Down
20 changes: 17 additions & 3 deletions src/ofxVolumetrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,18 @@ ofxVolumetrics::ofxVolumetrics() {
20, 22, 21, 21, 22, 23
};
volumeMesh.addVertices(vertices);
volumeMesh.addIndices(indices);
for(int i = 0; i < indices.size(); i++){
volumeMesh.addIndex(indices[i]);
}
}

void ofxVolumetrics::setup(int w, int h, int d, vec3 voxelSize, bool usePowerOfTwoTexSize) {
string shadersPath = "ofxVolumetrics/shaders/";
shadersPath += ofIsGLProgrammableRenderer() ? "gl3/" : "gl2/";
#ifndef TARGET_EMSCRIPTEN
shadersPath += ofIsGLProgrammableRenderer() ? "gl3/" : "gl2/";
#else
shadersPath += "gles3/";
#endif
volumeShader.unload();
volumeShader.load(shadersPath + "raycast.vert", shadersPath + "raycast.frag");

Expand Down Expand Up @@ -115,6 +121,10 @@ void ofxVolumetrics::updateVolumeData(unsigned char* data, int w, int h, int d,
volumeTexture.loadData(data, w, h, d, xOffset, yOffset, zOffset, GL_RGBA);
}

void ofxVolumetrics::updateTexture(int xOffset, int yOffset, int zOffset, int x, int y, int width, int height) {
volumeTexture.loadTexture(xOffset, yOffset, zOffset, x, y, width, height);
}

void ofxVolumetrics::drawVolume(float x, float y, float z, float size, int zTexOffset) {
vec3 volumeSize = voxelRatio * vec3(volWidth, volHeight, volDepth);
float maxDim = glm::max(glm::max(volumeSize.x, volumeSize.y), volumeSize.z);
Expand Down Expand Up @@ -191,7 +201,7 @@ void ofxVolumetrics::drawVolume(float x, float y, float z, float w, float h, flo

ofPushView();

glColor4iv(color);
ofSetColor(255);
ofSetupScreenOrtho();
fboRender.draw(0, 0, ofGetWidth(), ofGetHeight());

Expand Down Expand Up @@ -268,3 +278,7 @@ float ofxVolumetrics::getDensity() {
const ofFbo& ofxVolumetrics::getFbo() const {
return fboRender;
}

ofxTextureData3d ofxVolumetrics::getTextureData() {
return volumeTexture.getTextureData();
}
Loading