celestia/src/celengine/viewporteffect.cpp

162 lines
4.2 KiB
C++

//
// viewporteffect.cpp
//
// Copyright © 2020 Celestia Development Team. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include "viewporteffect.h"
#include "framebuffer.h"
#include "render.h"
#include "shadermanager.h"
#include "mapmanager.h"
bool ViewportEffect::preprocess(Renderer* renderer, FramebufferObject* fbo)
{
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFboId);
return fbo->bind();
}
bool ViewportEffect::prerender(Renderer* renderer, FramebufferObject* fbo)
{
if (!fbo->unbind(oldFboId))
return false;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return true;
}
bool ViewportEffect::distortXY(float &x, float &y)
{
return true;
}
PassthroughViewportEffect::PassthroughViewportEffect() :
ViewportEffect(),
vo(GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW)
{
}
bool PassthroughViewportEffect::prerender(Renderer* renderer, FramebufferObject* fbo)
{
if (!ViewportEffect::prerender(renderer, fbo))
return false;
renderer->disableDepthTest();
return true;
}
bool PassthroughViewportEffect::render(Renderer* renderer, FramebufferObject* fbo, int width, int height)
{
CelestiaGLProgram *prog = renderer->getShaderManager().getShader("passthrough");
if (prog == nullptr)
return false;
vo.bind();
if (!vo.initialized())
initializeVO(vo);
prog->use();
prog->samplerParam("tex") = 0;
glBindTexture(GL_TEXTURE_2D, fbo->colorTexture());
draw(vo);
glBindTexture(GL_TEXTURE_2D, 0);
vo.unbind();
return true;
}
void PassthroughViewportEffect::initializeVO(celgl::VertexObject& vo)
{
static float quadVertices[] = {
// positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
vo.allocate(sizeof(quadVertices), quadVertices);
vo.setVertices(2, GL_FLOAT, false, 4 * sizeof(float), 0);
vo.setTextureCoords(2, GL_FLOAT, false, 4 * sizeof(float), 2 * sizeof(float));
}
void PassthroughViewportEffect::draw(celgl::VertexObject& vo)
{
vo.draw(GL_TRIANGLES, 6);
}
WarpMeshViewportEffect::WarpMeshViewportEffect(WarpMesh *mesh) :
ViewportEffect(),
vo(GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW),
mesh(mesh)
{
}
bool WarpMeshViewportEffect::prerender(Renderer* renderer, FramebufferObject* fbo)
{
if (mesh == nullptr)
return false;
if (!ViewportEffect::prerender(renderer, fbo))
return false;
renderer->disableDepthTest();
return true;
}
bool WarpMeshViewportEffect::render(Renderer* renderer, FramebufferObject* fbo, int width, int height)
{
CelestiaGLProgram *prog = renderer->getShaderManager().getShader("warpmesh");
if (prog == nullptr)
return false;
vo.bind();
if (!vo.initialized())
initializeVO(vo);
prog->use();
prog->samplerParam("tex") = 0;
prog->floatParam("screenRatio") = (float)height / width;
glBindTexture(GL_TEXTURE_2D, fbo->colorTexture());
draw(vo);
glBindTexture(GL_TEXTURE_2D, 0);
vo.unbind();
return true;
}
void WarpMeshViewportEffect::initializeVO(celgl::VertexObject& vo)
{
mesh->scopedDataForRendering([&vo](float *data, int size){
vo.allocate(size, data);
vo.setVertices(2, GL_FLOAT, false, 5 * sizeof(float), 0);
vo.setTextureCoords(2, GL_FLOAT, false, 5 * sizeof(float), 2 * sizeof(float));
vo.setVertexAttribArray(CelestiaGLProgram::IntensityAttributeIndex, 1, GL_FLOAT, false, 5 * sizeof(float), 4 * sizeof(float));
});
}
void WarpMeshViewportEffect::draw(celgl::VertexObject& vo)
{
vo.draw(GL_TRIANGLES, mesh->count());
}
bool WarpMeshViewportEffect::distortXY(float &x, float &y)
{
if (mesh == nullptr)
return false;
float u;
float v;
if (!mesh->mapVertex(x * 2, y * 2, &u, &v))
return false;
x = u / 2;
y = v / 2;
return true;
}