From 542900a9c3e8bd47e6c7bd66ab04a2fc0aeeac5c Mon Sep 17 00:00:00 2001 From: deltaoscarmike <37912794+deltaoscarmike@users.noreply.github.com> Date: Sun, 22 Jul 2018 09:16:06 +0200 Subject: [PATCH] Texture manager rewrite to add sampler support (used by shaders) Renderer target rewrite to remove FBO support (better fps) Render to texture support restored --- src/libprojectM/Renderer/FBO.cpp | 252 ----------- src/libprojectM/Renderer/FBO.hpp | 71 --- src/libprojectM/Renderer/Makefile.am | 7 +- src/libprojectM/Renderer/Renderable.cpp | 16 +- src/libprojectM/Renderer/Renderer.cpp | 223 +++++----- src/libprojectM/Renderer/Renderer.hpp | 13 +- src/libprojectM/Renderer/SOIL2/SOIL2.c | 20 +- src/libprojectM/Renderer/SOIL2/SOIL2.h | 9 +- src/libprojectM/Renderer/Shader.cpp | 4 +- src/libprojectM/Renderer/Shader.hpp | 6 +- src/libprojectM/Renderer/ShaderEngine.cpp | 428 ++++++------------ src/libprojectM/Renderer/ShaderEngine.hpp | 51 ++- src/libprojectM/Renderer/Texture.cpp | 70 +++ src/libprojectM/Renderer/Texture.hpp | 42 ++ src/libprojectM/Renderer/TextureManager.cpp | 461 ++++++++++++-------- src/libprojectM/Renderer/TextureManager.hpp | 37 +- src/libprojectM/Renderer/UserTexture.cpp | 50 --- src/libprojectM/Renderer/UserTexture.hpp | 34 -- src/libprojectM/Renderer/VideoEcho.cpp | 3 - src/projectM-sdl/pmSDL.cpp | 106 ++++- src/projectM-sdl/pmSDL.hpp | 8 +- 21 files changed, 833 insertions(+), 1078 deletions(-) delete mode 100755 src/libprojectM/Renderer/FBO.cpp delete mode 100755 src/libprojectM/Renderer/FBO.hpp create mode 100644 src/libprojectM/Renderer/Texture.cpp create mode 100644 src/libprojectM/Renderer/Texture.hpp delete mode 100644 src/libprojectM/Renderer/UserTexture.cpp delete mode 100644 src/libprojectM/Renderer/UserTexture.hpp diff --git a/src/libprojectM/Renderer/FBO.cpp b/src/libprojectM/Renderer/FBO.cpp deleted file mode 100755 index 7f8efb7ca..000000000 --- a/src/libprojectM/Renderer/FBO.cpp +++ /dev/null @@ -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 -#include -#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; - } diff --git a/src/libprojectM/Renderer/FBO.hpp b/src/libprojectM/Renderer/FBO.hpp deleted file mode 100755 index 158d3f115..000000000 --- a/src/libprojectM/Renderer/FBO.hpp +++ /dev/null @@ -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 */ diff --git a/src/libprojectM/Renderer/Makefile.am b/src/libprojectM/Renderer/Makefile.am index 7a181dff0..d79535119 100644 --- a/src/libprojectM/Renderer/Makefile.am +++ b/src/libprojectM/Renderer/Makefile.am @@ -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\ diff --git a/src/libprojectM/Renderer/Renderable.cpp b/src/libprojectM/Renderer/Renderable.cpp index 200983f01..b32324fbf 100644 --- a/src/libprojectM/Renderer/Renderable.cpp +++ b/src/libprojectM/Renderer/Renderable.cpp @@ -1,6 +1,7 @@ #include "Common.hpp" #include "Renderable.hpp" +#include "Texture.hpp" #include #include "ShaderEngine.hpp" #include @@ -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; diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index 1a0107d3c..a6737e01c 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -10,16 +10,19 @@ #include #include "omptl/omptl" #include "omptl/omptl_algorithm" -#include "UserTexture.hpp" #include #include + +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; +} + + diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index 333e509f8..4cc299a74 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -1,7 +1,6 @@ #ifndef Renderer_HPP #define Renderer_HPP -#include "FBO.hpp" #include "BeatDetect.hpp" #include "Common.hpp" #include @@ -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 diff --git a/src/libprojectM/Renderer/SOIL2/SOIL2.c b/src/libprojectM/Renderer/SOIL2/SOIL2.c index 3feab5fb4..5aaec161b 100644 --- a/src/libprojectM/Renderer/SOIL2/SOIL2.c +++ b/src/libprojectM/Renderer/SOIL2/SOIL2.c @@ -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 ); diff --git a/src/libprojectM/Renderer/SOIL2/SOIL2.h b/src/libprojectM/Renderer/SOIL2/SOIL2.h index 7b022d03e..731997e29 100755 --- a/src/libprojectM/Renderer/SOIL2/SOIL2.h +++ b/src/libprojectM/Renderer/SOIL2/SOIL2.h @@ -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 ); /** diff --git a/src/libprojectM/Renderer/Shader.cpp b/src/libprojectM/Renderer/Shader.cpp index 1ffb11926..9bea3bba4 100644 --- a/src/libprojectM/Renderer/Shader.cpp +++ b/src/libprojectM/Renderer/Shader.cpp @@ -7,6 +7,4 @@ #include "Shader.hpp" -Shader::Shader() - : enabled(false) - {} +Shader::Shader() {} diff --git a/src/libprojectM/Renderer/Shader.hpp b/src/libprojectM/Renderer/Shader.hpp index 00093e65b..bccf5ecfc 100644 --- a/src/libprojectM/Renderer/Shader.hpp +++ b/src/libprojectM/Renderer/Shader.hpp @@ -10,15 +10,13 @@ #include #include -#include "UserTexture.hpp" +#include "Texture.hpp" class Shader { public: - std::map textures; - - bool enabled; + std::map textures; std::string programSource; std::string presetPath; diff --git a/src/libprojectM/Renderer/ShaderEngine.cpp b/src/libprojectM/Renderer/ShaderEngine.cpp index 33c0ac172..35e3d85af 100644 --- a/src/libprojectM/Renderer/ShaderEngine.cpp +++ b/src/libprojectM/Renderer/ShaderEngine.cpp @@ -6,10 +6,11 @@ */ #include #include -#include "PerlinNoise.hpp" #include "ShaderEngine.hpp" #include "BeatDetect.hpp" +#include "Texture.hpp" #include "HLSLTranslator.hpp" +#include #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 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::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::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::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::const_iterator pos = shader.textures.begin(); pos != shader.textures.end(); ++pos) - setupUserTextureState(programID_presetWarp, pos->second); - - for (std::map::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::const_iterator pos = shader.textures.begin(); pos != shader.textures.end(); ++pos) - setupUserTextureState(programID_presetComp, pos->second); - - for (std::map::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; } + + diff --git a/src/libprojectM/Renderer/ShaderEngine.hpp b/src/libprojectM/Renderer/ShaderEngine.hpp index 32f653e66..01cef511e 100644 --- a/src/libprojectM/Renderer/ShaderEngine.hpp +++ b/src/libprojectM/Renderer/ShaderEngine.hpp @@ -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 #include #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; diff --git a/src/libprojectM/Renderer/Texture.cpp b/src/libprojectM/Renderer/Texture.cpp new file mode 100644 index 000000000..f2c7b8a60 --- /dev/null +++ b/src/libprojectM/Renderer/Texture.cpp @@ -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::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::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; +} diff --git a/src/libprojectM/Renderer/Texture.hpp b/src/libprojectM/Renderer/Texture.hpp new file mode 100644 index 000000000..04bc9d5eb --- /dev/null +++ b/src/libprojectM/Renderer/Texture.hpp @@ -0,0 +1,42 @@ +#ifndef TEXTURE_HPP_ +#define TEXTURE_HPP_ + +#include +#include +#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 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 TextureSamplerDesc; + +#endif /* TEXTURE_HPP_ */ diff --git a/src/libprojectM/Renderer/TextureManager.cpp b/src/libprojectM/Renderer/TextureManager.cpp index c853caf45..0f2fd1007 100644 --- a/src/libprojectM/Renderer/TextureManager.cpp +++ b/src/libprojectM/Renderer/TextureManager.cpp @@ -1,10 +1,9 @@ +#include +#include + #include "projectM-opengl.h" -#ifdef USE_DEVIL -#include -#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::const_iterator iter = textures.begin(); iter != textures.end(); iter++) + delete(iter->second); + + textures.clear(); +} - for(std::map::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 "<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 user_texture_names; + + for(std::map::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::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::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 & 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); +} diff --git a/src/libprojectM/Renderer/TextureManager.hpp b/src/libprojectM/Renderer/TextureManager.hpp index fb87c594b..649d56585 100644 --- a/src/libprojectM/Renderer/TextureManager.hpp +++ b/src/libprojectM/Renderer/TextureManager.hpp @@ -5,29 +5,36 @@ #include #include #include +#include "projectM-opengl.h" +#include "Texture.hpp" + class TextureManager { - std::string presetURL; - std::map textures; - std::map heights; - std::map widths; - std::vector user_textures; - std::vector user_texture_names; + std::string presetsURL; + std::map textures; + std::vector blurTextures; + Texture * mainTexture; + std::vector 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 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 & getBlurTextures() const; + + void updateMainTexture(); + std::string getRandomTextureName(std::string rand_name); void clearRandomTextures(); }; diff --git a/src/libprojectM/Renderer/UserTexture.cpp b/src/libprojectM/Renderer/UserTexture.cpp deleted file mode 100644 index a280d4ca0..000000000 --- a/src/libprojectM/Renderer/UserTexture.cpp +++ /dev/null @@ -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 -} diff --git a/src/libprojectM/Renderer/UserTexture.hpp b/src/libprojectM/Renderer/UserTexture.hpp deleted file mode 100644 index 19fdc634d..000000000 --- a/src/libprojectM/Renderer/UserTexture.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * UserTexture.hpp - * - * Created on: Jul 16, 2008 - * Author: pete - */ - -#ifndef USERTEXTURE_HPP_ -#define USERTEXTURE_HPP_ - -#include - -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_ */ diff --git a/src/libprojectM/Renderer/VideoEcho.cpp b/src/libprojectM/Renderer/VideoEcho.cpp index 03919a617..a0ea32127 100644 --- a/src/libprojectM/Renderer/VideoEcho.cpp +++ b/src/libprojectM/Renderer/VideoEcho.cpp @@ -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); diff --git a/src/projectM-sdl/pmSDL.cpp b/src/projectM-sdl/pmSDL.cpp index 10b411fd0..f7dbb5a0f 100644 --- a/src/projectM-sdl/pmSDL.cpp +++ b/src/projectM-sdl/pmSDL.cpp @@ -6,6 +6,9 @@ // #include "pmSDL.hpp" +#include +#include +#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); +} + diff --git a/src/projectM-sdl/pmSDL.hpp b/src/projectM-sdl/pmSDL.hpp index cd6916d64..42c271ff2 100644 --- a/src/projectM-sdl/pmSDL.hpp +++ b/src/projectM-sdl/pmSDL.hpp @@ -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(); };