The shader is just a basic Kaleidoscope effect (with a few more features than the stock Resolume Kaleidoscope) but for it to work 100% I need to be able to set the extend mode of the texture (mirror, hold, repeat, zero) in the OpenGL section of the plugin. In Touch Designer I simply choose the mode on the GLSL operator but in the FFGL plugin I have to somehow create these modes (I only really need mirror). Also the problem only became apparent after I added the "Pre" parameters (see below).
The second problem is that I have to set the opacity <1 in Resolume otherwise the effect runs in some sort of feedback loop (which kind of looks good but it would be nice to be able to not have to do this). Any ideas?
One other thing, is it possible to get the resolution of the texture into the shader? For the aspect ratio of the effect to be correct I need the aspect ratio of the incoming texture?
Any help would be greatly appreciated.
thanks
Keith
Here's the source:
Code: Select all
#include <FFGL.h>
#include <FFGLLib.h>
#include <FFGLFBO.h>
#include <stdio.h>
#include "glsl_Kaliedoscope.h"
#define FFPARAM_SCALE_FLAG (0)
#define FFPARAM_OFFSETX_FLAG (1)
#define FFPARAM_OFFSETY_FLAG (2)
#define FFPARAM_ORIGINX_FLAG (3)
#define FFPARAM_ORIGINY_FLAG (4)
#define FFPARAM_DIV_FLAG (5)
#define FFPARAM_ANGLE_FLAG (6)
#define FFPARAM_ROTATE_FLAG (7)
#define FFPARAM_PRESCALEX_FLAG (8)
#define FFPARAM_PRESCALEY_FLAG (9)
#define FFPARAM_PREOFFSETX_FLAG (10)
#define FFPARAM_PREOFFSETY_FLAG (11)
#define FFPARAM_PREROTATE_FLAG (12)
static FFGLExtensions glExtensions;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Plugin information
////////////////////////////////////////////////////////////////////////////////////////////////////
static CFFGLPluginInfo PluginInfo (
CEx1::CreateInstance, // Create method
"KKD1", // Plugin unique ID
"Kaleido", // Plugin name
1, // API major version number
000, // API minor version number
1, // Plugin major version number
000, // Plugin minor version number
FF_EFFECT, // Plugin type
"Kaleidoscope by ", // Plugin description
"TryptaFX" // About
);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor and destructor
////////////////////////////////////////////////////////////////////////////////////////////////////
CEx1::CEx1()
{
// Input properties
SetMinInputs(1);
SetMaxInputs(1);
// Parameters
SetParamInfo(FFPARAM_SCALE_FLAG, "Scale", FF_TYPE_STANDARD, 0.1f);
SetParamInfo(FFPARAM_OFFSETX_FLAG, "OffsetX", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_OFFSETY_FLAG, "OffsetY", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_ORIGINX_FLAG, "OriginX", FF_TYPE_STANDARD, 0.5f);
SetParamInfo(FFPARAM_ORIGINY_FLAG, "OriginY", FF_TYPE_STANDARD, 0.5f);
SetParamInfo(FFPARAM_DIV_FLAG, "Divisions", FF_TYPE_STANDARD, 0.3f);
SetParamInfo(FFPARAM_ANGLE_FLAG, "Angle", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_ROTATE_FLAG, "Rotate", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_PRESCALEX_FLAG, "PreScaleX", FF_TYPE_STANDARD, 0.5f);
SetParamInfo(FFPARAM_PRESCALEY_FLAG, "PreScaleY", FF_TYPE_STANDARD, 0.5f);
SetParamInfo(FFPARAM_PREOFFSETX_FLAG, "PreOffsetX", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_PREOFFSETY_FLAG, "PreOffsetY", FF_TYPE_STANDARD, 0.0f);
SetParamInfo(FFPARAM_PREROTATE_FLAG, "PreRotate", FF_TYPE_STANDARD, 0.0f);
m_scale =0.1f;
m_offsetx = m_offsety = m_angle = m_rotate = m_preoffsetx = m_preoffsety = m_prerotate = 0.0f;
m_originx = m_originy = 0.5f;
m_div = 0.3f;
m_prescalex = m_prescaley = 0.5f;
}
CEx1::~CEx1()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Methods
////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD CEx1::ProcessOpenGL(ProcessOpenGLStruct *pGL)
{
if (pGL->numInputTextures<1)
return FF_FAIL;
if (pGL->inputTextures[0]==NULL)
return FF_FAIL;
FFGLTextureStruct &Texture = *(pGL->inputTextures[0]);
//bind the texture handle
glBindTexture(GL_TEXTURE_2D, Texture.Handle);
//enable texturemapping
glEnable(GL_TEXTURE_2D);
//get the max s,t that correspond to the
//width,height of the used portion of the allocated texture space
FFGLTexCoords maxCoords = GetMaxGLTexCoords(Texture);
// Render to screen using our shader
m_shader.BindShader();
// We use TEXTURE0
GLuint sampler_uniform_location = m_shader.FindUniform("color_texture");
glExtensions.glUniform1iARB(sampler_uniform_location, 0);
// Pass our 3 parameters
GLint pos = m_shader.FindUniform("Scale");
glExtensions.glUniform1fARB(pos, m_scale);
pos = m_shader.FindUniform("OffsetX");
glExtensions.glUniform1fARB(pos, m_offsetx);
pos = m_shader.FindUniform("OffsetY");
glExtensions.glUniform1fARB(pos, m_offsety);
pos = m_shader.FindUniform("OriginX");
glExtensions.glUniform1fARB(pos, m_originx);
pos = m_shader.FindUniform("OriginY");
glExtensions.glUniform1fARB(pos, m_originy);
pos = m_shader.FindUniform("Div");
glExtensions.glUniform1fARB(pos, m_div);
pos = m_shader.FindUniform("Angle");
glExtensions.glUniform1fARB(pos, m_angle);
pos = m_shader.FindUniform("Rotate");
glExtensions.glUniform1fARB(pos, m_rotate);
pos = m_shader.FindUniform("PreScaleX");
glExtensions.glUniform1fARB(pos, m_prescalex);
pos = m_shader.FindUniform("PreScaleY");
glExtensions.glUniform1fARB(pos, m_prescaley);
pos = m_shader.FindUniform("PreOffsetX");
glExtensions.glUniform1fARB(pos, m_preoffsetx);
pos = m_shader.FindUniform("PreOffsetY");
glExtensions.glUniform1fARB(pos, m_preoffsety);
pos = m_shader.FindUniform("PreRotate");
glExtensions.glUniform1fARB(pos, m_prerotate);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
//lower left
glTexCoord2d(0.0, 0.0);
glVertex2f(-1,-1);
//upper left
glTexCoord2d(0.0, maxCoords.t);
glVertex2f(-1,1);
//upper right
glTexCoord2d(maxCoords.s, maxCoords.t);
glVertex2f(1,1);
//lower right
glTexCoord2d(maxCoords.s, 0.0);
glVertex2f(1,-1);
glEnd();
//unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
//disable texturemapping
glDisable(GL_TEXTURE_2D);
return FF_SUCCESS;
}
DWORD CEx1::GetParameter(DWORD dwIndex)
{
DWORD dwRet;
switch (dwIndex)
{
case FFPARAM_SCALE_FLAG:
*((float *)(unsigned)(&dwRet)) = m_scale;
return dwRet;
case FFPARAM_OFFSETX_FLAG:
*((float *)(unsigned)(&dwRet)) = m_offsetx;
return dwRet;
case FFPARAM_OFFSETY_FLAG:
*((float *)(unsigned)(&dwRet)) = m_offsety;
return dwRet;
case FFPARAM_ORIGINX_FLAG:
*((float *)(unsigned)(&dwRet)) = m_originx;
return dwRet;
case FFPARAM_ORIGINY_FLAG:
*((float *)(unsigned)(&dwRet)) = m_originy;
return dwRet;
case FFPARAM_DIV_FLAG:
*((float *)(unsigned)(&dwRet)) = m_div;
return dwRet;
case FFPARAM_ANGLE_FLAG:
*((float *)(unsigned)(&dwRet)) = m_angle;
return dwRet;
case FFPARAM_ROTATE_FLAG:
*((float *)(unsigned)(&dwRet)) = m_rotate;
return dwRet;
case FFPARAM_PRESCALEX_FLAG:
*((float *)(unsigned)(&dwRet)) = m_prescalex;
return dwRet;
case FFPARAM_PRESCALEY_FLAG:
*((float *)(unsigned)(&dwRet)) = m_prescaley;
return dwRet;
case FFPARAM_PREOFFSETX_FLAG:
*((float *)(unsigned)(&dwRet)) = m_preoffsetx;
return dwRet;
case FFPARAM_PREOFFSETY_FLAG:
*((float *)(unsigned)(&dwRet)) = m_preoffsety;
return dwRet;
case FFPARAM_PREROTATE_FLAG:
*((float *)(unsigned)(&dwRet)) = m_prerotate;
return dwRet;
default:
return FF_FAIL;
}
}
DWORD CEx1::SetParameter(const SetParameterStruct* pParam)
{
if (pParam == NULL)
return FF_FAIL;
switch (pParam->ParameterNumber)
{
case FFPARAM_SCALE_FLAG:
m_scale = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_OFFSETX_FLAG:
m_offsetx = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_OFFSETY_FLAG:
m_offsety = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_ORIGINX_FLAG:
m_originx = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_ORIGINY_FLAG:
m_originy = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_DIV_FLAG:
m_div = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_ANGLE_FLAG:
m_angle = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_ROTATE_FLAG:
m_rotate = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_PRESCALEX_FLAG:
m_prescalex = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_PRESCALEY_FLAG:
m_prescaley = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_PREOFFSETX_FLAG:
m_preoffsetx = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_PREOFFSETY_FLAG:
m_preoffsety = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
case FFPARAM_PREROTATE_FLAG:
m_prerotate = *((float *)(unsigned)&(pParam->NewParameterValue));
break;
default:
return FF_FAIL;
}
return FF_SUCCESS;
}
DWORD CEx1::InitGL(const FFGLViewportStruct *vp)
{
glExtensions.Initialize();
//AllocConsole();
//freopen("CONOUT$", "a", stderr);
//freopen("CONOUT$", "a", stdout);
m_shader.SetExtensions(&glExtensions);
const char *vertexProgram = "";
const char *fragmentProgram = ""
"uniform float Scale;\n"
"uniform float OffsetX;\n"
"uniform float OffsetY;\n"
"uniform float OriginX;\n"
"uniform float OriginY;\n"
"uniform float Div;\n"
"uniform float Angle;\n"
"uniform float Rotate;\n"
"uniform float PreScaleX;\n"
"uniform float PreScaleY;\n"
"uniform float PreOffsetX;\n"
"uniform float PreOffsetY;\n"
"uniform float PreRotate;\n"
"uniform sampler2D color_texture;\n"
"const float pi=3.1415926;\n"
"vec2 Offset = vec2(OffsetX*2,OffsetY*2);\n"
"vec2 Origin = vec2(OriginX*2,OriginY*2);\n"
"vec2 PreScale = vec2(PreScaleX*2,PreScaleY*2);\n"
"vec2 PreOffset = vec2(PreOffsetX*2,PreOffsetY*2);\n"
"int div = int(Div * 20);\n"
"void main()\n"
"{\n"
// square image for 1.7778 aspect ratio, need resolution to do automatically
" vec2 point = vec2(gl_TexCoord[0].s,gl_TexCoord[0].t*0.5625+((1-.5625)/2));\n"
" vec2 dt = point - Origin + .5;\n"
" float radius = sqrt(dot(dt,dt));\n"
" float theta = atan(dt.y,dt.x)+pi;\n"
" theta += Angle*2*pi;\n"
" float phi = pi/div;\n"
" float modtheta = mod(abs(theta),phi*2.);\n"
" float foldtheta = (phi+Rotate*2*pi)-abs(modtheta-phi);\n"
" vec2 no = vec2(-cos(foldtheta) * radius, -sin(foldtheta) * radius);\n"
" no = (no + 0.5);\n"
" vec2 off = abs((no + Offset*2 + 1)*(Scale*10));\n"
" vec2 modoff = mod(off, 2.0);\n"
" vec2 fold = 1 - abs(modoff-1);\n"
" fold *= 1/PreScale;\n"
" float preRadius = sqrt(dot(fold,fold));\n"
" float preTheta = atan(fold.x,fold.y) + (PreRotate * 2 * pi) + 1.570796;\n"
" fold.x = preRadius * cos(preTheta);\n"
" fold.y = preRadius * sin(preTheta);\n"
" fold += PreOffset;\n"
" gl_FragColor = texture2D(color_texture,fold);\n"
"}\n";
if (!m_shader.Compile(vertexProgram, fragmentProgram))
return FF_FAIL;
return FF_SUCCESS;
}
DWORD CEx1::DeInitGL()
{
m_shader.FreeGLResources();
return FF_SUCCESS;
}