FFGL texture extend mode method

FFGL, OSC, GLSL. If you like abbreviations, this is the forum for you
Post Reply
Trypta
Is taking Resolume on a second date
Posts: 26
Joined: Fri Nov 02, 2012 20:32

FFGL texture extend mode method

Post by Trypta »

I'm just in the process of learning of FFGL and have run into a small problem with a FFGL plugin that uses a shader that I designed in Touch. The shader works perfectly in Touch Designer and almost works perfectly in FFGL but I'm having two small problems. I'm currently going through various tutorials for C++, and OpenGL (I do have quite a bit of experience with GLSL) but I'm not sure where/when I'll find the solutions and I would like to post this effect asap because it is almost working perfectly.

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;
}


Joris
Doesn't Know Jack about VJ'ing or Software Development and Mostly Just Gets Coffee for Everyone
Posts: 5185
Joined: Fri May 22, 2009 11:38

Re: FFGL texture extend mode method

Post by Joris »

I need to be able to set the extend mode of the texture
Take a look at GL_TEXTURE_WRAP (which can be set to MIRRORED_REPEAT).
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?
Could it be because you're not unbinding the shader?
One other thing, is it possible to get the resolution of the texture into the shader?
Yes, you can use glGetTexLevelParameter to get the width and height and then pass that as a variable.

Trypta
Is taking Resolume on a second date
Posts: 26
Joined: Fri Nov 02, 2012 20:32

Re: FFGL texture extend mode method

Post by Trypta »

Thanks for the info, I was able to find the solutions to the first two problems (I thought I posted that but I must have forgotten to press submit).

I'll add the glGetTexLevelParameter call right away though thanks. I was looking for a function that does this.

I've actually uploaded the shader to the general chat forum but I'll add the new variable and then upload an updated version.

viewtopic.php?f=5&t=10008


Thanks for the tips.
Keith

Trypta
Is taking Resolume on a second date
Posts: 26
Joined: Fri Nov 02, 2012 20:32

Re: FFGL texture extend mode method

Post by Trypta »

Hi so I think I'm pretty close to getting the value but something is wrong with my method, I think I'm just getting a value of zero.

Below is the code I have inside of the init function

Code: Select all

  GLint width = 0;
  GLint height = 0;
  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
  m_extensions.glUniform1iARB(m_resolutionXLocation, width);
  m_extensions.glUniform1iARB(m_resolutionYLocation, height);
Any ideas what I'm doing wrong?

thanks
Keith

Trypta
Is taking Resolume on a second date
Posts: 26
Joined: Fri Nov 02, 2012 20:32

Re: FFGL texture extend mode method

Post by Trypta »

Scratch the last post. I've got it. I had placed the call inside of InitGL function rather than processOpenGL function. It now works fine.

thanks
Keith

Post Reply