Texture manager rewrite to add sampler support (used by shaders)

Renderer target rewrite to remove FBO support (better fps)
Render to texture support restored
This commit is contained in:
deltaoscarmike
2018-07-22 09:16:06 +02:00
parent 56830d87b1
commit 542900a9c3
21 changed files with 833 additions and 1078 deletions

View File

@ -1,252 +0,0 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: FBO.c,v 1.1.1.1 2005/12/23 18:05:00 psperl Exp $
*
* Render this methods
*/
#include <stdio.h>
#include <iostream>
#include "Common.hpp"
#include "FBO.hpp"
RenderTarget::~RenderTarget() {
glDeleteTextures( 1, &this->textureID[0]);
#ifdef USE_FBO
if (useFBO)
{
glDeleteTextures( 1, &this->textureID[1] );
glDeleteRenderbuffers(1, &this->depthb[0]);
glDeleteFramebuffers(1, &this->fbuffer[0]);
if(renderToTexture)
{
glDeleteTextures( 1, &this->textureID[2] );
glDeleteRenderbuffers(1, &this->depthb[1]);
glDeleteFramebuffers(1, &this->fbuffer[1]);
}
}
#endif
}
GLuint RenderTarget::initRenderToTexture()
{
#ifdef USE_FBO
if (this->useFBO==1)
{
if (this->renderToTexture == 1) {
return this->textureID[2];
}
this->renderToTexture=1;
GLuint fb2, depth_rb2;
glGenFramebuffers(1, &fb2);
glBindFramebuffer( GL_FRAMEBUFFER, fb2 );
this->fbuffer[1] = fb2;
this->depthb[1]= depth_rb2;
glGenTextures(1, &this->textureID[2]);
glBindTexture(GL_TEXTURE_2D, this->textureID[2]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->textureID[2], 0 );
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_COMPLETE) {
return this->textureID[2];
}
std::cerr << "[projecM] warning: initRenderToTexture failed." << std::endl;
}
#endif
return -1;
}
/** Creates new pbuffers */
RenderTarget::RenderTarget(int texsize, int width, int height) : useFBO(false) {
int mindim = 0;
int origtexsize = 0;
this->renderToTexture = 0;
this->texsize = texsize;
#ifdef USE_FBO
useFBO = true;
GLuint fb, depth_rb, rgba_tex, other_tex;
glGenFramebuffers(1, &fb);
glBindFramebuffer( GL_FRAMEBUFFER, fb );
this->fbuffer[0] = fb;
this->depthb[0]= depth_rb;
glGenTextures(1, &other_tex);
glBindTexture(GL_TEXTURE_2D,other_tex);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glGenerateMipmapEXT(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenTextures(1, &rgba_tex);
glBindTexture(GL_TEXTURE_2D, rgba_tex);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glGenerateMipmapEXT(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgba_tex, 0 );
this->textureID[0] = rgba_tex;
this->textureID[1] = other_tex;
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
if (status == GL_FRAMEBUFFER_COMPLETE) {
return;
}
std::cerr << "[projecM] warning: FBO support not detected. Using fallback." << std::endl;
#endif
// Can reach here via two code paths:
// (1) useFBO was set to false externally by cmake / system setting / etc.
// (2) useFBO was true but forced to false as it failed to pass all the GLU extension checks.
/** Fallback pbuffer creation via teximage hack */
/** Check the texture size against the viewport size */
/** If the viewport is smaller, then we'll need to scale the texture size down */
/** If the viewport is larger, scale it up */
mindim = width < height ? width : height;
origtexsize = this->texsize;
this->texsize = nearestPower2( mindim, SCALE_MINIFY );
glGenTextures(1, &this->textureID[0] );
glBindTexture(GL_TEXTURE_2D, this->textureID[0] );
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
this->texsize, this->texsize,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
NULL);
return;
}
/** Locks the pbuffer */
void RenderTarget::lock() {
#ifdef USE_FBO
if(this->useFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, this->fbuffer[0]);
}
#endif
}
/** Unlocks the pbuffer */
void RenderTarget::unlock() {
#ifdef USE_FBO
if(this->useFBO)
{
glBindTexture( GL_TEXTURE_2D, this->textureID[1] );
glCopyTexSubImage2D( GL_TEXTURE_2D,
0, 0, 0, 0, 0,
this->texsize, this->texsize );
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return;
}
#endif
/** Fallback texture path */
glBindTexture( GL_TEXTURE_2D, this->textureID[0] );
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, this->texsize, this->texsize );
}
/**
* Calculates the nearest power of two to the given number using the
* appropriate rule
*/
int RenderTarget::nearestPower2( int value, TextureScale scaleRule ) {
int x = value;
int power = 0;
while ( ( x & 0x01 ) != 1 ) {
x >>= 1;
}
if ( x == 1 ) {
return value;
} else {
x = value;
while ( x != 0 ) {
x >>= 1;
power++;
}
switch ( scaleRule ) {
case SCALE_NEAREST:
if ( ( ( 1 << power ) - value ) <= ( value - ( 1 << ( power - 1 ) ) ) ) {
return 1 << power;
} else {
return 1 << ( power - 1 );
}
case SCALE_MAGNIFY:
return 1 << power;
case SCALE_MINIFY:
return 1 << ( power - 1 );
default:
break;
}
}
return 0;
}

View File

@ -1,71 +0,0 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: FBO.hpp,v 1.1.1.1 2005/12/23 18:05:00 psperl Exp $
*
* Opaque render target
*
*/
#ifndef _RENDERTARGET_H
#define _RENDERTARGET_H
#include "projectM-opengl.h"
typedef enum { SCALE_NEAREST, SCALE_MAGNIFY, SCALE_MINIFY } TextureScale;
class RenderTarget {
public:
/** Texture size */
int texsize;
int useFBO;
int renderToTexture;
~RenderTarget();
RenderTarget( int texsize, int width, int height );
void lock();
void unlock();
GLuint initRenderToTexture();
int nearestPower2( int value, TextureScale scaleRule );
/** Opaque pbuffer context and pbuffer */
/*
#ifdef __APPLE__
void *origContext;
void *pbufferContext;
void *pbuffer;
#endif
*/
/** Render target texture ID for non-pbuffer systems */
GLuint textureID[3];
#ifdef USE_FBO
GLuint fbuffer[2];
GLuint depthb[2];
#endif
};
#endif /** !_RENDERTARGET_H */

View File

@ -6,13 +6,12 @@ libRenderer_la_SOURCES = \
SOIL2/image_helper.c \
SOIL2/SOIL2.c \
SOIL2/etc1_utils.c \
FBO.cpp \
MilkdropWaveform.cpp \
PerPixelMesh.cpp \
Pipeline.cpp \
Renderer.cpp \
ShaderEngine.cpp \
UserTexture.cpp \
Texture.cpp \
Waveform.cpp \
Filters.cpp \
PerlinNoise.cpp \
@ -25,9 +24,9 @@ libRenderer_la_SOURCES = \
RenderItemDistanceMetric.cpp \
RenderItemMatcher.cpp \
BeatDetect.hpp PipelineContext.hpp ShaderEngine.hpp\
FBO.hpp RenderItemDistanceMetric.hpp TextureManager.hpp\
RenderItemDistanceMetric.hpp TextureManager.hpp\
Filters.hpp RenderItemMatcher.hpp Transformation.hpp\
MilkdropWaveform.hpp RenderItemMergeFunction.hpp UserTexture.hpp\
MilkdropWaveform.hpp RenderItemMergeFunction.hpp Texture.hpp\
PerPixelMesh.hpp Renderable.hpp VideoEcho.hpp\
PerlinNoise.hpp Renderer.hpp Waveform.hpp\
Pipeline.hpp Shader.hpp\

View File

@ -1,6 +1,7 @@
#include "Common.hpp"
#include "Renderable.hpp"
#include "Texture.hpp"
#include <math.h>
#include "ShaderEngine.hpp"
#include <glm/gtc/type_ptr.hpp>
@ -179,10 +180,13 @@ void Shape::Draw(RenderContext &context)
{
if (imageUrl !="")
{
GLuint tex= context.textureManager->getTexture(imageUrl);
if (tex != 0)
TextureSamplerDesc tex = context.textureManager->getTexture(imageUrl, GL_CLAMP_TO_EDGE, GL_LINEAR);
if (tex.first != NULL)
{
glBindTexture(GL_TEXTURE_2D, tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex.first->texID);
glBindSampler(0, tex.second->samplerID);
context.aspectRatio=1.0;
}
}
@ -220,10 +224,7 @@ void Shape::Draw(RenderContext &context)
glUseProgram(context.programID_v2f_c4f_t2f);
glActiveTexture(GL_TEXTURE0);
glUniformMatrix4fv(ShaderEngine::Uniform_V2F_C4F_T2F_VertexTranformation(), 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
glUniform1i(ShaderEngine::Uniform_V2F_C4F_T2F_FragTextureSampler(), 0);
glBindVertexArray(m_vaoID_texture);
@ -296,6 +297,9 @@ void Shape::Draw(RenderContext &context)
glDrawArrays(GL_LINE_LOOP,0,sides);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindSampler(0, 0);
if (thickOutline==1) glLineWidth(context.texsize < 512 ? 1 : context.texsize/512);
delete[] buffer_data;

View File

@ -10,16 +10,19 @@
#include <cassert>
#include "omptl/omptl"
#include "omptl/omptl_algorithm"
#include "UserTexture.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
Pipeline* Renderer::currentPipe;
class Preset;
Renderer::Renderer(int width, int height, int gx, int gy, int texsize, BeatDetect *beatDetect, std::string _presetURL,
Renderer::Renderer(int width, int height, int gx, int gy, int _texsize, BeatDetect *_beatDetect, std::string _presetURL,
std::string _titlefontURL, std::string _menufontURL) :
title_fontURL(_titlefontURL), menu_fontURL(_menufontURL), presetURL(_presetURL), m_presetName("None"), vw(width),
vh(height), texsize(texsize), mesh(gx, gy)
vh(height), texsize(_texsize), mesh(gx, gy)
{
int x;
int y;
@ -40,12 +43,12 @@ Renderer::Renderer(int width, int height, int gx, int gy, int texsize, BeatDetec
/** Other stuff... */
this->correction = true;
this->aspect = (float) height / (float) width;;
/// @bug put these on member init list
this->renderTarget = new RenderTarget(texsize, width, height);
this->textureManager = new TextureManager(presetURL);
this->beatDetect = beatDetect;
this->textureManager = NULL;
this->beatDetect = _beatDetect;
textureRenderToTexture = 0;
#ifdef USE_FTGL
/** Load the standard fonts if they do exist */
@ -159,7 +162,6 @@ Renderer::Renderer(int width, int height, int gx, int gy, int texsize, BeatDetec
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
shaderEngine.setParams(renderTarget->texsize, renderTarget->textureID[1], aspect, beatDetect, textureManager);
}
void Renderer::SetPipeline(Pipeline &pipeline)
@ -173,8 +175,6 @@ void Renderer::ResetTextures()
{
textureManager->Clear();
delete (renderTarget);
renderTarget = new RenderTarget(texsize, vw, vh);
reset(vw, vh);
textureManager->Preload();
@ -183,12 +183,11 @@ void Renderer::ResetTextures()
void Renderer::SetupPass1(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
totalframes++;
renderTarget->lock();
glViewport(0, 0, renderTarget->texsize, renderTarget->texsize);
glViewport(0, 0, texsizeX, texsizeY);
renderContext.mat_ortho = glm::ortho(0.0f, 1.0f, 0.0f, 1.0f, -40.0f, 40.0f);
shaderEngine.RenderBlurTextures(pipeline, pipelineContext, renderTarget->texsize);
shaderEngine.RenderBlurTextures(pipeline, pipelineContext);
}
void Renderer::RenderItems(const Pipeline &pipeline, const PipelineContext &pipelineContext)
@ -212,8 +211,8 @@ void Renderer::RenderItems(const Pipeline &pipeline, const PipelineContext &pipe
void Renderer::FinishPass1()
{
draw_title_to_texture();
renderTarget->unlock();
textureManager->updateMainTexture();
}
void Renderer::Pass2(const Pipeline &pipeline, const PipelineContext &pipelineContext)
@ -225,25 +224,14 @@ void Renderer::Pass2(const Pipeline &pipeline, const PipelineContext &pipelineCo
//video texture memory and render fullscreen.
/** Reset the viewport size */
#ifdef USE_FBO
if (renderTarget->renderToTexture)
if (textureRenderToTexture)
{
glBindFramebuffer(GL_FRAMEBUFFER, this->renderTarget->fbuffer[1]);
glViewport(0, 0, this->renderTarget->texsize, this->renderTarget->texsize);
glViewport(0, 0, texsizeX, texsizeY);
}
else
#endif
glViewport(0, 0, this->vw, this->vh);
glViewport(0, 0, this->vw, this->vh);
glBindTexture(GL_TEXTURE_2D, this->renderTarget->textureID[0]);
renderContext.mat_ortho = glm::ortho(-0.5f, 0.5f, -0.5f, 0.5f, -40.0f, 40.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(this->renderTarget->texsize < 512 ? 1 : this->renderTarget->texsize / 512.0);
CompositeOutput(pipeline, pipelineContext);
CompositeOutput(pipeline, pipelineContext);
/* FTGL does not support OpenGL ES
#ifndef EMSCRIPTEN
@ -268,70 +256,44 @@ void Renderer::Pass2(const Pipeline &pipeline, const PipelineContext &pipelineCo
glTranslatef(0.5, 0.5, 0);
*/
#ifdef USE_FBO
if (renderTarget->renderToTexture)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
if (textureRenderToTexture) {
glBindTexture(GL_TEXTURE_2D, textureRenderToTexture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsizeX, texsizeY);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
void Renderer::RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
#ifdef USE_FBO
// when not 'renderToTexture', the user may use its own couple FBO/texture
// so retrieve this external FBO if it exists, (0 means no FBO) and unbind it
GLint externalFBO = 0;
if (!renderTarget->renderToTexture)
{
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &externalFBO);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#endif
SetupPass1(pipeline, pipelineContext);
Interpolation(pipeline, pipelineContext);
RenderItems(pipeline, pipelineContext);
FinishPass1();
#ifdef USE_FBO
// when not 'renderToTexture', the user may use its own couple FBO/texture
// if it exists (0 means no external FBO)
// then rebind it just before calling the final pass: Pass2
if (!renderTarget->renderToTexture && externalFBO != 0)
glBindFramebuffer(GL_FRAMEBUFFER, externalFBO);
#endif
FinishPass1();
Pass2(pipeline, pipelineContext);
}
void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
if (this->renderTarget->useFBO)
glBindTexture(GL_TEXTURE_2D, renderTarget->textureID[1]);
else
glBindTexture(GL_TEXTURE_2D, renderTarget->textureID[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureManager->getMainTexture()->texID);
//Texture wrapping( clamp vs. wrap)
if (pipeline.textureWrap == 0)
{
#ifdef GL_TRANSITION
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#else
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
glActiveTexture(GL_TEXTURE0);
int size = (mesh.height - 1) * mesh.width * 4 * 2;
if (pipeline.staticPerPixel)
@ -357,15 +319,15 @@ void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pi
mesh.Reset();
omptl::transform(mesh.p.begin(), mesh.p.end(), mesh.identity.begin(), mesh.p.begin(), &Renderer::PerPixel);
for (int j = 0; j < mesh.height - 1; j++)
{
for (int j = 0; j < mesh.height - 1; j++)
{
int base = j * mesh.width * 2 * 4;
for (int i = 0; i < mesh.width; i++)
{
for (int i = 0; i < mesh.width; i++)
{
int strip = base + i * 8;
int index = j * mesh.width + i;
int index2 = (j + 1) * mesh.width + i;
int index = j * mesh.width + i;
int index2 = (j + 1) * mesh.width + i;
p[strip + 2] = mesh.p[index].x;
p[strip + 3] = mesh.p[index].y;
@ -374,8 +336,8 @@ void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pi
p[strip + 7] = mesh.p[index2].y;
}
}
}
}
}
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_Interpolation);
@ -385,10 +347,7 @@ void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pi
glBindBuffer(GL_ARRAY_BUFFER, 0);
shaderEngine.enableWarpShader(currentPipe->warpShader, pipeline, pipelineContext);
glUniformMatrix4fv(ShaderEngine::Uniform_V2F_C4F_T2F_VertexTranformation(), 1, GL_FALSE, glm::value_ptr(renderContext.mat_ortho));
glUniform1i(ShaderEngine::Uniform_V2F_C4F_T2F_FragTextureSampler(), 0);
shaderEngine.enableWarpShader(currentPipe->warpShader, pipeline, pipelineContext, renderContext.mat_ortho);
glVertexAttrib4f(1, 1.0, 1.0, 1.0, pipeline.screenDecay);
@ -396,23 +355,19 @@ void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pi
glBindVertexArray(m_vao_Interpolation);
for (int j = 0; j < mesh.height - 1; j++)
glDrawArrays(GL_TRIANGLE_STRIP,j* mesh.width* 2,mesh.width*2);
for (int j = 0; j < mesh.height - 1; j++)
glDrawArrays(GL_TRIANGLE_STRIP,j* mesh.width* 2,mesh.width*2);
glBindVertexArray(0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, 0);
}
Pipeline* Renderer::currentPipe;
Renderer::~Renderer()
{
int x;
if (renderTarget)
delete (renderTarget);
if (textureManager)
delete (textureManager);
@ -437,6 +392,8 @@ Renderer::~Renderer()
glDeleteBuffers(1, &m_vbo_CompositeOutput);
glDeleteVertexArrays(1, &m_vao_CompositeOutput);
glDeleteTextures(1, &textureRenderToTexture);
}
void Renderer::reset(int w, int h)
@ -445,45 +402,53 @@ void Renderer::reset(int w, int h)
this -> vw = w;
this -> vh = h;
shaderEngine.setAspect(aspect);
glCullFace(GL_BACK);
//glFrontFace( GL_CCW );
#ifndef GL_TRANSITION
glEnable(GL_LINE_SMOOTH);
#endif
glClearColor(0, 0, 0, 0);
glViewport(0, 0, w, h);
glEnable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
texsizeX = w;
texsizeY = h;
// snap to 16x16 blocks
texsizeX = ((texsizeX+15)/16)*16;
texsizeY = ((texsizeY+15)/16)*16;
if (textureManager != NULL) {
delete textureManager;
}
textureManager = new TextureManager(presetURL, texsizeX, texsizeY);
shaderEngine.setParams(texsizeX, texsizeY, beatDetect, textureManager);
shaderEngine.reset();
shaderEngine.loadPresetShaders(*currentPipe);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClear(GL_COLOR_BUFFER_BIT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// TODO: how to port this to modern openGL ?
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// if (!this->renderTarget->useFBO)
// {
// this->renderTarget->fallbackRescale(w, h);
// }
}
GLuint Renderer::initRenderToTexture()
{
return renderTarget->initRenderToTexture();
if (textureRenderToTexture == 0) {
glGenTextures(1, &textureRenderToTexture);
glBindTexture(GL_TEXTURE_2D, textureRenderToTexture);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsizeX, texsizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
}
return textureRenderToTexture;
}
void Renderer::draw_title_to_texture()
@ -747,6 +712,15 @@ void Renderer::draw_fps(float realfps)
void Renderer::CompositeOutput(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureManager->getMainTexture()->texID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
renderContext.mat_ortho = glm::ortho(-0.5f, 0.5f, -0.5f, 0.5f, -40.0f, 40.0f);
shaderEngine.enableCompositeShader(currentPipe->compositeShader, pipeline, pipelineContext);
glUniformMatrix4fv(ShaderEngine::Uniform_V2F_C4F_T2F_VertexTranformation(), 1, GL_FALSE, glm::value_ptr(renderContext.mat_ortho));
@ -756,8 +730,6 @@ void Renderer::CompositeOutput(const Pipeline &pipeline, const PipelineContext &
glBlendFunc(GL_ONE, GL_ZERO);
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(m_vao_CompositeOutput);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@ -770,4 +742,37 @@ void Renderer::CompositeOutput(const Pipeline &pipeline, const PipelineContext &
!= pipeline.compositeDrawables.end(); ++pos)
(*pos)->Draw(renderContext);
glBindTexture(GL_TEXTURE_2D, 0);
}
/**
* Calculates the nearest power of two to the given number using the
* appropriate rule
*/
int Renderer::nearestPower2( int value ) {
int x = value;
int power = 0;
while ( ( x & 0x01 ) != 1 ) {
x >>= 1;
}
if ( x == 1 ) {
return value;
} else {
x = value;
while ( x != 0 ) {
x >>= 1;
power++;
}
if ( ( ( 1 << power ) - value ) <= ( value - ( 1 << ( power - 1 ) ) ) ) {
return 1 << power;
} else {
return 1 << ( power - 1 );
}
}
return 0;
}

View File

@ -1,7 +1,6 @@
#ifndef Renderer_HPP
#define Renderer_HPP
#include "FBO.hpp"
#include "BeatDetect.hpp"
#include "Common.hpp"
#include <string>
@ -23,7 +22,7 @@
#endif /** USE_FTGL */
class UserTexture;
class Texture;
class BeatDetect;
class TextureManager;
@ -49,9 +48,10 @@ public:
std::string title;
int drawtitle;
int texsize;
int texsizeX;
int texsizeY;
Renderer( int width, int height, int gx, int gy, int texsize, BeatDetect *beatDetect, std::string presetURL, std::string title_fontURL, std::string menu_fontURL);
Renderer(int width, int height, int gx, int gy, int _texsize, BeatDetect *_beatDetect, std::string presetURL, std::string title_fontURL, std::string menu_fontURL);
~Renderer();
void RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext);
@ -75,7 +75,6 @@ public:
private:
PerPixelMesh mesh;
RenderTarget *renderTarget;
BeatDetect *beatDetect;
TextureManager *textureManager;
static Pipeline* currentPipe;
@ -130,6 +129,10 @@ private:
void draw_title_to_screen(bool flip);
void draw_title_to_texture();
int nearestPower2( int value );
GLuint textureRenderToTexture;
};
#endif

View File

@ -364,12 +364,14 @@ unsigned int
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
unsigned int flags,
int *width,
int *height
)
{
/* variables */
unsigned char* img;
int width, height, channels;
int channels;
unsigned int tex_id;
/* does the user want direct uploading of the image as a DDS file? */
if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
@ -407,7 +409,7 @@ unsigned int
}
/* try to load the image */
img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
img = SOIL_load_image( filename, width, height, &channels, force_channels );
/* channels holds the original number of channels, which may have been forced */
if( (force_channels >= 1) && (force_channels <= 4) )
{
@ -421,7 +423,7 @@ unsigned int
}
/* OK, make it a texture! */
tex_id = SOIL_internal_create_OGL_texture(
img, &width, &height, channels,
img, width, height, channels,
reuse_texture_ID, flags,
GL_TEXTURE_2D, GL_TEXTURE_2D,
GL_MAX_TEXTURE_SIZE );
@ -496,12 +498,14 @@ unsigned int
int buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
unsigned int flags,
int * width,
int * height
)
{
/* variables */
unsigned char* img;
int width, height, channels;
int channels;
unsigned int tex_id;
/* does the user want direct uploading of the image as a DDS file? */
if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
@ -547,7 +551,7 @@ unsigned int
/* try to load the image */
img = SOIL_load_image_from_memory(
buffer, buffer_length,
&width, &height, &channels,
width, height, &channels,
force_channels );
/* channels holds the original number of channels, which may have been forced */
if( (force_channels >= 1) && (force_channels <= 4) )
@ -562,7 +566,7 @@ unsigned int
}
/* OK, make it a texture! */
tex_id = SOIL_internal_create_OGL_texture(
img, &width, &height, channels,
img, width, height, channels,
reuse_texture_ID, flags,
GL_TEXTURE_2D, GL_TEXTURE_2D,
GL_MAX_TEXTURE_SIZE );

View File

@ -166,8 +166,9 @@ unsigned int
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
unsigned int flags,
int *width,
int *height);
/**
Loads 6 images from disk into an OpenGL cubemap texture.
@ -249,7 +250,9 @@ unsigned int
int buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
unsigned int flags,
int * width,
int * height
);
/**

View File

@ -7,6 +7,4 @@
#include "Shader.hpp"
Shader::Shader()
: enabled(false)
{}
Shader::Shader() {}

View File

@ -10,15 +10,13 @@
#include <string>
#include <map>
#include "UserTexture.hpp"
#include "Texture.hpp"
class Shader
{
public:
std::map<std::string, UserTexture*> textures;
bool enabled;
std::map<std::string, TextureSamplerDesc> textures;
std::string programSource;
std::string presetPath;

View File

@ -6,10 +6,11 @@
*/
#include <fstream>
#include <algorithm>
#include "PerlinNoise.hpp"
#include "ShaderEngine.hpp"
#include "BeatDetect.hpp"
#include "Texture.hpp"
#include "HLSLTranslator.hpp"
#include <glm/gtc/type_ptr.hpp>
#ifdef USE_GLES
#define GLSL_VERSION "300 es"
@ -63,7 +64,7 @@ std::string presetCompVertexShader(
"}\n");
std::string v2f_c4f_vert(
const std::string ShaderEngine::v2f_c4f_vert(
"#version "
GLSL_VERSION
"\n"
@ -82,7 +83,7 @@ std::string v2f_c4f_vert(
" fragment_color = vertex_color;\n"
"}\n");
std::string v2f_c4f_frag(
const std::string ShaderEngine::v2f_c4f_frag(
"#version "
GLSL_VERSION
"\n"
@ -95,7 +96,7 @@ std::string v2f_c4f_frag(
" color = fragment_color;\n"
"}\n");
std::string v2f_c4f_t2f_vert(
const std::string ShaderEngine::v2f_c4f_t2f_vert(
"#version "
GLSL_VERSION
"\n"
@ -114,7 +115,7 @@ std::string v2f_c4f_t2f_vert(
" fragment_texture = vertex_texture;\n"
"}\n");
std::string v2f_c4f_t2f_frag(
const std::string ShaderEngine::v2f_c4f_t2f_frag(
"#version "
GLSL_VERSION
"\n"
@ -133,10 +134,6 @@ std::string v2f_c4f_t2f_frag(
std::string PresetShaderIncludes = ""
// "float2 a = 1.0 + 2.0 * 3.0 + 4.0;\n"
// "float2 _uv, dx, dy, _c7;\n"
// "float2 uv_y =(_uv.xy)-( float2(0,-1.2) + float2(dx.y,dy.y)*8 + float2(dx.x,dy.x)*4 )*(_c7).zw;\n"
"#define M_PI 3.14159265359\n"
"#define M_PI_2 6.28318530718\n"
"#define M_INV_PI_2 0.159154943091895\n"
@ -432,114 +429,14 @@ bool ShaderEngine::checkCompileStatus(GLuint shader, const std::string & shaderT
return false;
}
void ShaderEngine::setParams(const int texsize, const unsigned int texId, const float aspect, BeatDetect *beatDetect,
TextureManager *textureManager)
void ShaderEngine::setParams(const int _texsizeX, const int _texsizeY, BeatDetect *_beatDetect,
TextureManager *_textureManager)
{
mainTextureId = texId;
this->beatDetect = beatDetect;
this->textureManager = textureManager;
this->aspect = aspect;
this->texsize = texsize;
this->beatDetect = _beatDetect;
this->textureManager = _textureManager;
textureManager->setTexture("main", texId, texsize, texsize);
#ifndef GL_TRANSITION
glGenTextures(1, &blur1_tex);
glBindTexture(GL_TEXTURE_2D, blur1_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texsize/2, texsize/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &blur2_tex);
glBindTexture(GL_TEXTURE_2D, blur2_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texsize / 4, texsize / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &blur3_tex);
glBindTexture(GL_TEXTURE_2D, blur3_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texsize / 8, texsize / 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#endif
blur1_enabled = false;
blur2_enabled = false;
blur3_enabled = false;
//std::cout << "Generating Noise Textures" << std::endl;
PerlinNoise noise;
#ifndef GL_TRANSITION
glGenTextures(1, &noise_texture_lq_lite);
glBindTexture(GL_TEXTURE_2D, noise_texture_lq_lite);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_lq_lite);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noise_lq_lite", noise_texture_lq_lite, 32, 32);
glGenTextures(1, &noise_texture_lq);
glBindTexture(GL_TEXTURE_2D, noise_texture_lq);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_lq);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noise_lq", noise_texture_lq, 256, 256);
glGenTextures(1, &noise_texture_mq);
glBindTexture(GL_TEXTURE_2D, noise_texture_mq);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_mq);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noise_mq", noise_texture_mq, 256, 256);
glGenTextures(1, &noise_texture_hq);
glBindTexture(GL_TEXTURE_2D, noise_texture_hq);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_hq);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noise_hq", noise_texture_hq, 256, 256);
glGenTextures(1, &noise_texture_perlin);
glBindTexture(GL_TEXTURE_2D, noise_texture_perlin);
glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_perlin);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noise_perlin", noise_texture_perlin, 512, 512);
glGenTextures( 1, &noise_texture_lq_vol );
glBindTexture( GL_TEXTURE_3D, noise_texture_lq_vol );
glTexImage3D(GL_TEXTURE_3D,0,4,32,32,32,0,GL_LUMINANCE,GL_FLOAT,noise.noise_lq_vol);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noisevol_lq", noise_texture_lq_vol, 256, 256);
glGenTextures( 1, &noise_texture_hq_vol );
glBindTexture( GL_TEXTURE_3D, noise_texture_hq_vol );
glTexImage3D(GL_TEXTURE_3D,0,4,32,32,32,0,GL_LUMINANCE,GL_FLOAT,noise.noise_hq_vol);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
textureManager->setTexture("noisevol_hq", noise_texture_hq_vol, 8, 8);
#endif
this->texsizeX = _texsizeX;
this->texsizeY = _texsizeY;
}
// compile a user-defined shader from a preset. returns program ID if successful.
@ -592,24 +489,6 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha
pmShader.textures.clear();
std::vector<std::string> standard_samplers = {
"main",
"fc_main",
"pc_main",
"fw_main",
"pw_main",
"noise_lq",
"noise_lq_lite",
"noise_mq",
"noise_hq",
"noisevol_lq",
"noisevol_hq",
"blur1",
"blur2",
"blur3",
};
// set up texture samplers for all samplers references in the shader program
found = 0;
found = program.find("sampler_", found);
@ -621,117 +500,98 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha
if (end != std::string::npos)
{
std::string sampler = program.substr((int) found, (int) end - found);
UserTexture* texture = new UserTexture(sampler);
std::string lowerCaseName(sampler);
std::transform(lowerCaseName.begin(), lowerCaseName.end(), lowerCaseName.begin(), tolower);
texture->texID = textureManager->getTexture(texture->name);
if (texture->texID != 0)
TextureSamplerDesc texDesc = textureManager->getTexture(sampler, GL_REPEAT, GL_LINEAR);
if (texDesc.first == NULL)
{
texture->width = textureManager->getTextureWidth(texture->name);
texture->height = textureManager->getTextureHeight(texture->name);
}
else
{
// Insert uniform keyword for GLSL sampler declarations
std::string sampler_lowercase(sampler);
std::transform(sampler_lowercase.begin(), sampler_lowercase.end(), sampler_lowercase.begin(), ::tolower);
std::vector<std::string>::iterator it = standard_samplers.begin();
it = std::find(standard_samplers.begin(), standard_samplers.end(), sampler_lowercase);
// Declare a uniform for sampler defined in preset but out from the shader body
if (it == standard_samplers.end() && found < program_start) {
int index = found;
while(index >= 0 && program[index] != '\n') { index--; }
program.insert(index+1, "uniform ");
found += 8;
program_start += 8;
}
if (sampler.substr(0, 4) == "rand")
if (lowerCaseName.substr(0, 4) == "rand")
{
std::string random_name = textureManager->getRandomTextureName(texture->name);
std::string random_name = textureManager->getRandomTextureName(lowerCaseName);
if (random_name.size() > 0)
{
texture->texID = textureManager->getTexture(random_name);
texture->width = textureManager->getTextureWidth(random_name);
texture->height = textureManager->getTextureHeight(random_name);
texDesc = textureManager->getTexture(random_name, GL_REPEAT, GL_LINEAR);
}
}
else
{
std::string extensions[6];
extensions[0] = ".jpg";
extensions[1] = ".dds";
extensions[2] = ".png";
extensions[3] = ".tga";
extensions[4] = ".bmp";
extensions[5] = ".dib";
for (int x = 0; x < 6; x++)
{
std::string filename = texture->name + extensions[x];
texture->texID = textureManager->getTexture(filename);
if (texture->texID != 0)
{
texture->width = textureManager->getTextureWidth(filename);
texture->height = textureManager->getTextureHeight(filename);
break;
}
}
texDesc = textureManager->tryLoadingTexture(sampler);
}
}
if (texture->texID != 0 && pmShader.textures.find(texture->qname) == pmShader.textures.end())
pmShader.textures[texture->qname] = texture;
if (texDesc.first == NULL)
{
std::cerr << "Texture loading error for: " << sampler << std::endl;
}
else
delete (texture);
{
// The shader declares a new sampler -> declaring it with a "uniform" outside the shader body
if (texDesc.first->userTexture) {
if (found < program_start) {
int index = found;
while(index >= 0 && program[index] != '\n') { index--; }
program.insert(index+1, "uniform ");
found += 8;
program_start += 8;
}
}
// Add built-in textures
// Add user textures only if used
if (!texDesc.first->userTexture || found > program_start)
{
std::map<std::string, TextureSamplerDesc>::const_iterator iter = pmShader.textures.cbegin();
for ( ; iter != pmShader.textures.cend(); ++iter)
{
if (iter->first == sampler)
break;
}
if (iter == pmShader.textures.cend())
pmShader.textures[sampler] = texDesc;
}
}
}
found = program.find("sampler_", found);
}
textureManager->clearRandomTextures();
// add texture size vars
found = 0;
found = program.find("texsize_", found);
while (found != std::string::npos)
{
found += 8;
size_t end = program.find_first_of(" ;.,\n\r)", found);
if (end != std::string::npos)
{
std::string tex = program.substr((int) found, (int) end - found);
if (pmShader.textures.find(tex) != pmShader.textures.end())
{
UserTexture* texture = pmShader.textures[tex];
texture->texsizeDefined = true;
//std::cout << "texsize_" << tex << " found" << std::endl;
}
}
found = program.find("texsize_", found);
}
// blur programs
blur1_enabled = false;
blur2_enabled = false;
blur3_enabled = false;
if (program.find("GetMain") != std::string::npos || program.find("GetPixel") != std::string::npos)
{
pmShader.textures["main"] = textureManager->getTexture("main", GL_REPEAT, GL_LINEAR);
}
found = program.find("GetBlur3");
if (found != std::string::npos)
{
blur1_enabled = blur2_enabled = blur3_enabled = true;
pmShader.textures["blur3"] = textureManager->getTexture("blur3", GL_CLAMP_TO_EDGE, GL_LINEAR);
}
else
{
found = program.find("GetBlur2");
if (found != std::string::npos)
{
blur1_enabled = blur2_enabled = true;
pmShader.textures["blur2"] = textureManager->getTexture("blur2", GL_CLAMP_TO_EDGE, GL_LINEAR);
}
else
{
found = program.find("GetBlur1");
if (found != std::string::npos)
{
blur1_enabled = true;
pmShader.textures["blur1"] = textureManager->getTexture("blur1", GL_CLAMP_TO_EDGE, GL_LINEAR);
}
}
}
@ -838,71 +698,49 @@ void ShaderEngine::SetupShaderVariables(GLuint program, const Pipeline &pipeline
glProgramUniform1f(program, glGetUniformLocation(program, "vol"), beatDetect->vol);
glProgramUniform1f(program, glGetUniformLocation(program, "vol_att"), beatDetect->vol);
glProgramUniform4f(program, glGetUniformLocation(program, "texsize"), texsize, texsize, 1 / (float) texsize, 1 / (float) texsize);
glProgramUniform4f(program, glGetUniformLocation(program, "aspect"), 1 / aspect, 1, aspect, 1);
glProgramUniform4f(program, glGetUniformLocation(program, "texsize"), texsizeX, texsizeY, 1 / (float) texsizeX, 1 / (float) texsizeY);
glProgramUniform4f(program, glGetUniformLocation(program, "aspect"), 1 / aspectX, 1, aspectX, 1);
/*
if (blur1_enabled)
{
cgGLSetTextureParameter(program, glGetUniformLocation(program, "sampler_blur1"), blur1_tex);
cgGLEnableTextureParameter(program, glGetUniformLocation(program, "sampler_blur1"));
}
if (blur2_enabled)
{
cgGLSetTextureParameter(glGetUniformLocation(program, "sampler_blur2"), blur2_tex);
cgGLEnableTextureParameter(glGetUniformLocation(program, "sampler_blur2"));
}
if (blur3_enabled)
{
cgGLSetTextureParameter(glGetUniformLocation(program, "sampler_blur3"), blur3_tex);
cgGLEnableTextureParameter(glGetUniformLocation(program, "sampler_blur3"));
}
*/
}
void ShaderEngine::setupUserTexture(GLuint program, const UserTexture* texture)
void ShaderEngine::SetupTextures(GLuint program, const Shader &shader)
{
std::string samplerName = "sampler_" + texture->qname;
// FIXME: check if each texture binding will overwrite previous one
uint texNum = 0;
for (std::map<std::string, TextureSamplerDesc>::const_iterator iter = shader.textures.begin(); iter
!= shader.textures.end(); ++iter)
{
std::string texName = iter->first;
Texture * texture = iter->second.first;
Sampler * sampler = iter->second.second;
std::string samplerName = "sampler_" + texName;
// https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Binding_textures_to_samplers
GLint param = glGetUniformLocation(program, samplerName.c_str());
if (param < 0) {
// FIXME: turn this on and fix it.
// i think sampler names are carrying over from previous shaders...
// std::cerr << "invalid uniform name " << samplerName << std::endl;
return;
}
// https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Binding_textures_to_samplers
GLint param = glGetUniformLocation(program, samplerName.c_str());
if (param < 0) {
// unused uniform have been optimized out by glsl compiler
continue;
}
glUniform1i(param, 0);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, texture->texID);
glActiveTexture(GL_TEXTURE0 + texNum);
glBindTexture(texture->type, texture->texID);
glBindSampler(texNum, sampler->samplerID);
if (texture->texsizeDefined)
{
std::string texsizeName = "texsize_" + texture->name;
glUniform1i(param, texNum);
std::string texsizeName = "texsize_" + texName;
GLint textSizeParam = glGetUniformLocation(program, texsizeName.c_str());
if (param >= 0) {
glProgramUniform4f(program, textSizeParam, texture->width, texture->height,
1 / (float) texture->width, 1 / (float) texture->height);
} else {
std::cerr << "invalid texsizeName " << texsizeName << std::endl;
std::cerr << "invalid texsize name " << texsizeName << std::endl;
return;
}
}
}
void ShaderEngine::setupUserTextureState(GLuint program, const UserTexture* texture)
{
glBindTexture(GL_TEXTURE_2D, texture->texID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texture->bilinear ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture->bilinear ? GL_LINEAR : GL_NEAREST);
#ifndef GL_TRANSITION
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture->wrap ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture->wrap ? GL_REPEAT : GL_CLAMP_TO_EDGE);
#endif
texNum++;
}
}
void ShaderEngine::SetupShaderQVariables(GLuint program, const Pipeline &q)
@ -924,12 +762,7 @@ void ShaderEngine::SetupShaderQVariables(GLuint program, const Pipeline &q)
}
}
void ShaderEngine::setAspect(float aspect)
{
this->aspect = aspect;
}
void ShaderEngine::RenderBlurTextures(const Pipeline &pipeline, const PipelineContext &pipelineContext, const int texsize)
void ShaderEngine::RenderBlurTextures(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
#ifndef GL_TRANSITION
if (blur1_enabled || blur2_enabled || blur3_enabled)
@ -1058,19 +891,24 @@ bool ShaderEngine::linkProgram(GLuint programID) {
return false;
}
#pragma mark Preset Shaders
void ShaderEngine::loadPresetShaders(Pipeline &pipeline) {
/*
// compile and link warp and composite shaders from pipeline
programID_presetWarp = loadPresetShader(PresentWarpShader, pipeline.warpShader, pipeline.warpShaderFilename);
programID_presetComp = loadPresetShader(PresentCompositeShader, pipeline.compositeShader, pipeline.compositeShaderFilename);
if (!pipeline.compositeShader.programSource.empty()) {
programID_presetComp = loadPresetShader(PresentCompositeShader, pipeline.compositeShader, pipeline.compositeShaderFilename);
if (programID_presetComp != GL_FALSE)
presetCompShaderLoaded = true;
}
if (programID_presetComp != GL_FALSE)
presetCompShaderLoaded = true;
if (programID_presetWarp != GL_FALSE)
presetWarpShaderLoaded = true;
if (!pipeline.warpShader.programSource.empty()) {
programID_presetWarp = loadPresetShader(PresentWarpShader, pipeline.warpShader, pipeline.warpShaderFilename);
if (programID_presetWarp != GL_FALSE) {
uniform_vertex_transf_warp_shader = glGetUniformLocation(programID_presetWarp, "vertex_transformation");
presetWarpShaderLoaded = true;
}
}
*/
std::cout << "Preset composite shader active: " << presetCompShaderLoaded << ", preset warp shader active: " << presetWarpShaderLoaded << std::endl;
}
@ -1082,14 +920,7 @@ GLuint ShaderEngine::loadPresetShader(const ShaderEngine::PresentShaderType shad
return GL_FALSE;
}
// pass texture info from preset to shader
for (auto &userTexture : presetShader.textures) {
setupUserTextureState(program, userTexture.second);
setupUserTexture(program, userTexture.second);
}
return program;
}
// deactivate preset shaders
@ -1173,40 +1004,43 @@ GLuint ShaderEngine::CompileShaderProgram(const std::string & VertexShaderCode,
// use the appropriate shader program for rendering the interpolation.
// it will use the preset shader if available, otherwise the textured shader
void ShaderEngine::enableWarpShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext) {
if (presetWarpShaderLoaded && PRESET_SHADERS_ENABLED) {
bool ShaderEngine::enableWarpShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext, const glm::mat4 & mat_ortho) {
if (presetWarpShaderLoaded) {
glUseProgram(programID_presetWarp);
for (std::map<std::string, UserTexture*>::const_iterator pos = shader.textures.begin(); pos != shader.textures.end(); ++pos)
setupUserTextureState(programID_presetWarp, pos->second);
for (std::map<std::string, UserTexture*>::const_iterator pos = shader.textures.begin(); pos
!= shader.textures.end(); ++pos)
setupUserTexture(programID_presetWarp, pos->second);
SetupTextures(programID_presetWarp, shader);
SetupShaderVariables(programID_presetWarp, pipeline, pipelineContext);
SetupShaderQVariables(programID_presetWarp, pipeline);
} else {
glUseProgram(programID_v2f_c4f_t2f);
glUniformMatrix4fv(uniform_vertex_transf_warp_shader, 1, GL_FALSE, glm::value_ptr(mat_ortho));
return true;
}
glUseProgram(programID_v2f_c4f_t2f);
glUniformMatrix4fv(ShaderEngine::Uniform_V2F_C4F_T2F_VertexTranformation(), 1, GL_FALSE, glm::value_ptr(mat_ortho));
glUniform1i(ShaderEngine::Uniform_V2F_C4F_T2F_FragTextureSampler(), 0);
return false;
}
void ShaderEngine::enableCompositeShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext) {
if (presetCompShaderLoaded && PRESET_SHADERS_ENABLED) {
bool ShaderEngine::enableCompositeShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext) {
if (presetCompShaderLoaded) {
glUseProgram(programID_presetComp);
for (std::map<std::string, UserTexture*>::const_iterator pos = shader.textures.begin(); pos != shader.textures.end(); ++pos)
setupUserTextureState(programID_presetComp, pos->second);
for (std::map<std::string, UserTexture*>::const_iterator pos = shader.textures.begin(); pos
!= shader.textures.end(); ++pos)
setupUserTexture(programID_presetComp, pos->second);
SetupTextures(programID_presetComp, shader);
SetupShaderVariables(programID_presetComp, pipeline, pipelineContext);
SetupShaderQVariables(programID_presetComp, pipeline);
} else {
glUseProgram(programID_v2f_c4f_t2f);
return true;
}
glUseProgram(programID_v2f_c4f_t2f);
return false;
}

View File

@ -8,8 +8,6 @@
#ifndef SHADERENGINE_HPP_
#define SHADERENGINE_HPP_
#define PRESET_SHADERS_ENABLED 1
#include "Common.hpp"
#include "projectM-opengl.h"
@ -24,6 +22,8 @@ class ShaderEngine;
#include <map>
#include <sstream>
#include "Shader.hpp"
class ShaderEngine
{
public:
@ -38,13 +38,16 @@ public:
ShaderEngine();
virtual ~ShaderEngine();
void loadPresetShaders(Pipeline &pipeline);
void enableWarpShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext);
void enableCompositeShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext);
void RenderBlurTextures(const Pipeline &pipeline, const PipelineContext &pipelineContext, const int texsize);
void setAspect(float aspect);
void setParams(const int texsize, const unsigned int texId, const float aspect, BeatDetect *beatDetect, TextureManager *textureManager);
bool enableWarpShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext, const glm::mat4 & mat_ortho);
bool enableCompositeShader(Shader &shader, const Pipeline &pipeline, const PipelineContext &pipelineContext);
void RenderBlurTextures(const Pipeline &pipeline, const PipelineContext &pipelineContext);
void setParams(const int _texsizeX, const int texsizeY, BeatDetect *beatDetect, TextureManager *_textureManager);
void reset();
static GLuint CompileShaderProgram(const std::string & VertexShaderCode, const std::string & FragmentShaderCode, const std::string & shaderTypeString);
static bool checkCompileStatus(GLuint shader, const std::string & shaderTitle);
static bool linkProgram(GLuint programID);
static GLint Uniform_V2F_C4F_VertexTranformation() { return UNIFORM_V2F_C4F_VERTEX_TRANFORMATION; }
static GLint Uniform_V2F_C4F_VertexPointSize() { return UNIFORM_V2F_C4F_VERTEX_POINT_SIZE; }
static GLint Uniform_V2F_C4F_T2F_VertexTranformation() { return UNIFORM_V2F_C4F_T2F_VERTEX_TRANFORMATION; }
@ -53,20 +56,24 @@ public:
GLuint programID_v2f_c4f;
GLuint programID_v2f_c4f_t2f;
const static std::string v2f_c4f_vert;
const static std::string v2f_c4f_frag;
const static std::string v2f_c4f_t2f_vert;
const static std::string v2f_c4f_t2f_frag;
private:
unsigned int mainTextureId;
int texsize;
float aspect;
int texsizeX;
int texsizeY;
float aspectX;
float aspectY;
BeatDetect *beatDetect;
TextureManager *textureManager;
GLint uniform_vertex_transf_warp_shader;
GLuint noise_texture_lq_lite;
GLuint noise_texture_lq;
GLuint noise_texture_mq;
GLuint noise_texture_hq;
GLuint noise_texture_perlin;
GLuint noise_texture_lq_vol;
GLuint noise_texture_hq_vol;
GLuint programID_warp_fallback;
GLuint programID_comp_fallback;
GLuint programID_blur1;
GLuint programID_blur2;
bool blur1_enabled;
bool blur2_enabled;
@ -79,11 +86,8 @@ private:
void SetupShaderQVariables(GLuint program, const Pipeline &q);
void SetupShaderVariables(GLuint program, const Pipeline &pipeline, const PipelineContext &pipelineContext);
void setupUserTexture(GLuint program, const UserTexture* texture);
void setupUserTextureState(GLuint program, const UserTexture* texture);
void SetupTextures(GLuint program, const Shader &shader);
GLuint compilePresetShader(const ShaderEngine::PresentShaderType shaderType, Shader &shader, const std::string &shaderFilename);
bool checkCompileStatus(GLuint shader, const std::string & shaderTitle);
bool linkProgram(GLuint programID);
void disablePresetShaders();
GLuint loadPresetShader(const PresentShaderType shaderType, Shader &shader, std::string &shaderFilename);
@ -92,14 +96,9 @@ private:
// programs generated from preset shader code
GLuint programID_presetComp, programID_presetWarp;
GLuint programID_blur1, programID_blur2;
bool presetCompShaderLoaded, presetWarpShaderLoaded;
GLuint CompileShaderProgram(const std::string & VertexShaderCode, const std::string & FragmentShaderCode, const std::string & shaderTypeString);
static GLint UNIFORM_V2F_C4F_VERTEX_TRANFORMATION;
static GLint UNIFORM_V2F_C4F_VERTEX_POINT_SIZE;
static GLint UNIFORM_V2F_C4F_T2F_VERTEX_TRANFORMATION;

View File

@ -0,0 +1,70 @@
#include "Texture.hpp"
Sampler::Sampler(const GLint _wrap_mode, const GLint _filter_mode) :
wrap_mode(_wrap_mode),
filter_mode(_filter_mode)
{
glGenSamplers(1, &samplerID);
glSamplerParameteri(samplerID, GL_TEXTURE_MIN_FILTER, _filter_mode);
glSamplerParameteri(samplerID, GL_TEXTURE_MAG_FILTER, _filter_mode);
glSamplerParameteri(samplerID, GL_TEXTURE_WRAP_S, _wrap_mode);
glSamplerParameteri(samplerID, GL_TEXTURE_WRAP_T, _wrap_mode);
}
Sampler::~Sampler()
{
glDeleteSamplers(1, &samplerID);
}
Texture::Texture(const int _width, const int _height, const bool _userTexture) :
type(GL_TEXTURE_2D),
width(_width),
height(_height),
userTexture(_userTexture)
{
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
}
Texture::Texture(const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture) :
texID(_texID),
type(_type),
width(_width),
height(_height),
userTexture(_userTexture)
{
}
Texture::~Texture()
{
glDeleteTextures(1, &texID);
for(std::vector<Sampler*>::const_iterator iter = samplers.begin(); iter != samplers.end(); iter++)
{
delete (*iter);
}
}
Sampler* Texture::getSampler(const GLint _wrap_mode, const GLint _filter_mode)
{
for(std::vector<Sampler*>::const_iterator iter = samplers.begin(); iter != samplers.end(); iter++)
{
if ((*iter)->wrap_mode == _wrap_mode && (*iter)->filter_mode == _filter_mode)
{
return *iter;
}
}
// Sampler not found -> adding it
Sampler * sampler = new Sampler(_wrap_mode, _filter_mode);
samplers.push_back(sampler);
return sampler;
}

View File

@ -0,0 +1,42 @@
#ifndef TEXTURE_HPP_
#define TEXTURE_HPP_
#include <string>
#include <vector>
#include "projectM-opengl.h"
class Sampler
{
public:
GLuint samplerID;
GLint wrap_mode;
GLint filter_mode;
Sampler(const GLint _wrap_mode, const GLint _filter_mode);
~Sampler();
};
class Texture
{
public:
GLuint texID;
GLenum type;
int width;
int height;
bool userTexture;
std::vector<Sampler*> samplers;
Texture(const int _width, const int _height, const bool _userTexture);
Texture(const GLuint _texID, const GLenum _type, const int _width, const int _height, const bool _userTexture);
~Texture();
Sampler *getSampler(const GLint _wrap_mode, const GLint _filter_mode);
};
typedef std::pair<Texture*, Sampler*> TextureSamplerDesc;
#endif /* TEXTURE_HPP_ */

View File

@ -1,10 +1,9 @@
#include <algorithm>
#include <vector>
#include "projectM-opengl.h"
#ifdef USE_DEVIL
#include <IL/ilut.h>
#else
#include "SOIL2/SOIL2.h"
#endif
#ifdef WIN32
#include "win32-dirent.h"
@ -23,253 +22,347 @@
#include "TextureManager.hpp"
#include "Common.hpp"
#include "IdleTextures.hpp"
#include "Texture.hpp"
#include "PerlinNoise.hpp"
TextureManager::TextureManager(const std::string _presetURL): presetURL(_presetURL)
TextureManager::TextureManager(const std::string _presetsURL, const int texsizeX, const int texsizeY):
presetsURL(_presetsURL)
{
#ifdef USE_DEVIL
ilInit();
iluInit();
ilutInit();
ilutRenderer(ILUT_OPENGL);
#endif
extensions.push_back(".jpg");
extensions.push_back(".dds");
extensions.push_back(".png");
extensions.push_back(".tga");
extensions.push_back(".bmp");
extensions.push_back(".dib");
Preload();
loadTextureDir();
Preload();
loadTextureDir();
// Create main texture ans associated samplers
mainTexture = new Texture(texsizeX, texsizeY, false);
mainTexture->getSampler(GL_REPEAT, GL_LINEAR);
mainTexture->getSampler(GL_REPEAT, GL_NEAREST);
mainTexture->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
mainTexture->getSampler(GL_CLAMP_TO_EDGE, GL_NEAREST);
textures["main"] = mainTexture;
PerlinNoise noise;
GLuint noise_texture_lq_lite;
glGenTextures(1, &noise_texture_lq_lite);
glBindTexture(GL_TEXTURE_2D, noise_texture_lq_lite);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_lq_lite);
Texture * textureNoise_lq_lite = new Texture(noise_texture_lq_lite, GL_TEXTURE_2D, 32, 32, false);
textureNoise_lq_lite->getSampler(GL_REPEAT, GL_LINEAR);
textures["noise_lq_lite"] = textureNoise_lq_lite;
GLuint noise_texture_lq;
glGenTextures(1, &noise_texture_lq);
glBindTexture(GL_TEXTURE_2D, noise_texture_lq);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_lq);
Texture * textureNoise_lq = new Texture(noise_texture_lq, GL_TEXTURE_2D, 256, 256, false);
textureNoise_lq->getSampler(GL_REPEAT, GL_LINEAR);
textures["noise_lq"] = textureNoise_lq;
GLuint noise_texture_mq;
glGenTextures(1, &noise_texture_mq);
glBindTexture(GL_TEXTURE_2D, noise_texture_mq);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_mq);
Texture * textureNoise_mq = new Texture(noise_texture_mq, GL_TEXTURE_2D, 256, 256, false);
textureNoise_mq->getSampler(GL_REPEAT, GL_LINEAR);
textures["noise_mq"] = textureNoise_mq;
GLuint noise_texture_hq;
glGenTextures(1, &noise_texture_hq);
glBindTexture(GL_TEXTURE_2D, noise_texture_hq);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_hq);
Texture * textureNoise_hq = new Texture(noise_texture_hq, GL_TEXTURE_2D, 256, 256, false);
textureNoise_hq->getSampler(GL_REPEAT, GL_LINEAR);
textures["noise_hq"] = textureNoise_hq;
GLuint noise_texture_lq_vol;
glGenTextures( 1, &noise_texture_lq_vol );
glBindTexture( GL_TEXTURE_3D, noise_texture_lq_vol );
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 32 ,32 ,32 ,0 ,GL_LUMINANCE ,GL_FLOAT ,noise.noise_lq_vol);
Texture * textureNoise_lq_vol = new Texture(noise_texture_lq_vol, GL_TEXTURE_3D, 32, 32, false);
textureNoise_lq_vol->getSampler(GL_REPEAT, GL_LINEAR);
textures["noisevol_lq"] = textureNoise_lq_vol;
GLuint noise_texture_hq_vol;
glGenTextures( 1, &noise_texture_hq_vol );
glBindTexture( GL_TEXTURE_3D, noise_texture_hq_vol );
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 32, 32, 32, 0, GL_LUMINANCE, GL_FLOAT, noise.noise_hq_vol);
Texture * textureNoise_hq_vol = new Texture(noise_texture_hq_vol, GL_TEXTURE_3D, 32, 32, false);
textureNoise_hq_vol->getSampler(GL_REPEAT, GL_LINEAR);
textures["noisevol_hq"] = textureNoise_hq_vol;
}
TextureManager::~TextureManager()
{
Clear();
Clear();
}
void TextureManager::Preload()
{
int width, height;
#ifdef USE_DEVIL
ILuint image;
ilGenImages(1, &image);
ilBindImage(image);
ilLoadL(IL_TYPE_UNKNOWN,(ILvoid*) M_data, M_bytes);
GLuint tex = ilutGLBindTexImage();
#else
unsigned int tex = SOIL_load_OGL_texture_from_memory(
M_data,
M_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
unsigned int tex = SOIL_load_OGL_texture_from_memory(
M_data,
M_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MULTIPLY_ALPHA
,&width,&height);
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MULTIPLY_ALPHA
// | SOIL_FLAG_COMPRESS_TO_DXT
);
#endif
textures["M.tga"]=tex;
Texture * newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true);
newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
textures["M.tga"] = newTex;
#ifdef USE_DEVIL
ilLoadL(IL_TYPE_UNKNOWN,(ILvoid*) project_data,project_bytes);
tex = ilutGLBindTexImage();
#else
tex = SOIL_load_OGL_texture_from_memory(
project_data,
project_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
// tex = SOIL_load_OGL_texture_from_memory(
// project_data,
// project_bytes,
// SOIL_LOAD_AUTO,
// SOIL_CREATE_NEW_ID,
// SOIL_FLAG_POWER_OF_TWO
// | SOIL_FLAG_MULTIPLY_ALPHA
// ,&width,&height);
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MULTIPLY_ALPHA
//| SOIL_FLAG_COMPRESS_TO_DXT
);
#endif
// newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true);
// newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
// textures["project.tga"] = newTex;
// textures["project.tga"]=tex;
tex = SOIL_load_OGL_texture_from_memory(
headphones_data,
headphones_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MULTIPLY_ALPHA
,&width,&height);
#ifdef USE_DEVIL
ilLoadL(IL_TYPE_UNKNOWN,(ILvoid*) headphones_data, headphones_bytes);
tex = ilutGLBindTexImage();
#else
tex = SOIL_load_OGL_texture_from_memory(
headphones_data,
headphones_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO
| SOIL_FLAG_MULTIPLY_ALPHA
// | SOIL_FLAG_COMPRESS_TO_DXT
);
#endif
textures["headphones.tga"]=tex;
newTex = new Texture(tex, GL_TEXTURE_2D, width, height, true);
newTex->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
textures["headphones.tga"] = newTex;
}
void TextureManager::Clear()
{
for(std::map<std::string, Texture*>::const_iterator iter = textures.begin(); iter != textures.end(); iter++)
delete(iter->second);
textures.clear();
}
for(std::map<std::string, GLuint>::const_iterator iter = textures.begin(); iter != textures.end(); iter++)
TextureSamplerDesc TextureManager::getTexture(const std::string fullName, const GLenum defaultWrap, const GLenum defaultFilter)
{
std::string name;
GLint wrap_mode;
GLint filter_mode;
ExtractTextureSettings(fullName, wrap_mode, filter_mode, name);
if (textures.find(name) == textures.end())
{
glDeleteTextures(1,&iter->second);
return {NULL, NULL};
}
textures.clear();
if (fullName == name) {
// Warp and filter mode not specified in sampler name
// applying default
wrap_mode = defaultWrap;
filter_mode = defaultFilter;
}
Texture * texture = textures[name];
Sampler * sampler = texture->getSampler(wrap_mode, filter_mode);
return {texture, sampler};
}
void TextureManager::setTexture(const std::string name, const unsigned int texId, const int width, const int height)
TextureSamplerDesc TextureManager::tryLoadingTexture(const std::string name)
{
textures[name] = texId;
widths[name] = width;
heights[name] = height;
}
TextureSamplerDesc texDesc;
//void TextureManager::unloadTextures(const PresetOutputs::cshape_container &shapes)
//{
/*
for (PresetOutputs::cshape_container::const_iterator pos = shapes.begin();
pos != shapes.end(); ++pos)
for (size_t x = 0; x < extensions.size(); x++)
{
std::string filename = name + extensions[x];
std::string fullURL = presetsURL + PATH_SEPARATOR + filename;
if( (*pos)->enabled==1)
{
texDesc = loadTexture(name, fullURL);
if ( (*pos)->textured)
{
std::string imageUrl = (*pos)->getImageUrl();
if (imageUrl != "")
{
std::string fullUrl = presetURL + "/" + imageUrl;
ReleaseTexture(LoadTexture(fullUrl.c_str()));
}
}
}
if (texDesc.first != NULL)
{
break;
}
}
*/
//}
GLuint TextureManager::getTexture(const std::string filename)
{
std::string fullURL = presetURL + PATH_SEPARATOR + filename;
return getTextureFullpath(filename,fullURL);
return texDesc;
}
GLuint TextureManager::getTextureFullpath(const std::string filename, const std::string imageURL)
TextureSamplerDesc TextureManager::loadTexture(const std::string name, const std::string fileName)
{
int width, height;
if (textures.find(filename)!= textures.end())
{
return textures[filename];
}
else
{
unsigned int tex = SOIL_load_OGL_texture(
fileName.c_str(),
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MULTIPLY_ALPHA
,&width,&height);
#ifdef USE_DEVIL
GLuint tex = ilutGLLoadImage((char *)imageURL.c_str());
#else
int width, height;
if (tex == 0)
{
return {NULL, NULL};
}
unsigned int tex = SOIL_load_OGL_texture(
imageURL.c_str(),
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
Texture * newTexture = new Texture(tex, GL_TEXTURE_2D, width, height, true);
Sampler * sampler = newTexture->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
//SOIL_FLAG_POWER_OF_TWO
// SOIL_FLAG_MIPMAPS
SOIL_FLAG_MULTIPLY_ALPHA
//| SOIL_FLAG_COMPRESS_TO_DXT
//| SOIL_FLAG_DDS_LOAD_DIRECT
//,&width,&height);
);
textures[name] = newTexture;
#endif
textures[filename]=tex;
widths[filename]=width;
heights[filename]=height;
return tex;
}
return {newTexture, sampler};
}
int TextureManager::getTextureWidth(const std::string imageURL)
{
return widths[imageURL];
}
int TextureManager::getTextureHeight(const std::string imageURL)
{
return heights[imageURL];
}
unsigned int TextureManager::getTextureMemorySize()
{
return 0;
}
void TextureManager::loadTextureDir()
{
std::string dirname = "/usr/local/share/projectM/textures";
std::string dirname = std::string(DATADIR_PATH) + "/presets";
DIR * m_dir;
DIR * m_dir;
// Allocate a new a stream given the current directory name
if ((m_dir = opendir(dirname.c_str())) == NULL)
{
std::cout<<"No Textures Loaded from "<<dirname<<std::endl;
return; // no files loaded. m_entries is empty
}
// Allocate a new a stream given the current directory name
if ((m_dir = opendir(dirname.c_str())) == NULL)
{
std::cout<<"No Textures Loaded from "<<dirname<<std::endl;
return; // no files loaded. m_entries is empty
}
struct dirent * dir_entry;
struct dirent * dir_entry;
while ((dir_entry = readdir(m_dir)) != NULL)
{
while ((dir_entry = readdir(m_dir)) != NULL)
{
// Convert char * to friendly string
std::string filename(dir_entry->d_name);
// Convert char * to friendly string
std::string filename(dir_entry->d_name);
if (filename.length() > 0 && filename[0] == '.')
continue;
if (filename.length() > 0 && filename[0] == '.')
continue;
std::string lowerCaseFileName(filename);
std::transform(lowerCaseFileName.begin(), lowerCaseFileName.end(), lowerCaseFileName.begin(), tolower);
// Create full path name
std::string fullname = dirname + PATH_SEPARATOR + filename;
// Remove extension
for (size_t x = 0; x < extensions.size(); x++)
{
size_t found = lowerCaseFileName.find(extensions[x]);
if (found != std::string::npos)
{
std::string name = filename;
name.replace(int(found), extensions[x].size(), "");
unsigned int texId = getTextureFullpath(filename, fullname);
if(texId != 0)
{
user_textures.push_back(texId);
textures[filename]=texId;
user_texture_names.push_back(filename);
}
}
// Create full path name
std::string fullname = dirname + PATH_SEPARATOR + filename;
loadTexture(name, fullname);
if (m_dir)
{
closedir(m_dir);
m_dir = 0;
}
break;
}
}
}
if (m_dir)
{
closedir(m_dir);
m_dir = 0;
}
}
std::string TextureManager::getRandomTextureName(std::string random_id)
{
if (user_texture_names.size() > 0)
{
std::string random_name = user_texture_names[rand() % user_texture_names.size()];
random_textures.push_back(random_id);
textures[random_id] = textures[random_name];
return random_name;
}
else return "";
std::vector<std::string> user_texture_names;
for(std::map<std::string, Texture*>::const_iterator iter = textures.begin(); iter != textures.end(); iter++)
{
if (iter->second->userTexture) {
user_texture_names.push_back(iter->first);
}
}
if (user_texture_names.size() > 0)
{
std::string random_name = user_texture_names[rand() % user_texture_names.size()];
random_textures.push_back(random_id);
textures[random_id] = textures[random_name];
return random_name;
}
else return "";
}
void TextureManager::clearRandomTextures()
{
for (std::vector<std::string>::iterator pos = random_textures.begin(); pos != random_textures.end(); ++pos)
{
textures.erase(*pos);
widths.erase(*pos);
heights.erase(*pos);
}
random_textures.clear();
for (std::vector<std::string>::iterator pos = random_textures.begin(); pos != random_textures.end(); ++pos)
{
textures.erase(*pos);
}
random_textures.clear();
}
void TextureManager::ExtractTextureSettings(const std::string qualifiedName, GLint & _wrap_mode, GLint & _filter_mode, std::string & name)
{
std::string lowerQualifiedName(qualifiedName);
std::transform(lowerQualifiedName.begin(), lowerQualifiedName.end(), lowerQualifiedName.begin(), tolower);
_wrap_mode = GL_REPEAT;
_filter_mode = GL_LINEAR;
if (lowerQualifiedName.substr(0,3) == "fc_")
{
name = qualifiedName.substr(3);
_filter_mode = GL_LINEAR;
_wrap_mode = GL_CLAMP_TO_EDGE;
}
else if (lowerQualifiedName.substr(0,3) == "fw_")
{
name = qualifiedName.substr(3);
_filter_mode = GL_LINEAR;
_wrap_mode = GL_REPEAT;
}
else if (lowerQualifiedName.substr(0,3) == "pc_")
{
name = qualifiedName.substr(3);
_filter_mode = GL_NEAREST;
_wrap_mode = GL_CLAMP_TO_EDGE;
}
else if (lowerQualifiedName.substr(0,3) == "pw_")
{
name = qualifiedName.substr(3);
_filter_mode = GL_NEAREST;
_wrap_mode = GL_REPEAT;
}
else
{
name = qualifiedName;
}
}
const Texture * TextureManager::getMainTexture() const {
return mainTexture;
}
const std::vector<Texture*> & TextureManager::getBlurTextures() const {
return blurTextures;
}
void TextureManager::updateMainTexture()
{
glBindTexture(GL_TEXTURE_2D, mainTexture->texID);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, mainTexture->width, mainTexture->height);
glBindTexture(GL_TEXTURE_2D, 0);
}

View File

@ -5,29 +5,36 @@
#include <string>
#include <map>
#include <vector>
#include "projectM-opengl.h"
#include "Texture.hpp"
class TextureManager
{
std::string presetURL;
std::map<std::string,unsigned int> textures;
std::map<std::string,unsigned int> heights;
std::map<std::string,unsigned int> widths;
std::vector<unsigned int> user_textures;
std::vector<std::string> user_texture_names;
std::string presetsURL;
std::map<std::string, Texture*> textures;
std::vector<Texture*> blurTextures;
Texture * mainTexture;
std::vector<std::string> random_textures;
void loadTextureDir();
TextureSamplerDesc loadTexture(const std::string name, const std::string imageUrl);
void ExtractTextureSettings(const std::string qualifiedName, GLint &_wrap_mode, GLint &_filter_mode, std::string & name);
std::vector<std::string> extensions;
public:
TextureManager(std::string _presetsURL, const int texsizeX, const int texsizeY);
~TextureManager();
TextureManager(std::string _presetURL);
//void unloadTextures(const PresetOutputs::cshape_container &shapes);
void Clear();
void Preload();
unsigned int getTexture(const std::string filenamne);
unsigned int getTextureFullpath(const std::string filename, const std::string imageUrl);
unsigned int getTextureMemorySize();
int getTextureWidth(const std::string imageUrl);
int getTextureHeight(const std::string imageUrl);
void setTexture(const std::string name, const unsigned int texId, const int width, const int height);
void loadTextureDir();
TextureSamplerDesc tryLoadingTexture(const std::string name);
TextureSamplerDesc getTexture(const std::string fullName, const GLenum defaultWrap, const GLenum defaultFilter);
const Texture * getMainTexture() const;
const std::vector<Texture *> & getBlurTextures() const;
void updateMainTexture();
std::string getRandomTextureName(std::string rand_name);
void clearRandomTextures();
};

View File

@ -1,50 +0,0 @@
/*
* UserTexture.cpp
*
* Created on: Jul 16, 2008
* Author: pete
*/
#include "UserTexture.hpp"
UserTexture::UserTexture(std::string qualifiedName): qname(qualifiedName)
{
if (qualifiedName.substr(0,3) == "fc_")
{
name = qualifiedName.substr(3);
bilinear = true;
wrap = false;
}
else if (qualifiedName.substr(0,3) == "fw_")
{
name = qualifiedName.substr(3);
bilinear = true;
wrap = true;
}
else if (qualifiedName.substr(0,3) == "pc_")
{
name = qualifiedName.substr(3);
bilinear = false;
wrap = false;
}
else if (qualifiedName.substr(0,3) == "pw_")
{
name = qualifiedName.substr(3);
bilinear = false;
wrap = true;
}
else
{
name = qualifiedName;
bilinear = true;
wrap = true;
}
texsizeDefined = false;
}
UserTexture::~UserTexture()
{
// TODO Auto-generated destructor stub
}

View File

@ -1,34 +0,0 @@
/*
* UserTexture.hpp
*
* Created on: Jul 16, 2008
* Author: pete
*/
#ifndef USERTEXTURE_HPP_
#define USERTEXTURE_HPP_
#include <string>
class UserTexture
{
public:
bool wrap;
bool bilinear;
bool texsizeDefined;
int width;
int height;
unsigned int texID;
std::string qname;
std::string name;
UserTexture(std::string qualifiedName);
virtual ~UserTexture();
};
#endif /* USERTEXTURE_HPP_ */

View File

@ -84,12 +84,9 @@ void VideoEcho::Draw(RenderContext &context)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glUseProgram(context.programID_v2f_c4f_t2f);
glUniformMatrix4fv(ShaderEngine::Uniform_V2F_C4F_T2F_VertexTranformation(), 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
glUniform1i(ShaderEngine::Uniform_V2F_C4F_T2F_FragTextureSampler(), 0);

View File

@ -6,6 +6,9 @@
//
#include "pmSDL.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Renderer/ShaderEngine.hpp"
void projectMSDL::audioInputCallbackF32(void *userdata, unsigned char *stream, int len) {
projectMSDL *app = (projectMSDL *) userdata;
@ -211,6 +214,11 @@ void projectMSDL::renderFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
projectM::renderFrame();
if (renderToTexture) {
renderTexture();
}
SDL_GL_SwapWindow(win);
}
@ -228,15 +236,107 @@ projectMSDL::projectMSDL(std::string config_file, int flags) : projectM(config_f
isFullScreen = false;
}
void projectMSDL::init(SDL_Window *window, SDL_GLContext *_glCtx) {
void projectMSDL::init(SDL_Window *window, SDL_GLContext *_glCtx, const bool _renderToTexture) {
win = window;
glCtx = _glCtx;
selectRandom(true);
projectM_resetGL(width, height);
renderToTexture = _renderToTexture;
if (renderToTexture) {
programID = ShaderEngine::CompileShaderProgram(ShaderEngine::v2f_c4f_t2f_vert, ShaderEngine::v2f_c4f_t2f_frag, "v2f_c4f_t2f");
textureID = projectM::initRenderToTexture();
float points[16] = {
-0.8, -0.8,
0.0, 0.0,
-0.8, 0.8,
0.0, 1.0,
0.8, -0.8,
1.0, 0.0,
0.8, 0.8,
1.0, 1.0,
};
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, points, GL_DYNAMIC_DRAW);
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)0); // Positions
glDisableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)(sizeof(float)*2)); // Textures
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
std::string projectMSDL::getActivePresetName()
{
return std::string("hey");
unsigned int index = 0;
if (selectedPresetIndex(index)) {
return getPresetName(index);
}
return std::string();
}
void projectMSDL::renderTexture() {
static int frame = 0;
frame++;
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glUseProgram(programID);
glUniform1i(glGetUniformLocation(programID, "texture_sampler"), 0);
glm::mat4 mat_proj = glm::frustum(-1.0f, 1.0f, -1.0f, 1.0f, 2.0f, 10.0f);
glEnable(GL_DEPTH_TEST);
glm::mat4 mat_model = glm::mat4(1.0f);
mat_model = glm::translate(mat_model, glm::vec3(cos(frame*0.023),
cos(frame*0.017),
-5+sin(frame*0.022)*2));
mat_model = glm::rotate(mat_model, glm::radians((float) sin(frame*0.0043)*360),
glm::vec3(sin(frame*0.0017),
sin(frame *0.0032),
1));
glm::mat4 mat_transf = glm::mat4(1.0f);
mat_transf = mat_proj * mat_model;
glUniformMatrix4fv(glGetUniformLocation(programID, "vertex_transformation"), 1, GL_FALSE, glm::value_ptr(mat_transf));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glDisable(GL_DEPTH_TEST);
}

View File

@ -35,7 +35,7 @@ public:
projectMSDL(Settings settings, int flags);
projectMSDL(std::string config_file, int flags);
void init(SDL_Window *window, SDL_GLContext *glCtx);
void init(SDL_Window *window, SDL_GLContext *glCtx, const bool renderToTexture = false);
int openAudioInput();
void beginAudioCapture();
void endAudioCapture();
@ -54,6 +54,11 @@ private:
projectM::Settings settings;
SDL_AudioDeviceID audioInputDevice;
unsigned int width, height;
bool renderToTexture;
GLuint programID = 0;
GLuint m_vbo = 0;
GLuint m_vao = 0;
GLuint textureID = 0;
// audio input device characteristics
unsigned short audioChannelsCount;
@ -67,6 +72,7 @@ private:
void keyHandler(SDL_Event *);
SDL_AudioDeviceID selectAudioInput(int count);
void renderTexture();
};