You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
7.2 KiB
305 lines
7.2 KiB
//
|
|
// CircleSurface.cpp
|
|
// Copyright (c) 2017 Cristobal Mendoza
|
|
// http://cuppetellimendoza.com
|
|
|
|
#include "CircleSurface.h"
|
|
|
|
namespace ofx {
|
|
namespace piMapper {
|
|
|
|
CircleSurface::CircleSurface() : QuadSurface() {
|
|
setup();
|
|
}
|
|
|
|
CircleSurface::CircleSurface(QuadSurface &surface) {
|
|
setup();
|
|
setVertices(surface.getVertices());
|
|
setTexCoords(surface.getTexCoords());
|
|
setPerspectiveWarping(surface.getPerspectiveWarping());
|
|
}
|
|
|
|
CircleSurface::~CircleSurface() {}
|
|
|
|
void CircleSurface::setup() {
|
|
|
|
QuadSurface::setup();
|
|
setPerspectiveWarping(true);
|
|
|
|
lastSourceTextureId = UINT_MAX;
|
|
updateMask = true;
|
|
// maskIsReady = false;
|
|
|
|
// glESVertexShader = CIRCLE_SURFACE_STRINGIFY(
|
|
// attribute vec4 position;
|
|
// attribute vec4 color;
|
|
// attribute vec4 normal;
|
|
// attribute vec2 texcoord;
|
|
//
|
|
// uniform mat4 modelViewMatrix;
|
|
// uniform mat4 projectionMatrix;
|
|
// uniform sampler2D maskTex;
|
|
//
|
|
// varying vec4 colorVarying;
|
|
// varying vec2 texCoordVarying;
|
|
//
|
|
// void main() {
|
|
//
|
|
// //get our current vertex position so we can modify it
|
|
// vec4 pos = projectionMatrix*modelViewMatrix*position;
|
|
//
|
|
// gl_Position = pos;
|
|
// colorVarying = color;
|
|
// texCoordVarying = texcoord;
|
|
// }
|
|
// );
|
|
//
|
|
// glESFragmentShader = CIRCLE_SURFACE_STRINGIFY(
|
|
////#ifdef GL_ES
|
|
//// define default precision for float, vec, mat.
|
|
// precision highp float;
|
|
////#endif
|
|
//
|
|
// uniform sampler2D tex0;
|
|
// uniform sampler2D maskTex;
|
|
// uniform vec4 globalColor;
|
|
//
|
|
// varying vec2 texCoordVarying;
|
|
//
|
|
// void main (void)
|
|
// {
|
|
// vec2 pos = texCoordVarying;
|
|
// vec3 src = texture2D(tex0, pos).rgb;
|
|
// float mask = texture2D(maskTex, pos).r;
|
|
// gl_FragColor = vec4( src , mask);
|
|
// }
|
|
// );
|
|
//
|
|
// gl2FragmentShader = "#version 120\n #extension GL_ARB_texture_rectangle : enable\n";
|
|
// gl2FragmentShader += CIRCLE_SURFACE_STRINGIFY(
|
|
// uniform sampler2DRect tex0;
|
|
// uniform sampler2DRect maskTex;
|
|
//
|
|
// void main (void) {
|
|
// vec2 pos = gl_TexCoord[0].st;
|
|
//
|
|
// vec3 src = texture2DRect(tex0, pos).rgb;
|
|
// float mask = texture2DRect(maskTex, pos).r;
|
|
//
|
|
// gl_FragColor = vec4(src, mask);
|
|
// }
|
|
// );
|
|
//
|
|
//#ifdef TARGET_OPENGLES
|
|
// maskShader.setupShaderFromSource(GL_VERTEX_SHADER, glESVertexShader);
|
|
// maskShader.setupShaderFromSource(GL_FRAGMENT_SHADER, glESFragmentShader);
|
|
// maskShader.bindDefaults();
|
|
// maskShader.linkProgram();
|
|
//#else
|
|
// if (ofIsGLProgrammableRenderer()) {
|
|
//
|
|
// } else {
|
|
// maskShader.setupShaderFromSource(GL_FRAGMENT_SHADER, gl2FragmentShader);
|
|
// maskShader.linkProgram();
|
|
// }
|
|
//#endif
|
|
|
|
Vec2 t1 = Vec2(0.0f, 0.0f);
|
|
Vec2 t2 = Vec2(1.0f, 0.0f);
|
|
Vec2 t3 = Vec2(1.0f, 1.0f);
|
|
Vec2 t4 = Vec2(0.0f, 1.0f);
|
|
|
|
defaultTexCoords.push_back(t1);
|
|
defaultTexCoords.push_back(t2);
|
|
defaultTexCoords.push_back(t3);
|
|
defaultTexCoords.push_back(t4);
|
|
}
|
|
|
|
void CircleSurface::draw() {
|
|
|
|
ofEnableAlphaBlending();
|
|
if (source->getTexture() == 0)
|
|
{
|
|
return;
|
|
}
|
|
if (!source->getTexture()->isAllocated()){
|
|
return;
|
|
}
|
|
|
|
if (source != currentSource) { // Pointer comparison
|
|
// Create the mask here
|
|
setupTextures();
|
|
lastSourceTextureId = UINT_MAX;
|
|
currentSource = source;
|
|
}
|
|
|
|
|
|
// Save Normie state:
|
|
auto isNorm = ofGetUsingNormalizedTexCoords();
|
|
|
|
// If we get to this part of the function, the mask fbo
|
|
// should already be allocated and the mask texture created.
|
|
|
|
ofEnableNormalizedTexCoords();
|
|
// Get the texture from the source an store a copy
|
|
// of the source texture's id:
|
|
auto sourceTex = ofTexture(*(source->getTexture()));
|
|
auto sourceTexId = sourceTex.getTextureData().textureID;
|
|
|
|
// Draw the mask only if the sources are FBO's, videos,
|
|
// or if the last texture id was UINT_MAX (which means that
|
|
// the mask has not yet been draw).
|
|
// if (source->getType() == SOURCE_TYPE_FBO ||
|
|
// source->getType() == SOURCE_TYPE_VIDEO ||
|
|
// lastSourceTextureId == UINT_MAX) {
|
|
if (true) {
|
|
lastSourceTextureId = sourceTexId;
|
|
drawMaskForSource(sourceTex);
|
|
}
|
|
|
|
// Swap the texture id of the source with the one of our
|
|
// newly drawn outputFbo:
|
|
source->getTexture()->getTextureData().textureID = outputFbo.getTexture().getTextureData().textureID;
|
|
auto texCoords = getMesh().getTexCoords();
|
|
getMesh().clearTexCoords();
|
|
getMesh().addTexCoords(Vec2::toOf(defaultTexCoords));
|
|
// Draw the Quad:
|
|
QuadSurface::draw();
|
|
|
|
// Reset the texture id of the source
|
|
source->getTexture()->getTextureData().textureID = lastSourceTextureId;
|
|
|
|
// Reset the texture coords of the QuadSurface mesh:
|
|
getMesh().clearTexCoords();
|
|
getMesh().addTexCoords(texCoords);
|
|
|
|
if (!isNorm) ofDisableNormalizedTexCoords();
|
|
}
|
|
|
|
void CircleSurface::setFeathering(float f) {
|
|
feathering = f;
|
|
updateMask = true;
|
|
}
|
|
|
|
|
|
void CircleSurface::drawMaskForSource(ofTexture &sourceTex) {
|
|
auto quadTexCoords = getMesh().getTexCoords();
|
|
|
|
maskMesh.clearTexCoords();
|
|
|
|
// Set the mesh's texture coords to the quads.
|
|
// This gets us the coordinates set in the TextureEditor
|
|
maskMesh.addTexCoords(quadTexCoords);
|
|
outputFbo.begin(true);
|
|
{
|
|
ofClear(0, 0, 0, 0);
|
|
ofEnableNormalizedTexCoords();
|
|
ofSetColor(255);
|
|
ofFill();
|
|
ofSetRectMode(OF_RECTMODE_CORNER);
|
|
//#ifdef TARGET_RASPBERRY_PI
|
|
sourceTex.bind();
|
|
maskMesh.draw();
|
|
sourceTex.unbind();
|
|
// Masking without shaders...
|
|
ofPushStyle();
|
|
ofEnableBlendMode(OF_BLENDMODE_MULTIPLY);
|
|
ofSetColor(255);
|
|
ofFill();
|
|
ofDisableNormalizedTexCoords();
|
|
maskFbo.draw(0, 0);
|
|
ofPopStyle();
|
|
//#else
|
|
// maskShader.begin();
|
|
// maskShader.setUniformTexture("maskTex", maskFbo.getTexture(), 1);
|
|
// ofSetColor(255);
|
|
// ofFill();
|
|
// ofSetRectMode(OF_RECTMODE_CORNER);
|
|
// scaledSourceFbo.getTexture().bind();
|
|
// maskMesh.draw();
|
|
// scaledSourceFbo.getTexture().unbind();
|
|
// maskShader.end();
|
|
//#endif
|
|
|
|
}
|
|
outputFbo.end();
|
|
|
|
}
|
|
|
|
void CircleSurface::setupTextures() {
|
|
float w = source->getTexture()->getWidth();
|
|
float h = source->getTexture()->getHeight();
|
|
float dia = 0;
|
|
if (w > h) {
|
|
dia = h;
|
|
} else {
|
|
dia = w;
|
|
}
|
|
|
|
float padding = 10;
|
|
|
|
maskFbo.allocate(w, h);
|
|
maskFbo.begin(false);
|
|
ofPushStyle();
|
|
ofSetupScreenOrtho(w, h, -1, 1);
|
|
ofClear(0, 0, 0, 255);
|
|
ofFill();
|
|
ofSetColor(255);
|
|
ofSetCircleResolution(300);
|
|
ofDrawEllipse(w/2, h/2, w-padding, h-padding);
|
|
ofPopStyle();
|
|
maskFbo.end();
|
|
|
|
outputFbo.allocate(w, h);
|
|
outputFbo.begin();
|
|
ofClear(0, 0, 0, 255);
|
|
outputFbo.end();
|
|
|
|
// scaledSourceFbo.allocate(w, h);
|
|
// scaledSourceFbo.begin();
|
|
// ofClear(0, 0, 0, 255);
|
|
// scaledSourceFbo.end();
|
|
|
|
// This is lifted from QuadSurface::setup to ensure that the two
|
|
// meshes are similar:
|
|
|
|
// Create 4 points for the 2 triangles
|
|
Vec3 p1 = Vec3(0, 0, 0);
|
|
Vec3 p2 = Vec3(0, h, 0);
|
|
Vec3 p3 = Vec3(w, h, 0);
|
|
Vec3 p4 = Vec3(w, 0, 0);
|
|
|
|
// Create 4 point for the texture coordinates
|
|
Vec2 t1 = Vec2(Vec2(0.0f, 1.0f));
|
|
Vec2 t2 = Vec2(Vec2(1.0f, 1.0f));
|
|
Vec2 t3 = Vec2(Vec2(1.0f, 0.0f));
|
|
Vec2 t4 = Vec2(Vec2(0.0f, 0.0f));
|
|
|
|
// Clear maskMesh
|
|
maskMesh.clear();
|
|
|
|
// Create a surface with the points
|
|
maskMesh.addVertex(p1.toOf());
|
|
maskMesh.addVertex(p2.toOf());
|
|
maskMesh.addVertex(p3.toOf());
|
|
maskMesh.addVertex(p4.toOf());
|
|
|
|
// Add 2 triangles
|
|
maskMesh.addTriangle(0, 2, 3);
|
|
maskMesh.addTriangle(0, 1, 2);
|
|
|
|
// Add texture coordinates
|
|
maskMesh.addTexCoord(t1.toOf());
|
|
maskMesh.addTexCoord(t2.toOf());
|
|
maskMesh.addTexCoord(t3.toOf());
|
|
maskMesh.addTexCoord(t4.toOf());
|
|
}
|
|
|
|
|
|
|
|
int CircleSurface::getType() {
|
|
return SurfaceType::CIRCLE_SURFACE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|