mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-02-07 17:15:44 +00:00
1033 lines
30 KiB
C++
1033 lines
30 KiB
C++
#include "Renderer.hpp"
|
|
#include "wipemalloc.h"
|
|
#include "math.h"
|
|
#include "Common.hpp"
|
|
#include "KeyHandler.hpp"
|
|
#include "TextureManager.hpp"
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <sys/stat.h>
|
|
#include <cassert>
|
|
#include "omptl/omptl"
|
|
#include "omptl/omptl_algorithm"
|
|
#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, 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), mesh(gx, gy)
|
|
{
|
|
this->totalframes = 1;
|
|
this->noSwitch = false;
|
|
this->showfps = false;
|
|
this->showtitle = false;
|
|
this->showpreset = false;
|
|
this->showhelp = false;
|
|
this->showstats = false;
|
|
this->studio = false;
|
|
this->realfps = 0;
|
|
|
|
this->drawtitle = 0;
|
|
|
|
//this->title = "Unknown";
|
|
|
|
/** Other stuff... */
|
|
this->correction = true;
|
|
|
|
/// @bug put these on member init list
|
|
this->textureManager = NULL;
|
|
this->beatDetect = _beatDetect;
|
|
|
|
textureRenderToTexture = 0;
|
|
|
|
#ifdef USE_FTGL
|
|
/** Load the standard fonts if they do exist */
|
|
struct stat buffer;
|
|
|
|
if (stat( title_fontURL.c_str(), &buffer )) {
|
|
std::cout << "Could not open font file: " << title_fontURL << std::endl;
|
|
exit(1);
|
|
}
|
|
if (stat( menu_fontURL.c_str(), &buffer )) {
|
|
std::cout << "Could not open font file: " << menu_fontURL << std::endl;
|
|
exit(1);
|
|
}
|
|
|
|
title_font = new FTGLPixmapFont(title_fontURL.c_str());
|
|
other_font = new FTGLPixmapFont(menu_fontURL.c_str());
|
|
poly_font = new FTGLExtrdFont(title_fontURL.c_str());
|
|
|
|
if(title_font->Error()) {
|
|
fprintf(stderr, "Failed to open font %s\n", title_fontURL.c_str());
|
|
} else {
|
|
title_font->UseDisplayList(true);
|
|
}
|
|
|
|
other_font->UseDisplayList(true);
|
|
|
|
if(poly_font->Error()) {
|
|
fprintf(stderr, "Failed to open font %s\n", title_fontURL.c_str());
|
|
} else {
|
|
poly_font->UseDisplayList(true);
|
|
poly_font->Depth(20);
|
|
poly_font->FaceSize(72);
|
|
}
|
|
|
|
#endif /** USE_FTGL */
|
|
|
|
|
|
int size = (mesh.height - 1) *mesh.width * 4 * 2;
|
|
p = ( float * ) wipemalloc ( size * sizeof ( float ) );
|
|
|
|
|
|
for (int j = 0; j < mesh.height - 1; j++)
|
|
{
|
|
int base = j * mesh.width * 4 * 2;
|
|
|
|
|
|
for (int i = 0; i < mesh.width; i++)
|
|
{
|
|
int index = j * mesh.width + i;
|
|
int index2 = (j + 1) * mesh.width + i;
|
|
|
|
int strip = base + i * 8;
|
|
p[strip + 0] = mesh.identity[index].x;
|
|
p[strip + 1] = mesh.identity[index].y;
|
|
|
|
p[strip + 4] = mesh.identity[index2].x;
|
|
p[strip + 5] = mesh.identity[index2].y;
|
|
}
|
|
}
|
|
|
|
renderContext.programID_v2f_c4f = shaderEngine.programID_v2f_c4f;
|
|
renderContext.programID_v2f_c4f_t2f = shaderEngine.programID_v2f_c4f_t2f;
|
|
|
|
renderContext.uniform_v2f_c4f_vertex_tranformation = shaderEngine.uniform_v2f_c4f_vertex_tranformation;
|
|
renderContext.uniform_v2f_c4f_vertex_point_size = shaderEngine.uniform_v2f_c4f_vertex_point_size;
|
|
renderContext.uniform_v2f_c4f_t2f_vertex_tranformation = shaderEngine.uniform_v2f_c4f_t2f_vertex_tranformation;
|
|
renderContext.uniform_v2f_c4f_t2f_frag_texture_sampler = shaderEngine.uniform_v2f_c4f_t2f_frag_texture_sampler;
|
|
|
|
// Interpolation VAO/VBO's
|
|
glGenBuffers(1, &m_vbo_Interpolation);
|
|
glGenVertexArrays(1, &m_vao_Interpolation);
|
|
|
|
glBindVertexArray(m_vao_Interpolation);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_Interpolation);
|
|
|
|
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);
|
|
|
|
// CompositeOutput VAO/VBO's
|
|
glGenBuffers(1, &m_vbo_CompositeOutput);
|
|
glGenVertexArrays(1, &m_vao_CompositeOutput);
|
|
|
|
float composite_buffer_data[8][2] =
|
|
{
|
|
{ -0.5, -0.5 },
|
|
{ 0, 1 },
|
|
{ -0.5, 0.5 },
|
|
{ 0, 0 },
|
|
{ 0.5, 0.5 },
|
|
{ 1, 0 },
|
|
{ 0.5, -0.5 },
|
|
{ 1, 1 } };
|
|
|
|
|
|
glBindVertexArray(m_vao_CompositeOutput);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_CompositeOutput);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8 * 2, composite_buffer_data, GL_STATIC_DRAW);
|
|
|
|
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);
|
|
|
|
|
|
|
|
// CompositeShaderOutput VAO/VBO's
|
|
glGenBuffers(1, &m_vbo_CompositeShaderOutput);
|
|
glGenVertexArrays(1, &m_vao_CompositeShaderOutput);
|
|
|
|
glBindVertexArray(m_vao_CompositeShaderOutput);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_CompositeShaderOutput);
|
|
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(composite_shader_vertex), (void*)0); // Positions
|
|
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(composite_shader_vertex), (void*)(sizeof(float)*2)); // Colors
|
|
|
|
glEnableVertexAttribArray(2);
|
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(composite_shader_vertex), (void*)(sizeof(float)*6)); // UV
|
|
|
|
glEnableVertexAttribArray(3);
|
|
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(composite_shader_vertex), (void*)(sizeof(float)*8)); // RAD ANG
|
|
|
|
glBindVertexArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
std::string Renderer::SetPipeline(Pipeline &pipeline)
|
|
{
|
|
currentPipe = &pipeline;
|
|
shaderEngine.reset();
|
|
if (!shaderEngine.loadPresetShaders(pipeline)) {
|
|
return "Shader compilation error";
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
void Renderer::ResetTextures()
|
|
{
|
|
textureManager->Clear();
|
|
|
|
reset(vw, vh);
|
|
|
|
textureManager->Preload();
|
|
}
|
|
|
|
void Renderer::SetupPass1(const Pipeline &pipeline, const PipelineContext &pipelineContext)
|
|
{
|
|
totalframes++;
|
|
glViewport(0, 0, texsizeX, texsizeY);
|
|
|
|
renderContext.mat_ortho = glm::ortho(0.0f, 1.0f, 0.0f, 1.0f, -40.0f, 40.0f);
|
|
}
|
|
|
|
void Renderer::RenderItems(const Pipeline &pipeline, const PipelineContext &pipelineContext)
|
|
{
|
|
renderContext.time = pipelineContext.time;
|
|
renderContext.texsize = nearestPower2(std::max(texsizeX, texsizeY));
|
|
renderContext.aspectCorrect = correction;
|
|
renderContext.aspectRatio = aspect;
|
|
renderContext.textureManager = textureManager;
|
|
renderContext.beatDetect = beatDetect;
|
|
|
|
for (std::vector<RenderItem*>::const_iterator pos = pipeline.drawables.begin(); pos != pipeline.drawables.end(); ++pos)
|
|
{
|
|
if (*pos != NULL)
|
|
{
|
|
(*pos)->Draw(renderContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Renderer::FinishPass1()
|
|
{
|
|
draw_title_to_texture();
|
|
|
|
textureManager->updateMainTexture();
|
|
}
|
|
|
|
void Renderer::Pass2(const Pipeline &pipeline, const PipelineContext &pipelineContext)
|
|
{
|
|
//BEGIN PASS 2
|
|
//
|
|
//end of texture rendering
|
|
//now we copy the texture from the FBO or framebuffer to
|
|
//video texture memory and render fullscreen.
|
|
|
|
/** Reset the viewport size */
|
|
if (textureRenderToTexture)
|
|
{
|
|
glViewport(0, 0, texsizeX, texsizeY);
|
|
}
|
|
else
|
|
glViewport(0, 0, this->vw, this->vh);
|
|
|
|
if (shaderEngine.enableCompositeShader(currentPipe->compositeShader, pipeline, pipelineContext)) {
|
|
CompositeShaderOutput(pipeline, pipelineContext);
|
|
} else {
|
|
CompositeOutput(pipeline, pipelineContext);
|
|
}
|
|
|
|
/* FTGL does not support OpenGL ES
|
|
#ifndef EMSCRIPTEN
|
|
glMatrixMode(GL_MODELVIEW);
|
|
#endif
|
|
glLoadIdentity();
|
|
glTranslatef(-0.5, -0.5, 0);
|
|
|
|
// When console refreshes, there is a chance the preset has been changed by the user
|
|
refreshConsole();
|
|
draw_title_to_screen(false);
|
|
if (this->showhelp % 2)
|
|
draw_help();
|
|
if (this->showtitle % 2)
|
|
draw_title();
|
|
if (this->showfps % 2)
|
|
draw_fps(this->realfps);
|
|
if (this->showpreset % 2)
|
|
draw_preset();
|
|
if (this->showstats % 2)
|
|
draw_stats();
|
|
glTranslatef(0.5, 0.5, 0);
|
|
*/
|
|
|
|
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)
|
|
{
|
|
shaderEngine.RenderBlurTextures(pipeline, pipelineContext);
|
|
|
|
SetupPass1(pipeline, pipelineContext);
|
|
|
|
Interpolation(pipeline, pipelineContext);
|
|
|
|
RenderItems(pipeline, pipelineContext);
|
|
|
|
FinishPass1();
|
|
|
|
Pass2(pipeline, pipelineContext);
|
|
}
|
|
|
|
void Renderer::Interpolation(const Pipeline &pipeline, const PipelineContext &pipelineContext)
|
|
{
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, textureManager->getMainTexture()->texID);
|
|
|
|
//Texture wrapping( clamp vs. wrap)
|
|
if (pipeline.textureWrap == 0)
|
|
{
|
|
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
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
}
|
|
|
|
int size = (mesh.height - 1) * mesh.width * 4 * 2;
|
|
|
|
if (pipeline.staticPerPixel)
|
|
{
|
|
for (int j = 0; j < mesh.height - 1; j++)
|
|
{
|
|
int base = j * mesh.width * 2 * 4;
|
|
|
|
for (int i = 0; i < mesh.width; i++)
|
|
{
|
|
int strip = base + i * 8;
|
|
p[strip + 2] = pipeline.x_mesh[i][j];
|
|
p[strip + 3] = pipeline.y_mesh[i][j];
|
|
|
|
p[strip + 6] = pipeline.x_mesh[i][j+1];
|
|
p[strip + 7] = pipeline.y_mesh[i][j+1];
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
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++)
|
|
{
|
|
int base = j * mesh.width * 2 * 4;
|
|
|
|
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;
|
|
|
|
p[strip + 2] = mesh.p[index].x;
|
|
p[strip + 3] = mesh.p[index].y;
|
|
|
|
p[strip + 6] = mesh.p[index2].x;
|
|
p[strip + 7] = mesh.p[index2].y;
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_Interpolation);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, NULL, GL_DYNAMIC_DRAW);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, p, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
shaderEngine.enableWarpShader(currentPipe->warpShader, pipeline, pipelineContext, renderContext.mat_ortho);
|
|
|
|
glVertexAttrib4f(1, 1.0, 1.0, 1.0, pipeline.screenDecay);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
|
|
|
|
glBindVertexArray(m_vao_Interpolation);
|
|
|
|
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);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
Renderer::~Renderer()
|
|
{
|
|
|
|
if (textureManager)
|
|
delete (textureManager);
|
|
|
|
//std::cerr << "grid assign end" << std::endl;
|
|
|
|
free(p);
|
|
|
|
#ifdef USE_FTGL
|
|
// std::cerr << "freeing title fonts" << std::endl;
|
|
if (title_font)
|
|
delete title_font;
|
|
if (poly_font)
|
|
delete poly_font;
|
|
if (other_font)
|
|
delete other_font;
|
|
// std::cerr << "freeing title fonts finished" << std::endl;
|
|
#endif
|
|
// std::cerr << "exiting destructor" << std::endl;
|
|
|
|
glDeleteBuffers(1, &m_vbo_Interpolation);
|
|
glDeleteVertexArrays(1, &m_vao_Interpolation);
|
|
|
|
glDeleteBuffers(1, &m_vbo_CompositeOutput);
|
|
glDeleteVertexArrays(1, &m_vao_CompositeOutput);
|
|
|
|
glDeleteTextures(1, &textureRenderToTexture);
|
|
}
|
|
|
|
void Renderer::reset(int w, int h)
|
|
{
|
|
aspect = (float) h / (float) w;
|
|
this -> vw = w;
|
|
this -> vh = h;
|
|
|
|
glCullFace(GL_BACK);
|
|
|
|
#ifndef GL_TRANSITION
|
|
glEnable(GL_LINE_SMOOTH);
|
|
#endif
|
|
|
|
glClearColor(0, 0, 0, 0);
|
|
|
|
glViewport(0, 0, w, h);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
texsizeX = w;
|
|
texsizeY = h;
|
|
|
|
// snap to 16x16 blocks
|
|
texsizeX = ((texsizeX-15)/16)*16;
|
|
texsizeY = ((texsizeY-15)/16)*16;
|
|
|
|
m_fAspectX = (texsizeY > texsizeX) ? (float)texsizeX/(float)texsizeY : 1.0f;
|
|
m_fAspectY = (texsizeX > texsizeY) ? (float)texsizeY/(float)texsizeX : 1.0f;
|
|
m_fInvAspectX = 1.0f/m_fAspectX;
|
|
m_fInvAspectY = 1.0f/m_fAspectY;
|
|
|
|
InitCompositeShaderVertex();
|
|
|
|
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);
|
|
}
|
|
|
|
GLuint Renderer::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()
|
|
{
|
|
#ifdef USE_FTGL
|
|
if (this->drawtitle > 100)
|
|
{
|
|
draw_title_to_screen(true);
|
|
this->drawtitle = 0;
|
|
}
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
float title_y;
|
|
|
|
void Renderer::draw_title_to_screen(bool flip)
|
|
{
|
|
|
|
#ifdef USE_FTGL
|
|
if (this->drawtitle > 0)
|
|
{
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
int draw;
|
|
if (drawtitle >= 80)
|
|
draw = 80;
|
|
else
|
|
draw = drawtitle;
|
|
|
|
float easein = ((80 - draw) * .0125);
|
|
float easein2 = easein * easein;
|
|
|
|
if (drawtitle == 1)
|
|
{
|
|
title_y = (float) rand() / RAND_MAX;
|
|
title_y *= 2;
|
|
title_y -= 1;
|
|
title_y *= .6;
|
|
}
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
//glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE);
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glFrustum(-1, 1, -1 * (float) vh / (float) vw, 1 * (float) vh / (float) vw, 1, 1000);
|
|
if (flip)
|
|
glScalef(1, -1, 1);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(-850, title_y * 850 * vh / vw, easein2 * 900 - 900);
|
|
|
|
glRotatef(easein2 * 360, 1, 0, 0);
|
|
|
|
poly_font->Render(this->title.c_str());
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
this->drawtitle++;
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_COLOR_MATERIAL);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_POLYGON_SMOOTH);
|
|
}
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
void Renderer::draw_title()
|
|
{
|
|
#ifdef USE_FTGL
|
|
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
// glPushMatrix();
|
|
// glTranslatef(this->vw*.001,this->vh*.03, -1);
|
|
// glScalef(this->vw*.015,this->vh*.025,0);
|
|
|
|
glRasterPos2f(0.01, 0.05);
|
|
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
|
|
|
|
title_font->Render(this->title.c_str());
|
|
// glPopMatrix();
|
|
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
void Renderer::draw_preset()
|
|
{
|
|
#ifdef USE_FTGL
|
|
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
// glPushMatrix();
|
|
//glTranslatef(this->vw*.001,this->vh*-.01, -1);
|
|
//glScalef(this->vw*.003,this->vh*.004,0);
|
|
|
|
|
|
glRasterPos2f(0.01, 0.01);
|
|
|
|
title_font->FaceSize((unsigned) (12 * (this->vh / 512.0)));
|
|
if (this->noSwitch)
|
|
title_font->Render("[LOCKED] ");
|
|
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
|
|
|
|
title_font->Render(this->presetName().c_str());
|
|
|
|
//glPopMatrix();
|
|
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
void Renderer::draw_help()
|
|
{
|
|
|
|
#ifdef USE_FTGL
|
|
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
glPushMatrix();
|
|
glTranslatef(0, 1, 0);
|
|
//glScalef(this->vw*.02,this->vh*.02 ,0);
|
|
|
|
|
|
title_font->FaceSize((unsigned) (18 * (this->vh / 512.0)));
|
|
|
|
glRasterPos2f(0.01, -0.05);
|
|
title_font->Render("Help");
|
|
|
|
glRasterPos2f(0.01, -0.09);
|
|
title_font->Render("----------------------------");
|
|
|
|
glRasterPos2f(0.01, -0.13);
|
|
title_font->Render("F1: This help menu");
|
|
|
|
glRasterPos2f(0.01, -0.17);
|
|
title_font->Render("F2: Show song title");
|
|
|
|
glRasterPos2f(0.01, -0.21);
|
|
title_font->Render("F3: Show preset name");
|
|
|
|
glRasterPos2f(0.01, -0.25);
|
|
title_font->Render("F4: Show Rendering Settings");
|
|
|
|
glRasterPos2f(0.01, -0.29);
|
|
title_font->Render("F5: Show FPS");
|
|
|
|
glRasterPos2f(0.01, -0.35);
|
|
title_font->Render("F: Fullscreen");
|
|
|
|
glRasterPos2f(0.01, -0.39);
|
|
title_font->Render("L: Lock/Unlock Preset");
|
|
|
|
glRasterPos2f(0.01, -0.43);
|
|
title_font->Render("M: Show Menu");
|
|
|
|
glRasterPos2f(0.01, -0.49);
|
|
title_font->Render("R: Random preset");
|
|
glRasterPos2f(0.01, -0.53);
|
|
title_font->Render("N: Next preset");
|
|
|
|
glRasterPos2f(0.01, -0.57);
|
|
title_font->Render("P: Previous preset");
|
|
|
|
glPopMatrix();
|
|
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
void Renderer::draw_stats()
|
|
{
|
|
|
|
#ifdef USE_FTGL
|
|
char buffer[128];
|
|
float offset = (this->showfps % 2 ? -0.05 : 0.0);
|
|
// glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
glPushMatrix();
|
|
glTranslatef(0.01, 1, 0);
|
|
glRasterPos2f(0, -.05 + offset);
|
|
other_font->Render(this->correction ? " aspect: corrected" : " aspect: stretched");
|
|
sprintf(buffer, " (%f)", this->aspect);
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.09 + offset);
|
|
other_font->FaceSize((unsigned) (18 * (vh / 512.0)));
|
|
|
|
sprintf(buffer, " texsize: %d", renderTarget->texsize);
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.13 + offset);
|
|
sprintf(buffer, " viewport: %d x %d", vw, vh);
|
|
|
|
other_font->Render(buffer);
|
|
glRasterPos2f(0, -.17 + offset);
|
|
other_font->Render((renderTarget->useFBO ? " FBO: on" : " FBO: off"));
|
|
|
|
glRasterPos2f(0, -.21 + offset);
|
|
sprintf(buffer, " mesh: %d x %d", mesh.width, mesh.height);
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.25 + offset);
|
|
sprintf(buffer, " textures: %.1fkB", textureManager->getTextureMemorySize() / 1000.0f);
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.29 + offset);
|
|
sprintf(buffer, "shader profile: %s", shaderEngine.profileName.c_str());
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.33 + offset);
|
|
sprintf(buffer, " warp shader: %s", currentPipe->warpShader.enabled ? "on" : "off");
|
|
other_font->Render(buffer);
|
|
|
|
glRasterPos2f(0, -.37 + offset);
|
|
sprintf(buffer, " comp shader: %s", currentPipe->compositeShader.enabled ? "on" : "off");
|
|
other_font->Render(buffer);
|
|
|
|
glPopMatrix();
|
|
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
#endif /** USE_FTGL */
|
|
}
|
|
void Renderer::draw_fps(float realfps)
|
|
{
|
|
#ifdef USE_FTGL
|
|
char bufferfps[20];
|
|
sprintf(bufferfps, "%.1f fps", realfps);
|
|
// glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
glPushMatrix();
|
|
glTranslatef(0.01, 1, 0);
|
|
glRasterPos2f(0, -0.05);
|
|
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
|
|
title_font->Render(bufferfps);
|
|
|
|
glPopMatrix();
|
|
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
#endif /** USE_FTGL */
|
|
}
|
|
|
|
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_vertex_tranformation, 1, GL_FALSE, glm::value_ptr(renderContext.mat_ortho));
|
|
glUniform1i(shaderEngine.uniform_v2f_c4f_t2f_frag_texture_sampler, 0);
|
|
|
|
//Overwrite anything on the screen
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
glBindVertexArray(m_vao_CompositeOutput);
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
glBindVertexArray(0);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
for (std::vector<RenderItem*>::const_iterator pos = pipeline.compositeDrawables.begin(); pos
|
|
!= 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;
|
|
}
|
|
|
|
float Renderer::SquishToCenter(float x, float fExp)
|
|
{
|
|
if (x > 0.5f)
|
|
return powf(x*2-1, fExp)*0.5f + 0.5f;
|
|
|
|
return (1-powf(1-x*2, fExp))*0.5f;
|
|
}
|
|
|
|
void Renderer::UvToMathSpace(float u, float v, float* rad, float* ang)
|
|
{
|
|
// (screen space = -1..1 on both axes; corresponds to UV space)
|
|
// uv space = [0..1] on both axes
|
|
// "math" space = what the preset authors are used to:
|
|
// upper left = [0,0]
|
|
// bottom right = [1,1]
|
|
// rad == 1 at corners of screen
|
|
// ang == 0 at three o'clock, and increases counter-clockwise (to 6.28).
|
|
float px = (u*2-1) * m_fAspectX; // probably 1.0
|
|
float py = (v*2-1) * m_fAspectY; // probably <1
|
|
|
|
*rad = sqrtf(px*px + py*py) / sqrtf(m_fAspectX*m_fAspectX + m_fAspectY*m_fAspectY);
|
|
*ang = atan2f(py, px);
|
|
if (*ang < 0)
|
|
*ang += 6.2831853071796f;
|
|
}
|
|
|
|
void Renderer::InitCompositeShaderVertex() {
|
|
|
|
// BUILD VERTEX LIST for final composite blit
|
|
memset(m_comp_verts, 0, sizeof(composite_shader_vertex)*FCGSX*FCGSY);
|
|
float fDivX = 1.0f / (float)(FCGSX-2);
|
|
float fDivY = 1.0f / (float)(FCGSY-2);
|
|
for (int j=0; j<FCGSY; j++)
|
|
{
|
|
int j2 = j - j/(FCGSY/2);
|
|
float v = j2*fDivY;
|
|
v = SquishToCenter(v, 3.0f);
|
|
float sy = -((v)*2-1);
|
|
for (int i=0; i<FCGSX; i++)
|
|
{
|
|
int i2 = i - i/(FCGSX/2);
|
|
float u = i2*fDivX;
|
|
u = SquishToCenter(u, 3.0f);
|
|
float sx = (u)*2-1;
|
|
composite_shader_vertex* pComp = &m_comp_verts[i + j*FCGSX];
|
|
pComp->x = sx;
|
|
pComp->y = sy;
|
|
|
|
float rad, ang;
|
|
UvToMathSpace( u, v, &rad, &ang );
|
|
// fix-ups:
|
|
if (i==FCGSX/2-1) {
|
|
if (j < FCGSY/2-1)
|
|
ang = 3.1415926535898f*1.5f;
|
|
else if (j == FCGSY/2-1)
|
|
ang = 3.1415926535898f*1.25f;
|
|
else if (j == FCGSY/2)
|
|
ang = 3.1415926535898f*0.75f;
|
|
else
|
|
ang = 3.1415926535898f*0.5f;
|
|
}
|
|
else if (i==FCGSX/2) {
|
|
if (j < FCGSY/2-1)
|
|
ang = 3.1415926535898f*1.5f;
|
|
else if (j == FCGSY/2-1)
|
|
ang = 3.1415926535898f*1.75f;
|
|
else if (j == FCGSY/2)
|
|
ang = 3.1415926535898f*0.25f;
|
|
else
|
|
ang = 3.1415926535898f*0.5f;
|
|
}
|
|
else if (j==FCGSY/2-1) {
|
|
if (i < FCGSX/2-1)
|
|
ang = 3.1415926535898f*1.0f;
|
|
else if (i == FCGSX/2-1)
|
|
ang = 3.1415926535898f*1.25f;
|
|
else if (i == FCGSX/2)
|
|
ang = 3.1415926535898f*1.75f;
|
|
else
|
|
ang = 3.1415926535898f*2.0f;
|
|
}
|
|
else if (j==FCGSY/2) {
|
|
if (i < FCGSX/2-1)
|
|
ang = 3.1415926535898f*1.0f;
|
|
else if (i == FCGSX/2-1)
|
|
ang = 3.1415926535898f*0.75f;
|
|
else if (i == FCGSX/2)
|
|
ang = 3.1415926535898f*0.25f;
|
|
else
|
|
ang = 3.1415926535898f*0.0f;
|
|
}
|
|
pComp->tu = u;
|
|
pComp->tv = v;
|
|
|
|
pComp->rad = rad;
|
|
pComp->ang = ang;
|
|
}
|
|
}
|
|
|
|
// build index list for final composite blit -
|
|
// order should be friendly for interpolation of 'ang' value!
|
|
int* cur_index = &m_comp_indices[0];
|
|
for (int y=0; y<FCGSY-1; y++)
|
|
{
|
|
if (y==FCGSY/2-1)
|
|
continue;
|
|
for (int x=0; x<FCGSX-1; x++)
|
|
{
|
|
if (x==FCGSX/2-1)
|
|
continue;
|
|
bool left_half = (x < FCGSX/2);
|
|
bool top_half = (y < FCGSY/2);
|
|
bool center_4 = ((x==FCGSX/2 || x==FCGSX/2-1) && (y==FCGSY/2 || y==FCGSY/2-1));
|
|
|
|
if ( ((int)left_half + (int)top_half + (int)center_4) % 2 )
|
|
{
|
|
*(cur_index+0) = (y )*FCGSX + (x );
|
|
*(cur_index+1) = (y )*FCGSX + (x+1);
|
|
*(cur_index+2) = (y+1)*FCGSX + (x+1);
|
|
*(cur_index+3) = (y+1)*FCGSX + (x+1);
|
|
*(cur_index+4) = (y+1)*FCGSX + (x );
|
|
*(cur_index+5) = (y )*FCGSX + (x );
|
|
}
|
|
else
|
|
{
|
|
*(cur_index+0) = (y+1)*FCGSX + (x );
|
|
*(cur_index+1) = (y )*FCGSX + (x );
|
|
*(cur_index+2) = (y )*FCGSX + (x+1);
|
|
*(cur_index+3) = (y )*FCGSX + (x+1);
|
|
*(cur_index+4) = (y+1)*FCGSX + (x+1);
|
|
*(cur_index+5) = (y+1)*FCGSX + (x );
|
|
}
|
|
|
|
cur_index += 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Renderer::CompositeShaderOutput(const Pipeline &pipeline, const PipelineContext &pipelineContext)
|
|
{
|
|
// hue shader
|
|
float shade[4][3] = {
|
|
{ 1.0f, 1.0f, 1.0f },
|
|
{ 1.0f, 1.0f, 1.0f },
|
|
{ 1.0f, 1.0f, 1.0f },
|
|
{ 1.0f, 1.0f, 1.0f } }; // for each vertex, then each comp.
|
|
|
|
// pick 4 colors for the 4 corners
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
shade[i][0] = 0.6f + 0.3f*sinf(pipelineContext.time*30.0f*0.0143f + 3 + i*21);
|
|
shade[i][1] = 0.6f + 0.3f*sinf(pipelineContext.time*30.0f*0.0107f + 1 + i*13);
|
|
shade[i][2] = 0.6f + 0.3f*sinf(pipelineContext.time*30.0f*0.0129f + 6 + i*9 );
|
|
float max = ((shade[i][0] > shade[i][1]) ? shade[i][0] : shade[i][1]);
|
|
if (shade[i][2] > max) max = shade[i][2];
|
|
for (int k=0; k<3; k++)
|
|
{
|
|
shade[i][k] /= max;
|
|
shade[i][k] = 0.5f + 0.5f*shade[i][k];
|
|
}
|
|
}
|
|
|
|
// interpolate the 4 colors & apply to all the verts
|
|
for (int j=0; j<FCGSY; j++)
|
|
{
|
|
for (int i=0; i<FCGSX; i++)
|
|
{
|
|
composite_shader_vertex* pComp = &m_comp_verts[i + j*FCGSX];
|
|
float x = pComp->x*0.5f + 0.5f;
|
|
float y = pComp->y*0.5f + 0.5f;
|
|
|
|
float col[3] = { 1, 1, 1 };
|
|
for (int c=0; c<3; c++)
|
|
col[c] = shade[0][c]*( x)*( y) +
|
|
shade[1][c]*(1-x)*( y) +
|
|
shade[2][c]*( x)*(1-y) +
|
|
shade[3][c]*(1-x)*(1-y);
|
|
|
|
pComp->Diffuse[0] = col[0];
|
|
pComp->Diffuse[1] = col[1];
|
|
pComp->Diffuse[2] = col[2];
|
|
pComp->Diffuse[3] = 1.0;
|
|
}
|
|
}
|
|
|
|
|
|
int primCount = (FCGSX-2)*(FCGSY-2)*6;
|
|
composite_shader_vertex tempv[primCount];
|
|
memset(tempv, 0, sizeof(composite_shader_vertex) * primCount);
|
|
int src_idx = 0;
|
|
for (int i=0; i<primCount; i++)
|
|
{
|
|
tempv[i] = m_comp_verts[ m_comp_indices[src_idx++] ];
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_CompositeShaderOutput);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(composite_shader_vertex) * primCount, NULL, GL_DYNAMIC_DRAW);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(composite_shader_vertex) * primCount, tempv, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
|
|
glBindVertexArray(m_vao_CompositeShaderOutput);
|
|
|
|
// Now do the final composite blit, fullscreen;
|
|
glDrawArrays(GL_TRIANGLES, 0, primCount);
|
|
|
|
glBindVertexArray(0);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
|