Refactor selection pointer to use glsl and common BO

pull/3/head
Hleb Valoshka 2019-11-08 00:56:56 +03:00
parent 08907c5883
commit ae02fe2c38
4 changed files with 121 additions and 92 deletions

View File

@ -0,0 +1,8 @@
#version 120
uniform vec4 color;
void main(void)
{
gl_FragColor = color;
}

View File

@ -0,0 +1,14 @@
#version 120
uniform float pixelSize;
uniform float s, c;
uniform float x0, y0;
uniform vec3 u, v;
void main(void)
{
float x = gl_Vertex.x * pixelSize;
float y = gl_Vertex.y * pixelSize;
vec3 pos = (x * c - y * s + x0) * u + (x * s + y * c + y0) * v;
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0f);
}

View File

@ -10,6 +10,7 @@
#include "marker.h"
#include <celmath/mathlib.h>
#include <celutil/util.h>
#include <GL/glew.h>
#include <vector>
#include "render.h"
@ -130,9 +131,18 @@ static GLfloat DownArrow[DownArrowCount * 2] =
0.0f, 1.0f
};
constexpr const int StaticVtxCount = DownArrowOffset + DownArrowCount;
constexpr const int SelPointerOffset = DownArrowOffset + DownArrowCount;
constexpr const int SelPointerCount = 3;
static GLfloat SelPointer[SelPointerCount * 2] =
{
0.0f, 0.0f,
-20.0f, 6.0f,
-20.0f, -6.0f
};
constexpr const int SmallCircleOffset = DownArrowOffset + DownArrowCount;
constexpr const int StaticVtxCount = SelPointerOffset + SelPointerCount;
constexpr const int SmallCircleOffset = StaticVtxCount;
static int SmallCircleCount = 0;
static int LargeCircleOffset = 0;
static int LargeCircleCount = 0;
@ -170,10 +180,11 @@ static void initVO(VertexObject& vo)
VOSTREAM(LeftArrow);
VOSTREAM(UpArrow);
VOSTREAM(DownArrow);
VOSTREAM(SelPointer);
#undef VOSTREAM
vo.setBufferData(small.data(), VTXTOMEM(SmallCircleOffset), small.size() * sizeof(GLfloat));
vo.setBufferData(large.data(), VTXTOMEM(LargeCircleOffset), large.size() * sizeof(GLfloat));
vo.setBufferData(small.data(), VTXTOMEM(SmallCircleOffset), memsize(small));
vo.setBufferData(large.data(), VTXTOMEM(LargeCircleOffset), memsize(large));
#undef VTXTOMEM
vo.setVertices(2, GL_FLOAT, false, 0, 0);
@ -181,16 +192,15 @@ static void initVO(VertexObject& vo)
void Renderer::renderMarker(MarkerRepresentation::Symbol symbol, float size, const Color& color)
{
markerVO.bind();
if (!markerVO.initialized())
initVO(markerVO);
assert(shaderManager != nullptr);
auto* prog = shaderManager->getShader("marker");
if (prog == nullptr)
return;
markerVO.bind();
if (!markerVO.initialized())
initVO(markerVO);
float s = size / 2.0f;
prog->use();
prog->vec4Param("color") = color.toVector4();
@ -259,3 +269,83 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol, float size, con
glUseProgram(0);
markerVO.unbind();
}
/*! Draw an arrow at the view border pointing to an offscreen selection. This method
* should only be called when the selection lies outside the view frustum.
*/
void Renderer::renderSelectionPointer(const Observer& observer,
double now,
const Frustum& viewFrustum,
const Selection& sel)
{
constexpr const float cursorDistance = 20.0f;
if (sel.empty())
return;
// Get the position of the cursor relative to the eye
Vector3d position = sel.getPosition(now).offsetFromKm(observer.getPosition());
if (viewFrustum.testSphere(position, sel.radius()) != Frustum::Outside)
return;
assert(shaderManager != nullptr);
auto* prog = shaderManager->getShader("selpointer");
if (prog == nullptr)
return;
Matrix3f cameraMatrix = observer.getOrientationf().conjugate().toRotationMatrix();
const Vector3f u = cameraMatrix.col(0);
const Vector3f v = cameraMatrix.col(1);
double distance = position.norm();
position *= cursorDistance / distance;
#ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
#endif
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float vfov = (float) observer.getFOV();
float h = tan(vfov / 2);
float w = h * getAspectRatio();
float diag = sqrt(h * h + w * w);
Vector3f posf = position.cast<float>() / cursorDistance;
float x = u.dot(posf);
float y = v.dot(posf);
float c, s;
sincos(atan2(y, x), s, c);
float x0 = c * diag;
float y0 = s * diag;
float t = (std::abs(x0) < w) ? h / abs(y0) : w / abs(x0);
x0 *= t;
y0 *= t;
const Vector3f &center = cameraMatrix.col(2);
glPushMatrix();
glTranslatef(-center.x(), -center.y(), -center.z());
markerVO.bind();
if (!markerVO.initialized())
initVO(markerVO);
prog->use();
prog->vec4Param("color") = Color(SelectionCursorColor, 0.6f).toVector4();
prog->floatParam("pixelSize") = pixelSize;
prog->floatParam("s") = s;
prog->floatParam("c") = c;
prog->floatParam("x0") = x0;
prog->floatParam("y0") = y0;
prog->vec3Param("u") = u;
prog->vec3Param("v") = v;
markerVO.draw(GL_TRIANGLES, SelPointerCount, SelPointerOffset);
glUseProgram(0);
markerVO.unbind();
glPopMatrix();
#ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
#endif
}

View File

@ -7174,89 +7174,6 @@ void Renderer::renderSkyGrids(const Observer& observer)
}
}
/*! Draw an arrow at the view border pointing to an offscreen selection. This method
* should only be called when the selection lies outside the view frustum.
*/
void Renderer::renderSelectionPointer(const Observer& observer,
double now,
const Frustum& viewFrustum,
const Selection& sel)
{
const float cursorDistance = 20.0f;
if (sel.empty())
return;
Matrix3f cameraMatrix = observer.getOrientationf().conjugate().toRotationMatrix();
Vector3f u = cameraMatrix * Vector3f::UnitX();
Vector3f v = cameraMatrix * Vector3f::UnitY();
// Get the position of the cursor relative to the eye
Vector3d position = sel.getPosition(now).offsetFromKm(observer.getPosition());
double distance = position.norm();
bool isVisible = viewFrustum.testSphere(position, sel.radius()) != Frustum::Outside;
position *= cursorDistance / distance;
#ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
#endif
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (!isVisible)
{
double viewAspectRatio = (double) windowWidth / (double) windowHeight;
double vfov = observer.getFOV();
auto h = (float) tan(vfov / 2);
auto w = (float) (h * viewAspectRatio);
float diag = std::sqrt(h * h + w * w);
Vector3f posf = position.cast<float>();
posf *= (1.0f / cursorDistance);
float x = u.dot(posf);
float y = v.dot(posf);
float angle = std::atan2(y, x);
float c = std::cos(angle);
float s = std::sin(angle);
float t = 1.0f;
float x0 = c * diag;
float y0 = s * diag;
if (std::abs(x0) < w)
t = h / std::abs(y0);
else
t = w / std::abs(x0);
x0 *= t;
y0 *= t;
glColor(SelectionCursorColor, 0.6f);
Vector3f center = -cameraMatrix * Vector3f::UnitZ();
glPushMatrix();
glTranslatef(center.x(), center.y(), center.z());
Vector3f p0(Vector3f::Zero());
Vector3f p1(-20.0f * pixelSize, 6.0f * pixelSize, 0.0f);
Vector3f p2(-20.0f * pixelSize, -6.0f * pixelSize, 0.0f);
glBegin(GL_TRIANGLES);
glVertex((p0.x() * c - p0.y() * s + x0) * u + (p0.x() * s + p0.y() * c + y0) * v);
glVertex((p1.x() * c - p1.y() * s + x0) * u + (p1.x() * s + p1.y() * c + y0) * v);
glVertex((p2.x() * c - p2.y() * s + x0) * u + (p2.x() * s + p2.y() * c + y0) * v);
glEnd();
glPopMatrix();
}
#ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
#endif
glEnable(GL_TEXTURE_2D);
}
void Renderer::labelConstellations(const AsterismList& asterisms,
const Observer& observer)
{