Render lines with triangles

pull/904/head
Levin Li 2020-12-05 17:56:43 +08:00
parent 7d4398c088
commit 668fd219cc
18 changed files with 808 additions and 342 deletions

View File

@ -1,6 +0,0 @@
uniform vec4 color;
void main(void)
{
gl_FragColor = color;
}

View File

@ -1,7 +0,0 @@
attribute vec2 in_Position;
void main(void)
{
vec4 p = vec4(in_Position.x, 0.0, in_Position.y, 1.0);
set_vp(p);
}

View File

@ -17,7 +17,7 @@ using namespace std;
AsterismRenderer::AsterismRenderer(const AsterismList *asterisms) : AsterismRenderer::AsterismRenderer(const AsterismList *asterisms) :
m_asterisms(asterisms) m_asterisms(asterisms)
{ {
m_shadprop.texUsage = ShaderProperties::VertexColors; m_shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
m_shadprop.lightModel = ShaderProperties::UnlitModel; m_shadprop.lightModel = ShaderProperties::UnlitModel;
} }
@ -37,22 +37,25 @@ void AsterismRenderer::render(const Renderer &renderer, const Color &defaultColo
m_vo.bind(); m_vo.bind();
if (!m_vo.initialized()) if (!m_vo.initialized())
{ {
auto *vtxBuf = prepare(); std::vector<LineEnds> data;
if (vtxBuf == nullptr) if (!prepare(data))
{ {
m_vo.unbind(); m_vo.unbind();
return; return;
} }
m_vo.allocate(m_vtxTotal * 3 * sizeof(GLfloat), vtxBuf); m_vo.allocate(data.size() * sizeof(LineEnds), data.data());
m_vo.setVertices(3, GL_FLOAT, false, 0, 0); m_vo.setVertices(3, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, point1));
delete[] vtxBuf; m_vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex, 3, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, point2));
m_vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex, 1, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, scale));
} }
prog->use(); prog->use();
prog->setMVPMatrices(*mvp.projection, *mvp.modelview); prog->setMVPMatrices(*mvp.projection, *mvp.modelview);
prog->lineWidthX = renderer.getLineWidthX();
prog->lineWidthY = renderer.getLineWidthY();
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, defaultColor); glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, defaultColor);
m_vo.draw(GL_LINES, m_vtxTotal); m_vo.draw(GL_TRIANGLES, m_vtxTotal);
assert(m_asterisms->size() == m_vtxCount.size()); assert(m_asterisms->size() == m_vtxCount.size());
@ -67,16 +70,16 @@ void AsterismRenderer::render(const Renderer &renderer, const Color &defaultColo
continue; continue;
} }
Color color = {ast->getOverrideColor(), opacity}; Color color = {ast->getOverrideColor(), opacity};
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color); glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
m_vo.draw(GL_LINES, m_vtxCount[i], offset); m_vo.draw(GL_TRIANGLES, m_vtxCount[i], offset);
offset += m_vtxCount[i]; offset += m_vtxCount[i];
} }
m_vo.unbind(); m_vo.unbind();
} }
GLfloat* AsterismRenderer::prepare() bool AsterismRenderer::prepare(std::vector<LineEnds> &data)
{ {
// calculate required vertices number // calculate required vertices number
GLsizei vtx_num = 0; GLsizei vtx_num = 0;
@ -85,12 +88,12 @@ GLfloat* AsterismRenderer::prepare()
GLsizei ast_vtx_num = 0; GLsizei ast_vtx_num = 0;
for (int k = 0; k < ast->getChainCount(); k++) for (int k = 0; k < ast->getChainCount(); k++)
{ {
// as we use GL_LINES we should double the number of vertices // as we use GL_TRIANGLES we should six times the number of
// as we don't need closed figures we have only one copy of // vertices as we don't need closed figures we have only one
// the 1st and last vertexes // copy of the 1st and last vertexes
GLsizei s = ast->getChain(k).size(); GLsizei s = ast->getChain(k).size();
if (s > 1) if (s > 1)
ast_vtx_num += 2 * s - 2; ast_vtx_num += (s - 1) * 6;
} }
m_vtxCount.push_back(ast_vtx_num); m_vtxCount.push_back(ast_vtx_num);
@ -98,11 +101,9 @@ GLfloat* AsterismRenderer::prepare()
} }
if (vtx_num == 0) if (vtx_num == 0)
return nullptr; return false;
m_vtxTotal = vtx_num; m_vtxTotal = vtx_num;
data.reserve(m_vtxTotal);
GLfloat* vtx_buf = new GLfloat[vtx_num * 3];
GLfloat* ptr = vtx_buf;
for (const auto ast : *m_asterisms) for (const auto ast : *m_asterisms)
{ {
@ -114,17 +115,18 @@ GLfloat* AsterismRenderer::prepare()
if (chain.size() <= 1) if (chain.size() <= 1)
continue; continue;
memcpy(ptr, chain[0].data(), 3 * sizeof(float)); for (unsigned i = 1; i < chain.size(); i++)
ptr += 3;
for (unsigned i = 1; i < chain.size() - 1; i++)
{ {
memcpy(ptr, chain[i].data(), 3 * sizeof(float)); Eigen::Vector3f prev = chain[i - 1];
memcpy(ptr + 3, chain[i].data(), 3 * sizeof(float)); Eigen::Vector3f cur = chain[i];
ptr += 6; data.emplace_back(prev, cur, -0.5);
data.emplace_back(prev ,cur, 0.5);
data.emplace_back(cur, prev, -0.5);
data.emplace_back(cur, prev, -0.5);
data.emplace_back(cur, prev, 0.5);
data.emplace_back(prev, cur, -0.5);
} }
memcpy(ptr, chain[chain.size() - 1].data(), 3 * sizeof(float));
ptr += 3;
} }
} }
return vtx_buf; return true;
} }

View File

@ -17,6 +17,7 @@
class Renderer; class Renderer;
struct Matrices; struct Matrices;
struct LineEnds;
class AsterismRenderer class AsterismRenderer
{ {
@ -33,7 +34,7 @@ class AsterismRenderer
bool sameAsterisms(const AsterismList *asterisms) const; bool sameAsterisms(const AsterismList *asterisms) const;
private: private:
GLfloat* prepare(); bool prepare(std::vector<LineEnds> &data);
celgl::VertexObject m_vo { GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW }; celgl::VertexObject m_vo { GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW };
ShaderProperties m_shadprop; ShaderProperties m_shadprop;

View File

@ -37,7 +37,7 @@ constexpr const float headRadius = 0.025f;
constexpr const unsigned nSections = 30; constexpr const unsigned nSections = 30;
static size_t initArrowAndLetters(VertexObject &vo) static size_t initArrow(VertexObject &vo)
{ {
static_assert(sizeof(Vector3f) == 3*sizeof(GLfloat), "sizeof(Vector3f) != 3*sizeof(GLfloat)"); static_assert(sizeof(Vector3f) == 3*sizeof(GLfloat), "sizeof(Vector3f) != 3*sizeof(GLfloat)");
static size_t count = 0; // number of vertices in the arrow static size_t count = 0; // number of vertices in the arrow
@ -122,31 +122,9 @@ static size_t initArrowAndLetters(VertexObject &vo)
#endif #endif
head.push_back(head[1]); head.push_back(head[1]);
GLfloat lettersVtx[] =
{
// X
0, 0, 0,
1, 0, 1,
1, 0, 0,
0, 0, 1,
// Y
0, 0, 1,
0.5f, 0, 0.5f,
1, 0, 1,
0.5f, 0, 0.5f,
0.5f, 0, 0,
0.5f, 0, 0.5f,
// Z
0, 0, 1,
1, 0, 1,
0, 0, 0,
1, 0, 0
};
GLintptr offset = 0; GLintptr offset = 0;
count = circle.size() + shaft.size() + annulus.size() + head.size(); count = circle.size() + shaft.size() + annulus.size() + head.size();
GLsizeiptr size = sizeof(lettersVtx) + count * sizeof(GLfloat) * 3; GLsizeiptr size = count * sizeof(GLfloat) * 3;
GLsizeiptr s = 0; GLsizeiptr s = 0;
vo.allocate(size); vo.allocate(size);
@ -167,16 +145,88 @@ static size_t initArrowAndLetters(VertexObject &vo)
vo.setBufferData(head.data(), offset, s); vo.setBufferData(head.data(), offset, s);
offset += s; offset += s;
vo.setBufferData(lettersVtx, offset, sizeof(lettersVtx));
vo.setVertices(3, GL_FLOAT, GL_FALSE, 0, 0); vo.setVertices(3, GL_FLOAT, GL_FALSE, 0, 0);
return count; return count;
} }
static void initLetters(VertexObject &vo)
{
vo.bind();
if (vo.initialized())
return;
GLfloat lettersVtx[] =
{
// X
0, 0, 0, 1, 0, 1, -0.5f,
0, 0, 0, 1, 0, 1, 0.5f,
1, 0, 1, 0, 0, 0, -0.5f,
1, 0, 1, 0, 0, 0, -0.5f,
1, 0, 1, 0, 0, 0, 0.5f,
0, 0, 0, 1, 0, 1, -0.5f,
1, 0, 0, 0, 0, 1, -0.5f,
1, 0, 0, 0, 0, 1, 0.5f,
0, 0, 1, 1, 0, 0, -0.5f,
0, 0, 1, 1, 0, 0, -0.5f,
0, 0, 1, 1, 0, 0, 0.5f,
1, 0, 0, 0, 0, 1, -0.5f,
// Y
0, 0, 1, 0.5f, 0, 0.5f, -0.5f,
0, 0, 1, 0.5f, 0, 0.5f, 0.5f,
0.5f, 0, 0.5f, 0, 0, 1, -0.5f,
0.5f, 0, 0.5f, 0, 0, 1, -0.5f,
0.5f, 0, 0.5f, 0, 0, 1, 0.5f,
0, 0, 1, 0.5f, 0, 0.5f, -0.5f,
1, 0, 1, 0.5f, 0, 0.5f, -0.5f,
1, 0, 1, 0.5f, 0, 0.5f, 0.5f,
0.5f, 0, 0.5f, 1, 0, 1, -0.5f,
0.5f, 0, 0.5f, 1, 0, 1, -0.5f,
0.5f, 0, 0.5f, 1, 0, 1, 0.5f,
1, 0, 1, 0.5f, 0, 0.5f, -0.5f,
0.5f, 0, 0, 0.5f, 0, 0.5f, -0.5f,
0.5f, 0, 0, 0.5f, 0, 0.5f, 0.5f,
0.5f, 0, 0.5f, 0.5f, 0, 0, -0.5f,
0.5f, 0, 0.5f, 0.5f, 0, 0, -0.5f,
0.5f, 0, 0.5f, 0.5f, 0, 0, 0.5f,
0.5f, 0, 0, 0.5f, 0, 0.5f, -0.5f,
// Z
0, 0, 1, 1, 0, 1, -0.5f,
0, 0, 1, 1, 0, 1, 0.5f,
1, 0, 1, 0, 0, 1, -0.5f,
1, 0, 1, 0, 0, 1, -0.5f,
1, 0, 1, 0, 0, 1, 0.5f,
0, 0, 1, 1, 0, 1, -0.5f,
1, 0, 1, 0, 0, 0, -0.5f,
1, 0, 1, 0, 0, 0, 0.5f,
0, 0, 0, 1, 0, 1, -0.5f,
0, 0, 0, 1, 0, 1, -0.5f,
0, 0, 0, 1, 0, 1, 0.5f,
1, 0, 1, 0, 0, 0, -0.5f,
0, 0, 0, 1, 0, 0, -0.5f,
0, 0, 0, 1, 0, 0, 0.5f,
1, 0, 0, 0, 0, 0, -0.5f,
1, 0, 0, 0, 0, 0, -0.5f,
1, 0, 0, 0, 0, 0, 0.5f,
0, 0, 0, 1, 0, 0, -0.5f,
};
vo.allocate(sizeof(lettersVtx));
vo.setBufferData(lettersVtx, 0, sizeof(lettersVtx));
vo.setVertices(3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0);
vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, sizeof(float) * 3);
vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex, 1, GL_FLOAT, GL_FALSE, sizeof(float) * 7, sizeof(float) * 6);
}
static void RenderArrow(VertexObject& vo) static void RenderArrow(VertexObject& vo)
{ {
auto count = initArrowAndLetters(vo); auto count = initArrow(vo);
vo.draw(GL_TRIANGLES, count); vo.draw(GL_TRIANGLES, count);
vo.unbind(); vo.unbind();
} }
@ -184,8 +234,8 @@ static void RenderArrow(VertexObject& vo)
// Draw letter x in xz plane // Draw letter x in xz plane
static void RenderX(VertexObject& vo) static void RenderX(VertexObject& vo)
{ {
auto offset = initArrowAndLetters(vo); initLetters(vo);
vo.draw(GL_LINES, 4, offset); vo.draw(GL_TRIANGLES, 12);
vo.unbind(); vo.unbind();
} }
@ -193,8 +243,8 @@ static void RenderX(VertexObject& vo)
// Draw letter y in xz plane // Draw letter y in xz plane
static void RenderY(VertexObject& vo) static void RenderY(VertexObject& vo)
{ {
auto offset = initArrowAndLetters(vo); initLetters(vo);
vo.draw(GL_LINES, 6, offset+4); vo.draw(GL_TRIANGLES, 18, 12);
vo.unbind(); vo.unbind();
} }
@ -202,8 +252,8 @@ static void RenderY(VertexObject& vo)
// Draw letter z in xz plane // Draw letter z in xz plane
static void RenderZ(VertexObject& vo) static void RenderZ(VertexObject& vo)
{ {
auto offset = initArrowAndLetters(vo); initLetters(vo);
vo.draw(GL_LINE_STRIP, 4, offset+10); vo.draw(GL_TRIANGLES, 18, 30);
vo.unbind(); vo.unbind();
} }
@ -387,35 +437,49 @@ AxesReferenceMark::render(Renderer* renderer,
return; return;
prog->use(); prog->use();
auto &vo = renderer->getVertexObject(VOType::AxisArrow, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW); auto &arrowVo = renderer->getVertexObject(VOType::AxisArrow, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
Affine3f labelTransform = Translation3f(Vector3f(0.1f, 0.0f, 0.75f)) * Scaling(labelScale); Affine3f labelTransform = Translation3f(Vector3f(0.1f, 0.0f, 0.75f)) * Scaling(labelScale);
Matrix4f labelTransformMatrix = labelTransform.matrix(); Matrix4f labelTransformMatrix = labelTransform.matrix();
Matrix4f tModelView;
// x-axis // x-axis
tModelView = modelView * vecgl::rotate(AngleAxisf(90.0_deg, Vector3f::UnitY())); Matrix4f xModelView = modelView * vecgl::rotate(AngleAxisf(90.0_deg, Vector3f::UnitY()));
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 1.0f, 0.0f, 0.0f, opacity); glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 1.0f, 0.0f, 0.0f, opacity);
prog->setMVPMatrices(projection, tModelView); prog->setMVPMatrices(projection, xModelView);
RenderArrow(vo); RenderArrow(arrowVo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderX(vo);
// y-axis // y-axis
tModelView = modelView * vecgl::rotate(AngleAxisf(180.0_deg, Vector3f::UnitY())); Matrix4f yModelView = modelView * vecgl::rotate(AngleAxisf(180.0_deg, Vector3f::UnitY()));
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 1.0f, 0.0f, opacity); glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 1.0f, 0.0f, opacity);
prog->setMVPMatrices(projection, tModelView); prog->setMVPMatrices(projection, yModelView);
RenderArrow(vo); RenderArrow(arrowVo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderY(vo);
// z-axis // z-axis
tModelView = modelView *vecgl::rotate(AngleAxisf(-90.0_deg, Vector3f::UnitX())); Matrix4f zModelView = modelView *vecgl::rotate(AngleAxisf(-90.0_deg, Vector3f::UnitX()));
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 0.0f, 1.0f, opacity); glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 0.0f, 1.0f, opacity);
prog->setMVPMatrices(projection, tModelView); prog->setMVPMatrices(projection, zModelView);
RenderArrow(vo); RenderArrow(arrowVo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderZ(vo); ShaderProperties letterProp = shadprop;
letterProp.texUsage |= ShaderProperties::LineAsTriangles;
prog = renderer->getShaderManager().getShader(letterProp);
if (prog == nullptr)
return;
prog->use();
prog->lineWidthX = renderer->getLineWidthX();
prog->lineWidthY = renderer->getLineWidthY();
auto &letterVo = renderer->getVertexObject(VOType::AxisLetter, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 1.0f, 0.0f, 0.0f, opacity);
prog->setMVPMatrices(projection, xModelView * labelTransformMatrix);
RenderX(letterVo);
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 1.0f, 0.0f, opacity);
prog->setMVPMatrices(projection, yModelView * labelTransformMatrix);
RenderY(letterVo);
glVertexAttrib4f(CelestiaGLProgram::ColorAttributeIndex, 0.0f, 0.0f, 1.0f, opacity);
prog->setMVPMatrices(projection, zModelView * labelTransformMatrix);
RenderZ(letterVo);
renderer->enableBlending(); renderer->enableBlending();
renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE); renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE);

View File

@ -21,7 +21,7 @@ using namespace std;
BoundariesRenderer::BoundariesRenderer(const ConstellationBoundaries *boundaries) : BoundariesRenderer::BoundariesRenderer(const ConstellationBoundaries *boundaries) :
m_boundaries(boundaries) m_boundaries(boundaries)
{ {
m_shadprop.texUsage = ShaderProperties::VertexColors; m_shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
m_shadprop.lightModel = ShaderProperties::UnlitModel; m_shadprop.lightModel = ShaderProperties::UnlitModel;
} }
@ -39,54 +39,57 @@ void BoundariesRenderer::render(const Renderer &renderer, const Color &color, co
m_vo.bind(); m_vo.bind();
if (!m_vo.initialized()) if (!m_vo.initialized())
{ {
auto *vtx_buf = prepare(); std::vector<LineEnds> data;
if (vtx_buf == nullptr) if (!prepare(data))
{ {
m_vo.unbind(); m_vo.unbind();
return; return;
} }
m_vo.allocate(m_vtxTotal * 3 * sizeof(GLshort), vtx_buf); m_vo.allocate(m_vtxTotal * sizeof(LineEnds), data.data());
m_vo.setVertices(3, GL_SHORT, false, 0, 0); m_vo.setVertices(3, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, point1));
delete[] vtx_buf; m_vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex, 3, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, point2));
m_vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex, 1, GL_FLOAT, false, sizeof(LineEnds), offsetof(LineEnds, scale));
} }
prog->use(); prog->use();
prog->setMVPMatrices(*mvp.projection, *mvp.modelview); prog->setMVPMatrices(*mvp.projection, *mvp.modelview);
prog->lineWidthX = renderer.getLineWidthX();
prog->lineWidthY = renderer.getLineWidthY();
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color); glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
m_vo.draw(GL_LINES, m_vtxTotal); m_vo.draw(GL_TRIANGLES, m_vtxTotal);
m_vo.unbind(); m_vo.unbind();
} }
GLshort* BoundariesRenderer::prepare() bool BoundariesRenderer::prepare(std::vector<LineEnds> &data)
{ {
auto chains = m_boundaries->getChains(); auto chains = m_boundaries->getChains();
auto vtx_num = accumulate(chains.begin(), chains.end(), 0, auto vtx_num = accumulate(chains.begin(), chains.end(), 0,
[](int a, ConstellationBoundaries::Chain* b) { return a + b->size(); }); [](int a, ConstellationBoundaries::Chain* b) { return a + b->size(); });
if (vtx_num == 0) if (vtx_num == 0)
return nullptr; return false;
// as we use GL_LINES we should double the number of vertices // as we use GL_TRIANGLES we should six times the number of vertices
vtx_num *= 2; vtx_num *= 6;
m_vtxTotal = vtx_num; m_vtxTotal = vtx_num;
auto *vtx_buf = new GLshort[vtx_num * 3]; data.reserve(m_vtxTotal);
GLshort* ptr = vtx_buf;
for (const auto chain : chains) for (const auto chain : chains)
{ {
for (unsigned j = 0; j < 3; j++, ptr++)
*ptr = (GLshort) (*chain)[0][j];
for (unsigned i = 1; i < chain->size(); i++) for (unsigned i = 1; i < chain->size(); i++)
{ {
for (unsigned j = 0; j < 3; j++) Eigen::Vector3f prev = (*chain)[i - 1];
ptr[j] = ptr[j + 3] = (GLshort) (*chain)[i][j]; Eigen::Vector3f cur = (*chain)[i];
ptr += 6; data.emplace_back(prev, cur, -0.5);
data.emplace_back(prev ,cur, 0.5);
data.emplace_back(cur, prev, -0.5);
data.emplace_back(cur, prev, -0.5);
data.emplace_back(cur, prev, 0.5);
data.emplace_back(prev, cur, -0.5);
} }
for (unsigned j = 0; j < 3; j++, ptr++)
*ptr = (GLshort) (*chain)[0][j];
} }
return vtx_buf; return true;
} }

View File

@ -16,6 +16,7 @@ class Color;
class ConstellationBoundaries; class ConstellationBoundaries;
class Renderer; class Renderer;
struct Matrices; struct Matrices;
struct LineEnds;
class BoundariesRenderer class BoundariesRenderer
{ {
@ -32,7 +33,7 @@ class BoundariesRenderer
bool sameBoundaries(const ConstellationBoundaries*) const; bool sameBoundaries(const ConstellationBoundaries*) const;
private: private:
GLshort* prepare(); bool prepare(std::vector<LineEnds> &data);
celgl::VertexObject m_vo { GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW }; celgl::VertexObject m_vo { GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW };
ShaderProperties m_shadprop; ShaderProperties m_shadprop;

View File

@ -165,7 +165,7 @@ public:
vbobj(0), vbobj(0),
currentStripLength(0) currentStripLength(0)
{ {
data = new Vertex[capacity]; data = new Vertex[(capacity + 1) * 2];
} }
~HighPrec_VertexBuffer() ~HighPrec_VertexBuffer()
@ -183,6 +183,8 @@ public:
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
Vector4f* vertexBase = vbobj ? (Vector4f*) offsetof(Vertex, position) : &data[0].position; Vector4f* vertexBase = vbobj ? (Vector4f*) offsetof(Vertex, position) : &data[0].position;
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex, glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
@ -192,6 +194,14 @@ public:
glVertexAttribPointer(CelestiaGLProgram::ColorAttributeIndex, glVertexAttribPointer(CelestiaGLProgram::ColorAttributeIndex,
4, GL_FLOAT, GL_FALSE, sizeof(Vertex), colorBase); 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), colorBase);
float* scaleBase = vbobj ? (float*) offsetof(Vertex, scale) : &data[0].scale;
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(Vertex), scaleBase);
Vector4f* nextVertexBase = vbobj ? (Vector4f*) (offsetof(Vertex, position) + (2 * sizeof(Vertex))) : &data[2].position;
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
4, GL_FLOAT, GL_FALSE, sizeof(Vertex), nextVertexBase);
stripLengths.clear(); stripLengths.clear();
currentStripLength = 0; currentStripLength = 0;
currentPosition = 0; currentPosition = 0;
@ -205,6 +215,8 @@ public:
{ {
glDisableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
#endif #endif
@ -213,16 +225,26 @@ public:
inline void vertex(const Vector3d& v) inline void vertex(const Vector3d& v)
{ {
#if USE_VERTEX_BUFFER #if USE_VERTEX_BUFFER
data[currentPosition].position.segment<3>(0) = v.cast<float>(); Vector3f pos = v.cast<float>();
data[currentPosition].color = color; int index = currentPosition * 2;
data[index].position.segment<3>(0) = pos;
data[index].color = color;
data[index].scale = -0.5f;
data[index + 1].position.segment<3>(0) = pos;
data[index + 1].color = color;
data[index + 1].scale = 0.5f;
++currentPosition; ++currentPosition;
++currentStripLength; ++currentStripLength;
if (currentPosition == capacity) if (currentPosition == capacity)
{ {
flush(); flush();
data[0].position.segment<3>(0) = v.cast<float>(); data[0].position.segment<3>(0) = pos;
data[0].color = color; data[0].color = color;
data[0].scale = -0.5f;
data[1].position.segment<3>(0) = pos;
data[1].color = color;
data[1].scale = 0.5f;
currentPosition = 1; currentPosition = 1;
currentStripLength = 1; currentStripLength = 1;
} }
@ -233,38 +255,32 @@ public:
inline void vertex(const Vector4d& v) inline void vertex(const Vector4d& v)
{ {
#if USE_VERTEX_BUFFER vertex(v, color);
data[currentPosition].position = v.cast<float>();
data[currentPosition].color = color;
++currentPosition;
++currentStripLength;
if (currentPosition == capacity)
{
flush();
data[0].position = v.cast<float>();
data[0].color = color;
currentPosition = 1;
currentStripLength = 1;
}
#else
glVertex3dv(v.data());
#endif
} }
inline void vertex(const Vector4d& v, const Vector4f& color) inline void vertex(const Vector4d& v, const Vector4f& color)
{ {
#if USE_VERTEX_BUFFER #if USE_VERTEX_BUFFER
data[currentPosition].position = v.cast<float>(); Vector4f pos = v.cast<float>();
data[currentPosition].color = color; int index = currentPosition * 2;
data[index].position = pos;
data[index].color = color;
data[index].scale = -0.5f;
data[index + 1].position = pos;
data[index + 1].color = color;
data[index + 1].scale = 0.5f;
++currentPosition; ++currentPosition;
++currentStripLength; ++currentStripLength;
if (currentPosition == capacity) if (currentPosition == capacity)
{ {
flush(); flush();
data[0].position = v.cast<float>(); data[0].position = pos;
data[0].color = color; data[0].color = color;
data[0].scale = -0.5f;
data[1].position = pos;
data[1].color = color;
data[1].scale = 0.5f;
currentPosition = 1; currentPosition = 1;
currentStripLength = 1; currentStripLength = 1;
} }
@ -284,6 +300,12 @@ public:
inline void end() inline void end()
{ {
#if USE_VERTEX_BUFFER #if USE_VERTEX_BUFFER
if (currentPosition > 1)
{
int index = currentPosition * 2;
memcpy(&data[index], &data[index - 4], 2 * sizeof(Vertex));
currentPosition += 1;
}
stripLengths.push_back(currentStripLength); stripLengths.push_back(currentStripLength);
currentStripLength = 0; currentStripLength = 0;
#else #else
@ -296,7 +318,7 @@ public:
#if USE_VERTEX_BUFFER #if USE_VERTEX_BUFFER
if (currentPosition > 0) if (currentPosition > 0)
{ {
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * currentPosition, data); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * (currentPosition + 1) * 2, data);
// Finish the current line strip // Finish the current line strip
if (currentStripLength > 1) if (currentStripLength > 1)
@ -305,8 +327,9 @@ public:
unsigned int startIndex = 0; unsigned int startIndex = 0;
for (vector<unsigned int>::const_iterator iter = stripLengths.begin(); iter != stripLengths.end(); ++iter) for (vector<unsigned int>::const_iterator iter = stripLengths.begin(); iter != stripLengths.end(); ++iter)
{ {
glDrawArrays(GL_LINE_STRIP, startIndex, *iter); unsigned int drawCount = *iter * 2;
startIndex += *iter; glDrawArrays(GL_TRIANGLE_STRIP, startIndex, drawCount);
startIndex += drawCount + 2;
} }
currentPosition = 0; currentPosition = 0;
@ -325,7 +348,7 @@ public:
glGenBuffers(1, &vbobj); glGenBuffers(1, &vbobj);
glBindBuffer(GL_ARRAY_BUFFER, vbobj); glBindBuffer(GL_ARRAY_BUFFER, vbobj);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
capacity * sizeof(Vertex), (2 * (capacity + 1)) * sizeof(Vertex),
nullptr, nullptr,
GL_STREAM_DRAW); GL_STREAM_DRAW);
} }
@ -349,6 +372,7 @@ private:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Vector4f position; Vector4f position;
Vector4f color; Vector4f color;
float scale;
}; };
Vertex* data; Vertex* data;
GLuint vbobj; GLuint vbobj;

View File

@ -24,38 +24,7 @@ using namespace celmath;
using namespace celestia; using namespace celestia;
using namespace Eigen; using namespace Eigen;
constexpr const int SquareOffset = 0;
constexpr const int DiamondOffset = 0;
constexpr const int DiamondCount = 4;
static GLfloat Diamond[DiamondCount * 2] =
{
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, -1.0f,
-1.0f, 0.0f
};
constexpr const int PlusOffset = DiamondOffset + DiamondCount;
constexpr const int PlusCount = 4;
static GLfloat Plus[PlusCount * 2] =
{
0.0f, 1.0f,
0.0f, -1.0f,
1.0f, 0.0f,
-1.0f, 0.0f
};
constexpr const int XOffset = PlusOffset + PlusCount;
constexpr const int XCount = 4;
static GLfloat X[XCount * 2] =
{
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f,
-1.0f, 1.0f
};
constexpr const int SquareOffset = XOffset + XCount;
constexpr const int SquareCount = 4; constexpr const int SquareCount = 4;
static GLfloat Square[SquareCount * 2] = static GLfloat Square[SquareCount * 2] =
{ {
@ -145,7 +114,7 @@ static GLfloat SelPointer[SelPointerCount * 2] =
constexpr const int CrosshairOffset = SelPointerOffset + SelPointerCount; constexpr const int CrosshairOffset = SelPointerOffset + SelPointerCount;
constexpr const int CrosshairCount = 3; constexpr const int CrosshairCount = 3;
static GLfloat Crosshair[CrosshairCount * 2 ] = static GLfloat Crosshair[CrosshairCount * 2] =
{ {
0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, -1.0f,
@ -155,49 +124,117 @@ static GLfloat Crosshair[CrosshairCount * 2 ] =
constexpr const int StaticVtxCount = CrosshairOffset + CrosshairCount; constexpr const int StaticVtxCount = CrosshairOffset + CrosshairCount;
constexpr const int SmallCircleOffset = StaticVtxCount; constexpr const int SmallCircleOffset = StaticVtxCount;
static int SmallCircleCount = 0; constexpr const int SmallCircleCount = 10;
static int LargeCircleOffset = 0; constexpr const int LargeCircleOffset = SmallCircleOffset + SmallCircleCount;
static int LargeCircleCount = 0; constexpr const int LargeCircleCount = 60;
static int EclipticOffset = 0;
constexpr const int EclipticCount = 200; static int DiamondLineOffset = 0;
static int DiamondLineCount = 0;
static int PlusLineOffset = 0;
static int PlusLineCount = 0;
static int XLineOffset = 0;
static int XLineCount = 0;
static int TriangleLineOffset = 0;
static int TriangleLineCount = 0;
static int SquareLineOffset = 0;
static int SquareLineCount = 0;
static int SmallCircleLineOffset = 0;
static int SmallCircleLineCount = 0;
static int LargeCircleLineOffset = 0;
static int LargeCircleLineCount = 0;
static int EclipticLineCount = 0;
static void fillCircleValue(GLfloat* data, int size, float scale)
{
float s, c;
for (int i = 0; i < size; i++)
{
sincos((float) (2 * i) / (float) size * ((float) PI), s, c);
data[i * 2] = c * scale;
data[i * 2 + 1] = s * scale;
}
}
static int bufferVertices(VertexObject& vo, GLfloat* data, int vertexCount, int& offset)
{
int dataSize = vertexCount * 2 * sizeof(GLfloat);
vo.setBufferData(data, offset, dataSize);
offset += dataSize;
return vertexCount;
}
static int bufferLineVertices(VertexObject& vo, GLfloat* data, int vertexSize, int vertexCount, int& offset)
{
int dataSize = vertexCount * 3 * (2 * vertexSize + 1) * sizeof(GLfloat);
GLfloat* tranformed = new GLfloat[dataSize];
GLfloat* ptr = tranformed;
for (int i = 0; i < vertexCount; i += 2)
{
int index = i * vertexSize;
GLfloat* thisVert = &data[index];
GLfloat* nextVert = &data[index + vertexSize];
#define STREAM_AND_ADVANCE(firstVertex, secondVertex, scale) do {\
memcpy(ptr, firstVertex, vertexSize * sizeof(GLfloat));\
memcpy(ptr + vertexSize, secondVertex, vertexSize * sizeof(GLfloat));\
ptr[2 * vertexSize] = scale;\
ptr += 2 * vertexSize + 1;\
} while (0)
STREAM_AND_ADVANCE(thisVert, nextVert, -0.5);
STREAM_AND_ADVANCE(thisVert, nextVert, 0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, -0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, -0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, 0.5);
STREAM_AND_ADVANCE(thisVert, nextVert, -0.5);
#undef STREAM_AND_ADVANCE
}
vo.setBufferData(tranformed, offset, dataSize);
offset += dataSize;
delete[] tranformed;
return vertexCount * 3;
}
static int bufferLineLoopVertices(VertexObject& vo, GLfloat* data, int vertexSize, int vertexCount, int& offset)
{
int dataSize = vertexCount * 6 * (2 * vertexSize + 1) * sizeof(GLfloat);
GLfloat* tranformed = new GLfloat[dataSize];
GLfloat* ptr = tranformed;
for (int i = 0; i < vertexCount; i += 1)
{
int index = i * vertexSize;
int nextIndex = ((i + 1) % vertexCount) * vertexSize;
GLfloat* thisVert = &data[index];
GLfloat* nextVert = &data[nextIndex];
#define STREAM_AND_ADVANCE(firstVertex, secondVertex, scale) do {\
memcpy(ptr, firstVertex, vertexSize * sizeof(GLfloat));\
memcpy(ptr + vertexSize, secondVertex, vertexSize * sizeof(GLfloat));\
ptr[2 * vertexSize] = scale;\
ptr += 2 * vertexSize + 1;\
} while (0)
STREAM_AND_ADVANCE(thisVert, nextVert, -0.5);
STREAM_AND_ADVANCE(thisVert, nextVert, 0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, -0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, -0.5);
STREAM_AND_ADVANCE(nextVert, thisVert, 0.5);
STREAM_AND_ADVANCE(thisVert, nextVert, -0.5);
#undef STREAM_AND_ADVANCE
}
vo.setBufferData(tranformed, offset, dataSize);
offset += dataSize;
delete[] tranformed;
return vertexCount * 6;
}
static void initVO(VertexObject& vo) static void initVO(VertexObject& vo)
{ {
float c, s; GLfloat SmallCircle[SmallCircleCount * 2];
GLfloat LargeCircle[LargeCircleCount * 2];
fillCircleValue(SmallCircle, SmallCircleCount, 1.0f);
fillCircleValue(LargeCircle, LargeCircleCount, 1.0f);
vector<GLfloat> small, large; vo.allocate((LargeCircleOffset + LargeCircleCount) * sizeof(GLfloat) * 2);
for (int i = 0; i < 360; i += 36)
{
sincos(degToRad(static_cast<float>(i)), s, c);
small.push_back(c); small.push_back(s);
large.push_back(c); large.push_back(s);
for (int j = i+6; j < i+36; j += 6)
{
sincos(degToRad(static_cast<float>(j)), s, c);
large.push_back(c); large.push_back(s);
}
};
SmallCircleCount = small.size() / 2; int offset = 0;
LargeCircleCount = large.size() / 2; #define VOSTREAM(a) bufferVertices(vo, a, a##Count, offset)
LargeCircleOffset = SmallCircleOffset + SmallCircleCount;
vector<GLfloat> ecliptic;
for (int i = 0; i < EclipticCount; i++)
{
sincos((float) (2 * i) / (float) EclipticCount * ((float) PI), s, c);
ecliptic.push_back(c * 1000.0f);
ecliptic.push_back(s * 1000.0f);
}
EclipticOffset = LargeCircleOffset + LargeCircleCount;
#define VTXTOMEM(a) ((a) * sizeof(GLfloat) * 2)
vo.allocate(VTXTOMEM(StaticVtxCount + SmallCircleCount + LargeCircleCount + EclipticCount));
#define VOSTREAM(a) vo.setBufferData(a, VTXTOMEM(a ## Offset), sizeof(a))
VOSTREAM(Diamond);
VOSTREAM(Plus);
VOSTREAM(X);
VOSTREAM(Square); VOSTREAM(Square);
VOSTREAM(Triangle); VOSTREAM(Triangle);
VOSTREAM(RightArrow); VOSTREAM(RightArrow);
@ -206,57 +243,162 @@ static void initVO(VertexObject& vo)
VOSTREAM(DownArrow); VOSTREAM(DownArrow);
VOSTREAM(SelPointer); VOSTREAM(SelPointer);
VOSTREAM(Crosshair); VOSTREAM(Crosshair);
VOSTREAM(SmallCircle);
VOSTREAM(LargeCircle);
#undef VOSTREAM #undef VOSTREAM
vo.setBufferData(small.data(), VTXTOMEM(SmallCircleOffset), memsize(small));
vo.setBufferData(large.data(), VTXTOMEM(LargeCircleOffset), memsize(large));
vo.setBufferData(ecliptic.data(), VTXTOMEM(EclipticOffset), memsize(ecliptic));
#undef VTXTOMEM
vo.setVertices(2, GL_FLOAT, false, 0, 0); vo.setVertices(2, GL_FLOAT, false, 0, 0);
} }
static void initLineVO(VertexObject& vo)
{
constexpr const int DiamondCount = 4;
static GLfloat Diamond[DiamondCount * 2] =
{
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, -1.0f,
-1.0f, 0.0f
};
constexpr const int PlusCount = 4;
GLfloat Plus[PlusCount * 2] =
{
0.0f, 1.0f,
0.0f, -1.0f,
1.0f, 0.0f,
-1.0f, 0.0f
};
constexpr const int XCount = 4;
GLfloat X[XCount * 2] =
{
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f,
-1.0f, 1.0f
};
GLfloat SmallCircle[SmallCircleCount * 2];
GLfloat LargeCircle[LargeCircleCount * 2];
fillCircleValue(SmallCircle, SmallCircleCount, 1.0f);
fillCircleValue(LargeCircle, LargeCircleCount, 1.0f);
int stride = sizeof(GLfloat) * 5;
int size = ((DiamondCount + SquareCount + TriangleCount + SmallCircleCount + LargeCircleCount) * 6 + (PlusCount + XCount) * 3) * stride;
vo.allocate(size);
int offset = 0;
#define VOSTREAM_LINES(a) do { \
a##LineOffset = offset / stride;\
a##LineCount = bufferLineVertices(vo, a, 2, a##Count, offset); \
} while (0)
#define VOSTREAM_LINE_LOOP(a) do { \
a##LineOffset = offset / stride;\
a##LineCount = bufferLineLoopVertices(vo, a, 2, a##Count, offset); \
} while (0)
VOSTREAM_LINE_LOOP(Diamond);
VOSTREAM_LINES(Plus);
VOSTREAM_LINES(X);
VOSTREAM_LINE_LOOP(Square);
VOSTREAM_LINE_LOOP(Triangle);
VOSTREAM_LINE_LOOP(SmallCircle);
VOSTREAM_LINE_LOOP(LargeCircle);
#undef VOSTREAM_LINES
#undef VOSTREAM_LINE_LOOP
vo.setVertices(2, GL_FLOAT, false, stride, 0);
vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex, 2, GL_FLOAT, false, stride, sizeof(GLfloat) * 2);
vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex, 1, GL_FLOAT, false, stride, sizeof(GLfloat) * 4);
}
static void initEclipticVO(VertexObject& vo)
{
constexpr const int eclipticCount = 200;
GLfloat ecliptic[eclipticCount * 3];
float s, c;
float scale = 1000.0f;
for (int i = 0; i < eclipticCount; i++)
{
sincos((float) (2 * i) / (float) eclipticCount * ((float) PI), s, c);
ecliptic[i * 3] = c * scale;
ecliptic[i * 3 + 1] = 0;
ecliptic[i * 3 + 2] = s * scale;
}
int stride = sizeof(GLfloat) * 7;
vo.allocate(eclipticCount * 6 * stride);
int offset = 0;
EclipticLineCount = bufferLineLoopVertices(vo, ecliptic, 3, eclipticCount, offset);
vo.setVertices(3, GL_FLOAT, false, stride, 0);
vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex, 3, GL_FLOAT, false, stride, sizeof(GLfloat) * 3);
vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex, 1, GL_FLOAT, false, stride, sizeof(GLfloat) * 6);
}
void Renderer::renderMarker(MarkerRepresentation::Symbol symbol, void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
float size, float size,
const Color &color, const Color &color,
const Matrices &m) const Matrices &m)
{ {
assert(shaderManager != nullptr); assert(shaderManager != nullptr);
bool solid = true;
switch (symbol)
{
case MarkerRepresentation::Diamond:
case MarkerRepresentation::Plus:
case MarkerRepresentation::X:
case MarkerRepresentation::Square:
case MarkerRepresentation::Triangle:
case MarkerRepresentation::Circle:
solid = false;
default:
break;
}
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors; shadprop.texUsage = ShaderProperties::VertexColors;
if (!solid)
shadprop.texUsage |= ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
shadprop.fishEyeOverride = ShaderProperties::FisheyeOverrideModeDisabled; shadprop.fishEyeOverride = ShaderProperties::FisheyeOverrideModeDisabled;
auto* prog = shaderManager->getShader(shadprop); auto* prog = shaderManager->getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
return; return;
auto &markerVO = getVertexObject(VOType::Marker, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW); auto &markerVO = getVertexObject(solid ? VOType::Marker : VOType::MarkerLine, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
markerVO.bind(); markerVO.bind();
if (!markerVO.initialized()) if (!markerVO.initialized())
initVO(markerVO); solid ? initVO(markerVO) : initLineVO(markerVO);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color); glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
prog->use(); prog->use();
float s = size / 2.0f; float s = size / 2.0f * getScaleFactor();
prog->setMVPMatrices(*m.projection, (*m.modelview) * vecgl::scale(Vector3f(s, s, 0))); prog->setMVPMatrices(*m.projection, (*m.modelview) * vecgl::scale(Vector3f(s, s, 0)));
if (!solid)
{
prog->lineWidthX = getLineWidthX();
prog->lineWidthY = getLineWidthY();
}
switch (symbol) switch (symbol)
{ {
case MarkerRepresentation::Diamond: case MarkerRepresentation::Diamond:
markerVO.draw(GL_LINE_LOOP, DiamondCount, DiamondOffset); markerVO.draw(GL_TRIANGLES, DiamondLineCount, DiamondLineOffset);
break; break;
case MarkerRepresentation::Plus: case MarkerRepresentation::Plus:
markerVO.draw(GL_LINES, PlusCount, PlusOffset); markerVO.draw(GL_TRIANGLES, PlusLineCount, PlusLineOffset);
break; break;
case MarkerRepresentation::X: case MarkerRepresentation::X:
markerVO.draw(GL_LINES, XCount, XOffset); markerVO.draw(GL_TRIANGLES, XLineCount, XLineOffset);
break; break;
case MarkerRepresentation::Square: case MarkerRepresentation::Square:
markerVO.draw(GL_LINE_LOOP, SquareCount, SquareOffset); markerVO.draw(GL_TRIANGLES, SquareLineCount, SquareLineOffset);
break; break;
case MarkerRepresentation::FilledSquare: case MarkerRepresentation::FilledSquare:
@ -264,7 +406,7 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
break; break;
case MarkerRepresentation::Triangle: case MarkerRepresentation::Triangle:
markerVO.draw(GL_LINE_LOOP, TriangleCount, TriangleOffset); markerVO.draw(GL_TRIANGLES, TriangleLineCount, TriangleLineOffset);
break; break;
case MarkerRepresentation::RightArrow: case MarkerRepresentation::RightArrow:
@ -284,14 +426,14 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
break; break;
case MarkerRepresentation::Circle: case MarkerRepresentation::Circle:
if (s <= 20) if (size <= 40.0f) // TODO: this should be configurable
markerVO.draw(GL_LINE_LOOP, SmallCircleCount, SmallCircleOffset); markerVO.draw(GL_TRIANGLES, SmallCircleLineCount, SmallCircleLineOffset);
else else
markerVO.draw(GL_LINE_LOOP, LargeCircleCount, LargeCircleOffset); markerVO.draw(GL_TRIANGLES, LargeCircleLineCount, LargeCircleLineOffset);
break; break;
case MarkerRepresentation::Disk: case MarkerRepresentation::Disk:
if (s <= 20) // TODO: this should be configurable if (size <= 40.0f) // TODO: this should be configurable
markerVO.draw(GL_TRIANGLE_FAN, SmallCircleCount, SmallCircleOffset); markerVO.draw(GL_TRIANGLE_FAN, SmallCircleCount, SmallCircleOffset);
else else
markerVO.draw(GL_TRIANGLE_FAN, LargeCircleCount, LargeCircleOffset); markerVO.draw(GL_TRIANGLE_FAN, LargeCircleCount, LargeCircleOffset);
@ -365,7 +507,7 @@ void Renderer::renderSelectionPointer(const Observer& observer,
const Vector3f &center = cameraMatrix.col(2); const Vector3f &center = cameraMatrix.col(2);
prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix() * vecgl::translate(Vector3f(-center))); prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix() * vecgl::translate(Vector3f(-center)));
prog->vec4Param("color") = Color(SelectionCursorColor, 0.6f).toVector4(); prog->vec4Param("color") = Color(SelectionCursorColor, 0.6f).toVector4();
prog->floatParam("pixelSize") = pixelSize; prog->floatParam("pixelSize") = pixelSize * getScaleFactor();
prog->floatParam("s") = s; prog->floatParam("s") = s;
prog->floatParam("c") = c; prog->floatParam("c") = c;
prog->floatParam("x0") = x0; prog->floatParam("x0") = x0;
@ -390,22 +532,27 @@ void Renderer::renderEclipticLine()
if ((renderFlags & ShowEcliptic) == 0) if ((renderFlags & ShowEcliptic) == 0)
return; return;
assert(shaderManager != nullptr); ShaderProperties shadprop;
auto* prog = shaderManager->getShader("ecliptic"); shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
auto* prog = shaderManager->getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
return; return;
auto &markerVO = getVertexObject(VOType::Marker, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW); auto &eclipticVO = getVertexObject(VOType::Ecliptic, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
markerVO.bind(); eclipticVO.bind();
if (!markerVO.initialized()) if (!eclipticVO.initialized())
initVO(markerVO); initEclipticVO(eclipticVO);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, EclipticColor);
prog->use(); prog->use();
prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix()); prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix());
prog->vec4Param("color") = EclipticColor.toVector4(); prog->lineWidthX = getLineWidthX();
markerVO.draw(GL_LINE_LOOP, EclipticCount, EclipticOffset); prog->lineWidthY = getLineWidthY();
eclipticVO.draw(GL_TRIANGLES, EclipticLineCount, 0);
markerVO.unbind(); eclipticVO.unbind();
} }
void Renderer::renderCrosshair(float selectionSizeInPixels, void Renderer::renderCrosshair(float selectionSizeInPixels,
@ -439,8 +586,9 @@ void Renderer::renderCrosshair(float selectionSizeInPixels,
prog->setMVPMatrices(*m.projection, *m.modelview); prog->setMVPMatrices(*m.projection, *m.modelview);
prog->vec4Param("color") = color.toVector4(); prog->vec4Param("color") = color.toVector4();
prog->floatParam("radius") = cursorRadius; prog->floatParam("radius") = cursorRadius;
prog->floatParam("width") = minCursorWidth * cursorGrow; float scaleFactor = getScaleFactor();
prog->floatParam("h") = 2.0f * cursorGrow; prog->floatParam("width") = minCursorWidth * cursorGrow * scaleFactor;
prog->floatParam("h") = 2.0f * cursorGrow * scaleFactor;
const unsigned int markCount = 4; const unsigned int markCount = 4;
for (unsigned int i = 0; i < markCount; i++) for (unsigned int i = 0; i < markCount; i++)

View File

@ -25,14 +25,14 @@ using namespace celestia;
unsigned int PlanetographicGrid::circleSubdivisions = 100; unsigned int PlanetographicGrid::circleSubdivisions = 100;
float* PlanetographicGrid::xyCircle = nullptr; std::vector<LineStripEnd> PlanetographicGrid::xyCircle;
float* PlanetographicGrid::xzCircle = nullptr; std::vector<LineStripEnd> PlanetographicGrid::xzCircle;
PlanetographicGrid::PlanetographicGrid(const Body& _body) : PlanetographicGrid::PlanetographicGrid(const Body& _body) :
body(_body) body(_body)
{ {
if (xyCircle == nullptr) if (xyCircle.empty())
InitializeGeometry(); InitializeGeometry();
setTag("planetographic grid"); setTag("planetographic grid");
setIAULongLatConvention(); setIAULongLatConvention();
@ -93,7 +93,7 @@ PlanetographicGrid::render(Renderer* renderer,
const Matrices& m) const const Matrices& m) const
{ {
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors; shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = renderer->getShaderManager().getShader(shadprop); auto *prog = renderer->getShaderManager().getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
@ -129,8 +129,14 @@ PlanetographicGrid::render(Renderer* renderer,
Matrix4f modelView = *m.modelview * transform.matrix(); Matrix4f modelView = *m.modelview * transform.matrix();
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex, glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, 0, xzCircle); 3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xzCircle[0].point);
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xzCircle[2].point);
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xzCircle[0].scale);
// Only show the coordinate labels if the body is sufficiently large on screen // Only show the coordinate labels if the body is sufficiently large on screen
bool showCoordinateLabels = false; bool showCoordinateLabels = false;
@ -146,6 +152,8 @@ PlanetographicGrid::render(Renderer* renderer,
} }
prog->use(); prog->use();
float lineWidthX = renderer->getLineWidthX();
float lineWidthY = renderer->getLineWidthY();
for (float latitude = -90.0f + latitudeStep; latitude < 90.0f; latitude += latitudeStep) for (float latitude = -90.0f + latitudeStep; latitude < 90.0f; latitude += latitudeStep)
{ {
@ -156,17 +164,18 @@ PlanetographicGrid::render(Renderer* renderer,
{ {
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex,
Renderer::PlanetEquatorColor); Renderer::PlanetEquatorColor);
glLineWidth(2.0f * renderer->getScreenDpi() / 96.0f); prog->lineWidthX = 2.0f * lineWidthX;
prog->lineWidthY = 2.0f * lineWidthY;
} }
else else
{ {
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex,
Renderer::PlanetographicGridColor); Renderer::PlanetographicGridColor);
prog->lineWidthX = lineWidthX;
prog->lineWidthY = lineWidthY;
} }
prog->setMVPMatrices(projection, modelView * vecgl::translate(0.0f, sin(phi), 0.0f) * vecgl::scale(r)); prog->setMVPMatrices(projection, modelView * vecgl::translate(0.0f, sin(phi), 0.0f) * vecgl::scale(r));
glDrawArrays(GL_LINE_LOOP, 0, circleSubdivisions); glDrawArrays(GL_TRIANGLE_STRIP, 0, xzCircle.size() - 2);
glLineWidth(1.0f * renderer->getScreenDpi() / 96.0f);
if (showCoordinateLabels) if (showCoordinateLabels)
{ {
@ -186,14 +195,18 @@ PlanetographicGrid::render(Renderer* renderer,
} }
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex, glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, 0, xyCircle); 3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xyCircle[0].point);
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xyCircle[2].point);
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &xyCircle[0].scale);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex,
Renderer::PlanetographicGridColor); Renderer::PlanetographicGridColor);
for (float longitude = 0.0f; longitude <= 180.0f; longitude += longitudeStep) for (float longitude = 0.0f; longitude <= 180.0f; longitude += longitudeStep)
{ {
prog->setMVPMatrices(projection, modelView * vecgl::rotate(AngleAxisf(degToRad(longitude), Vector3f::UnitY()))); prog->setMVPMatrices(projection, modelView * vecgl::rotate(AngleAxisf(degToRad(longitude), Vector3f::UnitY())));
glDrawArrays(GL_LINE_LOOP, 0, circleSubdivisions); glDrawArrays(GL_TRIANGLE_STRIP, 0, xyCircle.size() - 2);
if (showCoordinateLabels) if (showCoordinateLabels)
{ {
@ -247,6 +260,8 @@ PlanetographicGrid::render(Renderer* renderer,
} }
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
renderer->enableBlending(); renderer->enableBlending();
renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE); renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE);
@ -291,18 +306,18 @@ PlanetographicGrid::setIAULongLatConvention()
void void
PlanetographicGrid::InitializeGeometry() PlanetographicGrid::InitializeGeometry()
{ {
xyCircle = new float[circleSubdivisions * 3]; xyCircle.reserve((circleSubdivisions + 2) * 2);
xzCircle = new float[circleSubdivisions * 3]; xzCircle.reserve((circleSubdivisions + 2) * 2);
for (unsigned int i = 0; i < circleSubdivisions; i++) for (unsigned int i = 0; i <= circleSubdivisions + 1; i++)
{ {
float theta = (float) (2.0 * PI) * (float) i / (float) circleSubdivisions; float theta = (float) (2.0 * PI) * (float) i / (float) circleSubdivisions;
float s, c; float s, c;
sincos(theta, s, c); sincos(theta, s, c);
xyCircle[i * 3 + 0] = c; Vector3f thisPointXY(c, s, 0.0f);
xyCircle[i * 3 + 1] = s; Vector3f thisPointXZ(c, 0.0f, s);
xyCircle[i * 3 + 2] = 0.0f; xyCircle.emplace_back(thisPointXY, -0.5f);
xzCircle[i * 3 + 0] = c; xyCircle.emplace_back(thisPointXY, 0.5f);
xzCircle[i * 3 + 1] = 0.0f; xzCircle.emplace_back(thisPointXZ, -0.5f);
xzCircle[i * 3 + 2] = s; xzCircle.emplace_back(thisPointXZ, 0.5f);
} }
} }

View File

@ -16,7 +16,7 @@
#include <celengine/referencemark.h> #include <celengine/referencemark.h>
class Body; class Body;
struct LineStripEnd;
class PlanetographicGrid : public ReferenceMark class PlanetographicGrid : public ReferenceMark
{ {
@ -71,8 +71,8 @@ private:
NorthDirection northDirection{ NorthNormal }; NorthDirection northDirection{ NorthNormal };
static unsigned int circleSubdivisions; static unsigned int circleSubdivisions;
static float* xyCircle; static std::vector<LineStripEnd> xyCircle;
static float* xzCircle; static std::vector<LineStripEnd> xzCircle;
}; };
#endif // _CELENGINE_PLANETGRID_H_ #endif // _CELENGINE_PLANETGRID_H_

View File

@ -162,8 +162,11 @@ RenderContext::drawGroup(const Mesh::PrimitiveGroup& group)
return; return;
} }
bool drawPoints = false;
bool drawLines = false;
if (group.prim == Mesh::SpriteList || group.prim == Mesh::PointList) if (group.prim == Mesh::SpriteList || group.prim == Mesh::PointList)
{ {
drawPoints = true;
if (group.prim == Mesh::PointList) if (group.prim == Mesh::PointList)
glVertexAttrib1f(CelestiaGLProgram::PointSizeAttributeIndex, 1.0f); glVertexAttrib1f(CelestiaGLProgram::PointSizeAttributeIndex, 1.0f);
#ifndef GL_ES #ifndef GL_ES
@ -172,17 +175,26 @@ RenderContext::drawGroup(const Mesh::PrimitiveGroup& group)
#endif #endif
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
else if (group.prim == Mesh::LineList || group.prim == Mesh::LineStrip)
{
drawLines = true;
renderer->enableSmoothLines();
}
glDrawElements(GLPrimitiveModes[(int) group.prim], glDrawElements(GLPrimitiveModes[(int) group.prim],
group.nIndices, group.nIndices,
GL_UNSIGNED_INT, GL_UNSIGNED_INT,
group.indices); group.indices);
#ifndef GL_ES #ifndef GL_ES
if (group.prim == Mesh::SpriteList || group.prim == Mesh::PointList) if (drawPoints)
{ {
glDisable(GL_POINT_SPRITE); glDisable(GL_POINT_SPRITE);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
} }
else if (drawLines)
{
renderer->disableSmoothLines();
}
#endif #endif
} }

View File

@ -701,6 +701,31 @@ void Renderer::setScreenDpi(int _dpi)
screenDpi = _dpi; screenDpi = _dpi;
} }
float Renderer::getScaleFactor() const
{
return screenDpi / 96.0f;
}
float Renderer::getPointWidth() const
{
return 2.0f / windowWidth * getScaleFactor();
}
float Renderer::getPointHeight() const
{
return 2.0f / windowHeight * getScaleFactor();
}
float Renderer::getLineWidthX() const
{
return ((renderFlags | ShowSmoothLines) ? 1.5f : 1.0f) * getPointWidth();
}
float Renderer::getLineWidthY() const
{
return ((renderFlags | ShowSmoothLines) ? 1.5f : 1.0f) * getPointHeight();
}
void Renderer::setFaintestAM45deg(float _faintestAutoMag45deg) void Renderer::setFaintestAM45deg(float _faintestAutoMag45deg)
{ {
faintestAutoMag45deg = _faintestAutoMag45deg; faintestAutoMag45deg = _faintestAutoMag45deg;
@ -1033,7 +1058,7 @@ Renderer::enableSmoothLines()
#ifndef GL_ES #ifndef GL_ES
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
#endif #endif
glLineWidth(1.5f * screenDpi / 96.0f); glLineWidth(1.5f * getScaleFactor());
} }
void void
@ -1047,7 +1072,7 @@ Renderer::disableSmoothLines()
#ifndef GL_ES #ifndef GL_ES
glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_SMOOTH);
#endif #endif
glLineWidth(1.0f * screenDpi / 96.0f); glLineWidth(1.0f * getScaleFactor());
} }
Vector4f renderOrbitColor(const Body *body, bool selected, float opacity) Vector4f renderOrbitColor(const Body *body, bool selected, float opacity)
@ -1117,7 +1142,7 @@ void Renderer::renderOrbit(const OrbitPathListEntry& orbitPath,
const Matrices& m) const Matrices& m)
{ {
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors; shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = shaderManager->getShader(shadprop); auto *prog = shaderManager->getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
@ -1320,6 +1345,8 @@ void Renderer::renderOrbit(const OrbitPathListEntry& orbitPath,
prog->use(); prog->use();
prog->setMVPMatrices(*m.projection); prog->setMVPMatrices(*m.projection);
prog->lineWidthX = getPointWidth();
prog->lineWidthY = getPointHeight();
if (orbit->isPeriodic()) if (orbit->isPeriodic())
{ {
double period = orbit->getPeriod(); double period = orbit->getPeriod();
@ -1722,9 +1749,7 @@ void Renderer::draw(const Observer& observer,
disableDepthMask(); disableDepthMask();
// Render sky grids first--these will always be in the background // Render sky grids first--these will always be in the background
enableSmoothLines();
renderSkyGrids(observer); renderSkyGrids(observer);
disableSmoothLines();
enableBlending(); enableBlending();
// Render deep sky objects // Render deep sky objects
@ -3869,9 +3894,7 @@ void Renderer::renderAsterisms(const Universe& universe, float dist, const Matri
(MaxAsterismLinesDist - MaxAsterismLinesConstDist) + 1); (MaxAsterismLinesDist - MaxAsterismLinesConstDist) + 1);
} }
enableSmoothLines();
m_asterismRenderer->render(*this, Color(ConstellationColor, opacity), mvp); m_asterismRenderer->render(*this, Color(ConstellationColor, opacity), mvp);
disableSmoothLines();
} }
@ -3900,9 +3923,7 @@ void Renderer::renderBoundaries(const Universe& universe, float dist, const Matr
(MaxAsterismLabelsDist - MaxAsterismLabelsConstDist) + 1); (MaxAsterismLabelsDist - MaxAsterismLabelsConstDist) + 1);
} }
enableSmoothLines();
m_boundariesRenderer->render(*this, Color(BoundaryColor, opacity), mvp); m_boundariesRenderer->render(*this, Color(BoundaryColor, opacity), mvp);
disableSmoothLines();
} }
@ -4689,10 +4710,6 @@ void Renderer::renderDeepSkyObjects(const Universe& universe,
openClusterRep = MarkerRepresentation(MarkerRepresentation::Circle, 8.0f, OpenClusterLabelColor); openClusterRep = MarkerRepresentation(MarkerRepresentation::Circle, 8.0f, OpenClusterLabelColor);
globularRep = MarkerRepresentation(MarkerRepresentation::Circle, 8.0f, GlobularLabelColor); globularRep = MarkerRepresentation(MarkerRepresentation::Circle, 8.0f, GlobularLabelColor);
// Render any line primitives with smooth lines
// (mostly to make graticules look good.)
enableSmoothLines();
setBlendingFactors(GL_SRC_ALPHA, GL_ONE); setBlendingFactors(GL_SRC_ALPHA, GL_ONE);
#ifdef OCTREE_DEBUG #ifdef OCTREE_DEBUG
@ -4713,8 +4730,6 @@ void Renderer::renderDeepSkyObjects(const Universe& universe,
#endif #endif
// clog << "DSOs processed: " << dsoRenderer.dsosProcessed << endl; // clog << "DSOs processed: " << dsoRenderer.dsosProcessed << endl;
disableSmoothLines();
} }
@ -4946,9 +4961,6 @@ void Renderer::renderAnnotations(const vector<Annotation>& annotations,
if (font[fs] == nullptr) if (font[fs] == nullptr)
return; return;
// Enable line smoothing for rendering symbols
enableSmoothLines();
#ifdef USE_HDR #ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
#endif #endif
@ -5010,7 +5022,6 @@ void Renderer::renderAnnotations(const vector<Annotation>& annotations,
#endif #endif
font[fs]->unbind(); font[fs]->unbind();
disableSmoothLines();
} }
@ -5444,10 +5455,14 @@ void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
bool solid = r.type != Rect::Type::BorderOnly;
if (r.nColors > 0) if (r.nColors > 0)
shadprop.texUsage |= ShaderProperties::VertexColors; shadprop.texUsage |= ShaderProperties::VertexColors;
if (r.tex != nullptr) if (r.tex != nullptr)
shadprop.texUsage |= ShaderProperties::DiffuseTexture; shadprop.texUsage |= ShaderProperties::DiffuseTexture;
if (!solid)
shadprop.texUsage |= ShaderProperties::LineAsTriangles;
shadprop.fishEyeOverride = fishEyeOverrideMode; shadprop.fishEyeOverride = fishEyeOverrideMode;
@ -5457,10 +5472,55 @@ void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen
constexpr array<short, 8> texels = {0, 1, 1, 1, 1, 0, 0, 0}; constexpr array<short, 8> texels = {0, 1, 1, 1, 1, 0, 0, 0};
array<float, 8> vertices = { r.x, r.y, r.x+r.w, r.y, r.x+r.w, r.y+r.h, r.x, r.y+r.h }; array<float, 8> vertices = { r.x, r.y, r.x+r.w, r.y, r.x+r.w, r.y+r.h, r.x, r.y+r.h };
array<float, 80> lineAsTriangleVertices = {
r.x, r.y, r.x + r.w, r.y, -0.5,
r.x, r.y, r.x + r.w, r.y, 0.5,
r.x + r.w, r.y, r.x, r.y, -0.5,
r.x + r.w, r.y, r.x, r.y, 0.5,
r.x + r.w, r.y, r.x + r.w, r.y + r.h, -0.5,
r.x + r.w, r.y, r.x + r.w, r.y + r.h, 0.5,
r.x + r.w, r.y + r.h, r.x + r.w, r.y, -0.5,
r.x + r.w, r.y + r.h, r.x + r.w, r.y, 0.5,
r.x + r.w, r.y + r.h, r.x, r.y + r.h, -0.5,
r.x + r.w, r.y + r.h, r.x, r.y + r.h, 0.5,
r.x, r.y + r.h, r.x + r.w, r.y + r.h, -0.5,
r.x, r.y + r.h, r.x + r.w, r.y + r.h, 0.5,
r.x, r.y + r.h, r.x, r.y, -0.5,
r.x, r.y + r.h, r.x, r.y, 0.5,
r.x, r.y, r.x, r.y + r.h, -0.5,
r.x, r.y, r.x, r.y + r.h, 0.5,
};
constexpr array<short, 24> lineAsTriangleIndcies = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12
};
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex, if (solid)
2, GL_FLOAT, GL_FALSE, 0, vertices.data()); {
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
2, GL_FLOAT, GL_FALSE, 0, vertices.data());
}
else
{
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, lineAsTriangleVertices.data());
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, lineAsTriangleVertices.data() + 2);
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(float) * 5, lineAsTriangleVertices.data() + 4);
}
if (r.tex != nullptr) if (r.tex != nullptr)
{ {
glEnableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
@ -5482,22 +5542,22 @@ void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen
prog->use(); prog->use();
prog->setMVPMatrices(p, m); prog->setMVPMatrices(p, m);
if (r.type != Rect::Type::BorderOnly) if (solid)
{ {
glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
} }
else else
{ {
if (r.lw != 1.0f) prog->lineWidthX = getLineWidthX() * r.lw;
glLineWidth(r.lw * screenDpi / 96.0f); prog->lineWidthY = getLineWidthY() * r.lw;
glDrawArrays(GL_LINE_LOOP, 0, 4); glDrawElements(GL_TRIANGLES, lineAsTriangleIndcies.size(), GL_UNSIGNED_SHORT, lineAsTriangleIndcies.data());
if (r.lw != 1.0f)
glLineWidth(1.0f * screenDpi / 96.0f);
} }
glDisableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
} }
void Renderer::setRenderRegion(int x, int y, int width, int height, bool withScissor) void Renderer::setRenderRegion(int x, int y, int width, int height, bool withScissor)
@ -5551,13 +5611,18 @@ bool Renderer::getInfo(map<string, string>& info) const
#endif #endif
GLint pointSizeRange[2]; GLint pointSizeRange[2];
GLfloat lineWidthRange[2];
#ifdef GL_ES #ifdef GL_ES
glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange); glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
#else #else
glGetIntegerv(GL_SMOOTH_POINT_SIZE_RANGE, pointSizeRange); glGetIntegerv(GL_SMOOTH_POINT_SIZE_RANGE, pointSizeRange);
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, lineWidthRange);
#endif #endif
info["PointSizeMin"] = to_string(pointSizeRange[0]); info["PointSizeMin"] = to_string(pointSizeRange[0]);
info["PointSizeMax"] = to_string(pointSizeRange[1]); info["PointSizeMax"] = to_string(pointSizeRange[1]);
info["LineWidthMin"] = to_string(lineWidthRange[0]);
info["LineWidthMax"] = to_string(lineWidthRange[1]);
#ifndef GL_ES #ifndef GL_ES
GLfloat pointSizeGran = 0; GLfloat pointSizeGran = 0;
@ -6142,8 +6207,6 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
#else #else
setBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); setBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#endif #endif
enableSmoothLines();
// Scan through the list of orbits and render any that overlap this interval // Scan through the list of orbits and render any that overlap this interval
for (const auto& orbit : orbitPathList) for (const auto& orbit : orbitPathList)
{ {
@ -6163,8 +6226,6 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
m); m);
} }
} }
disableSmoothLines();
} }
// Render transparent objects in the second pass // Render transparent objects in the second pass
@ -6178,13 +6239,11 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
} }
// Render annotations in this interval // Render annotations in this interval
enableSmoothLines();
annotation = renderSortedAnnotations(annotation, annotation = renderSortedAnnotations(annotation,
nearPlaneDistance, nearPlaneDistance,
farPlaneDistance, farPlaneDistance,
FontNormal); FontNormal);
endObjectAnnotations(); endObjectAnnotations();
disableSmoothLines();
} }
// reset the depth range // reset the depth range

View File

@ -48,6 +48,21 @@ struct Matrices
const Eigen::Matrix4f *modelview; const Eigen::Matrix4f *modelview;
}; };
struct LineStripEnd
{
LineStripEnd(Eigen::Vector3f point, float scale) : point(point), scale(scale) {};
Eigen::Vector3f point;
float scale;
};
struct LineEnds
{
LineEnds(Eigen::Vector3f point1, Eigen::Vector3f point2, float scale) : point1(point1), point2(point2), scale(scale) {};
Eigen::Vector3f point1;
Eigen::Vector3f point2;
float scale;
};
struct LightSource struct LightSource
{ {
Eigen::Vector3d position; Eigen::Vector3d position;
@ -73,7 +88,10 @@ enum class VOType
Rectangle = 2, Rectangle = 2,
Terminator = 3, Terminator = 3,
LargeStar = 4, LargeStar = 4,
Count = 5 AxisLetter = 5,
MarkerLine = 6,
Ecliptic = 7,
Count = 8,
}; };
enum class RenderMode enum class RenderMode
@ -257,6 +275,12 @@ class Renderer
int getWindowWidth() const; int getWindowWidth() const;
int getWindowHeight() const; int getWindowHeight() const;
float getScaleFactor() const;
float getPointWidth() const;
float getPointHeight() const;
float getLineWidthX() const;
float getLineWidthY() const;
// GL wrappers // GL wrappers
void getViewport(int* x, int* y, int* w, int* h) const; void getViewport(int* x, int* y, int* w, int* h) const;
void getViewport(std::array<int, 4>& viewport) const; void getViewport(std::array<int, 4>& viewport) const;
@ -279,6 +303,9 @@ class Renderer
void enableDepthTest() noexcept; void enableDepthTest() noexcept;
void disableDepthTest() noexcept; void disableDepthTest() noexcept;
void enableSmoothLines();
void disableSmoothLines();
void drawRectangle(const Rect& r, int fishEyeOverrideMode, const Eigen::Matrix4f& p, const Eigen::Matrix4f& m = Eigen::Matrix4f::Identity()); void drawRectangle(const Rect& r, int fishEyeOverrideMode, const Eigen::Matrix4f& p, const Eigen::Matrix4f& m = Eigen::Matrix4f::Identity());
void setRenderRegion(int x, int y, int width, int height, bool withScissor = true); void setRenderRegion(int x, int y, int width, int height, bool withScissor = true);
@ -718,9 +745,6 @@ class Renderer
void createShadowFBO(); void createShadowFBO();
void enableSmoothLines();
void disableSmoothLines();
#ifdef USE_HDR #ifdef USE_HDR
private: private:
int sceneTexWidth, sceneTexHeight; int sceneTexWidth, sceneTexHeight;

View File

@ -74,7 +74,7 @@ invariant gl_Position;
static const char *VPFunction = static const char *VPFunction =
"#ifdef FISHEYE\n" "#ifdef FISHEYE\n"
"void set_vp(vec4 in_Position) {\n" "vec4 calc_vp(vec4 in_Position) {\n"
" float PID2 = 1.570796326794896619231322;\n" " float PID2 = 1.570796326794896619231322;\n"
" vec4 inPos = ModelViewMatrix * in_Position;\n" " vec4 inPos = ModelViewMatrix * in_Position;\n"
" float l = length(inPos.xy);\n" " float l = length(inPos.xy);\n"
@ -83,17 +83,38 @@ static const char *VPFunction =
" float lensR = phi / PID2;\n" " float lensR = phi / PID2;\n"
" inPos.xy *= (lensR / l);\n" " inPos.xy *= (lensR / l);\n"
" }\n" " }\n"
" gl_Position = ProjectionMatrix * inPos;\n" " return ProjectionMatrix * inPos;\n"
"}\n" "}\n"
"#else\n" "#else\n"
"void set_vp(vec4 in_Position) {\n" "vec4 calc_vp(vec4 in_Position) {\n"
" gl_Position = MVPMatrix * in_Position;\n" " return MVPMatrix * in_Position;\n"
"}\n" "}\n"
"#endif\n"; "#endif\n"
"void set_vp(vec4 in_Position) {\n"
" gl_Position = calc_vp(in_Position);\n"
"}\n";
static const char* VertexPosition = static const char* NormalVertexPosition =
"set_vp(in_Position);\n"; "set_vp(in_Position);\n";
static const char* LineVertexPosition =
"vec4 thisPos = calc_vp(in_Position);\n"
"vec4 nextPos = calc_vp(in_PositionNext);\n"
"float w = thisPos.w;\n"
"thisPos /= w;\n"
"nextPos /= nextPos.w;\n"
"vec2 transform = normalize(nextPos.xy - thisPos.xy);\n"
"transform = vec2(transform.y * lineWidthX, -transform.x * lineWidthY) * in_ScaleFactor;\n"
"gl_Position = thisPos;\n"
"gl_Position.xy += transform;\n"
"gl_Position *= w;\n";
static string VertexPosition(const ShaderProperties& props)
{
return (props.texUsage & ShaderProperties::LineAsTriangles) ? LineVertexPosition : NormalVertexPosition;
}
static const char* FragmentHeader = ""; static const char* FragmentHeader = "";
static const char* CommonAttribs = R"glsl( static const char* CommonAttribs = R"glsl(
@ -1689,6 +1710,17 @@ StaticPointSize()
return source; return source;
} }
static string
LineDeclaration()
{
string source;
source += DeclareAttribute("in_PositionNext", Shader_Vector4);
source += DeclareAttribute("in_ScaleFactor", Shader_Float);
source += DeclareUniform("lineWidthX", Shader_Float);
source += DeclareUniform("lineWidthY", Shader_Float);
return source;
}
static string static string
CalculateShadow() CalculateShadow()
{ {
@ -1854,6 +1886,9 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
if (props.hasShadowMap()) if (props.hasShadowMap())
source += "uniform mat4 ShadowMatrix0;\n"; source += "uniform mat4 ShadowMatrix0;\n";
if (props.texUsage & ShaderProperties::LineAsTriangles)
source += LineDeclaration();
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled) if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
source += "#define FISHEYE\n"; source += "#define FISHEYE\n";
@ -2076,7 +2111,7 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
if (props.hasShadowMap()) if (props.hasShadowMap())
source += "shadowTexCoord0 = ShadowMatrix0 * vec4(in_Position.xyz, 1.0);\n"; source += "shadowTexCoord0 = ShadowMatrix0 * vec4(in_Position.xyz, 1.0);\n";
source += VertexPosition; source += VertexPosition(props);
source += "}\n"; source += "}\n";
DumpVSSource(source); DumpVSSource(source);
@ -2699,6 +2734,9 @@ ShaderManager::buildRingsVertexShader(const ShaderProperties& props)
if (props.texUsage & ShaderProperties::DiffuseTexture) if (props.texUsage & ShaderProperties::DiffuseTexture)
source += "varying vec2 diffTexCoord;\n"; source += "varying vec2 diffTexCoord;\n";
if (props.texUsage & ShaderProperties::LineAsTriangles)
source += LineDeclaration();
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled) if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
source += "#define FISHEYE\n"; source += "#define FISHEYE\n";
@ -2719,7 +2757,7 @@ ShaderManager::buildRingsVertexShader(const ShaderProperties& props)
} }
} }
source += VertexPosition; source += VertexPosition(props);
source += "}\n"; source += "}\n";
DumpVSSource(source); DumpVSSource(source);
@ -2858,6 +2896,9 @@ ShaderManager::buildAtmosphereVertexShader(const ShaderProperties& props)
source += "varying vec3 scatterEx;\n"; source += "varying vec3 scatterEx;\n";
source += "varying vec3 eyeDir_obj;\n"; source += "varying vec3 eyeDir_obj;\n";
if (props.texUsage & ShaderProperties::LineAsTriangles)
source += LineDeclaration();
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled) if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
source += "#define FISHEYE\n"; source += "#define FISHEYE\n";
@ -2872,7 +2913,7 @@ ShaderManager::buildAtmosphereVertexShader(const ShaderProperties& props)
source += AtmosphericEffects(props); source += AtmosphericEffects(props);
source += "eyeDir_obj = eyeDir;\n"; source += "eyeDir_obj = eyeDir;\n";
source += VertexPosition; source += VertexPosition(props);
source += "}\n"; source += "}\n";
DumpVSSource(source); DumpVSSource(source);
@ -2967,6 +3008,9 @@ ShaderManager::buildEmissiveVertexShader(const ShaderProperties& props)
source += DeclareVarying("v_Color", Shader_Vector4); source += DeclareVarying("v_Color", Shader_Vector4);
source += DeclareVarying("v_TexCoord0", Shader_Vector2); source += DeclareVarying("v_TexCoord0", Shader_Vector2);
if (props.texUsage & ShaderProperties::LineAsTriangles)
source += LineDeclaration();
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled) if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
source += "#define FISHEYE\n"; source += "#define FISHEYE\n";
@ -2998,7 +3042,7 @@ ShaderManager::buildEmissiveVertexShader(const ShaderProperties& props)
else if (props.texUsage & ShaderProperties::StaticPointSize) else if (props.texUsage & ShaderProperties::StaticPointSize)
source += StaticPointSize(); source += StaticPointSize();
source += VertexPosition; source += VertexPosition(props);
source += "}\n"; source += "}\n";
// End of main() // End of main()
@ -3095,6 +3139,9 @@ ShaderManager::buildParticleVertexShader(const ShaderProperties& props)
source << "varying vec3 position_obj;\n"; source << "varying vec3 position_obj;\n";
} }
if (props.texUsage & ShaderProperties::LineAsTriangles)
source << LineDeclaration();
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled) if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
source << "#define FISHEYE\n"; source << "#define FISHEYE\n";
@ -3132,7 +3179,7 @@ ShaderManager::buildParticleVertexShader(const ShaderProperties& props)
else if (props.texUsage & ShaderProperties::StaticPointSize) else if (props.texUsage & ShaderProperties::StaticPointSize)
source << StaticPointSize(); source << StaticPointSize();
source << VertexPosition; source << VertexPosition(props);
source << "}\n"; source << "}\n";
// End of main() // End of main()
@ -3283,6 +3330,17 @@ ShaderManager::buildProgram(const ShaderProperties& props)
CelestiaGLProgram::IntensityAttributeIndex, CelestiaGLProgram::IntensityAttributeIndex,
"in_Intensity"); "in_Intensity");
if (props.texUsage & ShaderProperties::LineAsTriangles)
{
glBindAttribLocation(prog->getID(),
CelestiaGLProgram::NextVCoordAttributeIndex,
"in_PositionNext");
glBindAttribLocation(prog->getID(),
CelestiaGLProgram::ScaleFactorAttributeIndex,
"in_ScaleFactor");
}
if (props.texUsage & ShaderProperties::NormalTexture) if (props.texUsage & ShaderProperties::NormalTexture)
{ {
glBindAttribLocation(prog->getID(), glBindAttribLocation(prog->getID(),
@ -3593,6 +3651,12 @@ CelestiaGLProgram::initParameters()
{ {
pointScale = floatParam("pointScale"); pointScale = floatParam("pointScale");
} }
if (props.texUsage & ShaderProperties::LineAsTriangles)
{
lineWidthX = floatParam("lineWidthX");
lineWidthY = floatParam("lineWidthY");
}
} }

View File

@ -67,6 +67,7 @@ class ShaderProperties
PointSprite = 0x4000, PointSprite = 0x4000,
SharedTextureCoords = 0x8000, SharedTextureCoords = 0x8000,
StaticPointSize = 0x10000, StaticPointSize = 0x10000,
LineAsTriangles = 0x20000,
}; };
enum enum
@ -194,6 +195,8 @@ class CelestiaGLProgram
PointSizeAttributeIndex = 7, PointSizeAttributeIndex = 7,
ColorAttributeIndex = 8, ColorAttributeIndex = 8,
IntensityAttributeIndex = 9, IntensityAttributeIndex = 9,
NextVCoordAttributeIndex = 10,
ScaleFactorAttributeIndex = 11,
}; };
public: public:
@ -260,6 +263,10 @@ class CelestiaGLProgram
// Scale factor for point sprites // Scale factor for point sprites
FloatShaderParameter pointScale; FloatShaderParameter pointScale;
// Used to draw line as triangles
FloatShaderParameter lineWidthX;
FloatShaderParameter lineWidthY;
// Color sent as a uniform // Color sent as a uniform
Vec4ShaderParameter color; Vec4ShaderParameter color;

View File

@ -392,7 +392,7 @@ SkyGrid::render(Renderer& renderer,
int windowHeight) int windowHeight)
{ {
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors; shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = renderer.getShaderManager().getShader(shadprop); auto *prog = renderer.getShaderManager().getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
@ -556,14 +556,23 @@ SkyGrid::render(Renderer& renderer,
vecgl::rotate((xrot90 * m_orientation.conjugate() * xrot90.conjugate()).cast<float>()) * vecgl::rotate((xrot90 * m_orientation.conjugate() * xrot90.conjugate()).cast<float>()) *
vecgl::scale(1000.0f); vecgl::scale(1000.0f);
prog->setMVPMatrices(renderer.getProjectionMatrix(), m); prog->setMVPMatrices(renderer.getProjectionMatrix(), m);
prog->lineWidthX = renderer.getLineWidthX();
prog->lineWidthY = renderer.getLineWidthY();
double arcStep = (maxTheta - minTheta) / (double) ARC_SUBDIVISIONS; double arcStep = (maxTheta - minTheta) / (double) ARC_SUBDIVISIONS;
double theta0 = minTheta; double theta0 = minTheta;
auto buffer = new Vector3f[ARC_SUBDIVISIONS+1]; vector<LineStripEnd> buffer;
buffer.reserve(2 * (ARC_SUBDIVISIONS + 2));
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex, glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, 0, buffer); 3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &buffer[0].point);
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &buffer[2].point);
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(LineStripEnd), &buffer[0].scale);
for (int dec = startDec; dec <= endDec; dec += decIncrement) for (int dec = startDec; dec <= endDec; dec += decIncrement)
{ {
@ -571,15 +580,17 @@ SkyGrid::render(Renderer& renderer,
double cosPhi = cos(phi); double cosPhi = cos(phi);
double sinPhi = sin(phi); double sinPhi = sin(phi);
for (int j = 0; j <= ARC_SUBDIVISIONS; j++) for (int j = 0; j <= ARC_SUBDIVISIONS + 1; j++)
{ {
double theta = theta0 + j * arcStep; double theta = theta0 + j * arcStep;
auto x = (float) (cosPhi * std::cos(theta)); auto x = (float) (cosPhi * std::cos(theta));
auto y = (float) (cosPhi * std::sin(theta)); auto y = (float) (cosPhi * std::sin(theta));
auto z = (float) sinPhi; auto z = (float) sinPhi;
buffer[j] = {x, z, -y}; // convert to Celestia coords Vector3f position = {x, z, -y}; // convert to Celestia coords
buffer[2 * j] = {position, -0.5f};
buffer[2 * j + 1] = {position, 0.5f};
} }
glDrawArrays(GL_LINE_STRIP, 0, ARC_SUBDIVISIONS+1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 2 * (ARC_SUBDIVISIONS + 1));
// Place labels at the intersections of the view frustum planes // Place labels at the intersections of the view frustum planes
// and the parallels. // and the parallels.
@ -646,15 +657,17 @@ SkyGrid::render(Renderer& renderer,
double cosTheta = cos(theta); double cosTheta = cos(theta);
double sinTheta = sin(theta); double sinTheta = sin(theta);
for (int j = 0; j <= ARC_SUBDIVISIONS; j++) for (int j = 0; j <= ARC_SUBDIVISIONS + 1; j++)
{ {
double phi = phi0 + j * arcStep; double phi = phi0 + j * arcStep;
auto x = (float) (cos(phi) * cosTheta); auto x = (float) (cos(phi) * cosTheta);
auto y = (float) (cos(phi) * sinTheta); auto y = (float) (cos(phi) * sinTheta);
auto z = (float) sin(phi); auto z = (float) sin(phi);
buffer[j] = {x, z, -y}; // convert to Celestia coords Vector3f position = {x, z, -y}; // convert to Celestia coords
buffer[2 * j] = {position, -0.5f};
buffer[2 * j + 1] = {position, 0.5f};
} }
glDrawArrays(GL_LINE_STRIP, 0, ARC_SUBDIVISIONS+1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 2 * (ARC_SUBDIVISIONS + 1));
// Place labels at the intersections of the view frustum planes // Place labels at the intersections of the view frustum planes
// and the meridians. // and the meridians.
@ -704,16 +717,47 @@ SkyGrid::render(Renderer& renderer,
} }
// Draw crosses indicating the north and south poles // Draw crosses indicating the north and south poles
buffer[0] = {-polarCrossSize, 1.0f, 0.0f}; array<float, 112> lineAsTriangleVertices = {
buffer[1] = { polarCrossSize, 1.0f, 0.0f}; -polarCrossSize, 1.0f, 0.0f, polarCrossSize, 1.0f, 0.0f, -0.5,
buffer[2] = {0.0f, 1.0f, -polarCrossSize}; -polarCrossSize, 1.0f, 0.0f, polarCrossSize, 1.0f, 0.0f, 0.5,
buffer[3] = {0.0f, 1.0f, polarCrossSize};
buffer[4] = {-polarCrossSize, -1.0f, 0.0f}; polarCrossSize, 1.0f, 0.0f, -polarCrossSize, 1.0f, 0.0f, -0.5,
buffer[5] = { polarCrossSize, -1.0f, 0.0f}; polarCrossSize, 1.0f, 0.0f, -polarCrossSize, 1.0f, 0.0f, 0.5,
buffer[6] = {0.0f, -1.0f, -polarCrossSize};
buffer[7] = {0.0f, -1.0f, polarCrossSize}; 0.0f, 1.0f, -polarCrossSize, 0.0f, 1.0f, polarCrossSize, -0.5,
glDrawArrays(GL_LINES, 0, 8); 0.0f, 1.0f, -polarCrossSize, 0.0f, 1.0f, polarCrossSize, 0.5,
0.0f, 1.0f, polarCrossSize, 0.0f, 1.0f, -polarCrossSize, -0.5,
0.0f, 1.0f, polarCrossSize, 0.0f, 1.0f, -polarCrossSize, 0.5,
-polarCrossSize, -1.0f, 0.0f, polarCrossSize, -1.0f, 0.0f, -0.5,
-polarCrossSize, -1.0f, 0.0f, polarCrossSize, -1.0f, 0.0f, 0.5,
polarCrossSize, -1.0f, 0.0f, -polarCrossSize, -1.0f, 0.0f, -0.5,
polarCrossSize, -1.0f, 0.0f, -polarCrossSize, -1.0f, 0.0f, 0.5,
0.0f, -1.0f, -polarCrossSize, 0.0f, -1.0f, polarCrossSize, -0.5,
0.0f, -1.0f, -polarCrossSize, 0.0f, -1.0f, polarCrossSize, 0.5,
0.0f, -1.0f, polarCrossSize, 0.0f, -1.0f, -polarCrossSize, -0.5,
0.0f, -1.0f, polarCrossSize, 0.0f, -1.0f, -polarCrossSize, 0.5,
};
constexpr array<short, 24> lineAsTriangleIndcies = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12
};
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, lineAsTriangleVertices.data());
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, lineAsTriangleVertices.data() + 3);
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, sizeof(float) * 7, lineAsTriangleVertices.data() + 6);
glDrawElements(GL_TRIANGLES, lineAsTriangleIndcies.size(), GL_UNSIGNED_SHORT, lineAsTriangleIndcies.data());
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex); glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
delete[] buffer; glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
} }

View File

@ -84,7 +84,7 @@ constexpr const unsigned maxSections = 360;
static void static void
renderTerminator(Renderer* renderer, renderTerminator(Renderer* renderer,
const vector<Vector3f>& pos, const vector<LineStripEnd>& pos,
const Color& color, const Color& color,
const Matrices& mvp) const Matrices& mvp)
{ {
@ -94,8 +94,9 @@ renderTerminator(Renderer* renderer,
* Because of this we make calculations on a CPU and stream results to GPU. * Because of this we make calculations on a CPU and stream results to GPU.
*/ */
float lineWidth = renderer->getScreenDpi() / 96.0f;
ShaderProperties shadprop; ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors; shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel; shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = renderer->getShaderManager().getShader(shadprop); auto *prog = renderer->getShaderManager().getShader(shadprop);
if (prog == nullptr) if (prog == nullptr)
@ -106,18 +107,26 @@ renderTerminator(Renderer* renderer,
vo.bindWritable(); vo.bindWritable();
if (!vo.initialized()) if (!vo.initialized())
{ {
vo.setBufferSize(maxSections * sizeof(Vector3f)); vo.setBufferSize((maxSections + 2) * 2 * sizeof(LineStripEnd));
vo.allocate(); vo.allocate();
vo.setVertices(3, GL_FLOAT); vo.setVertices(3, GL_FLOAT, false, sizeof(LineStripEnd), 0);
vo.setVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex,
3, GL_FLOAT, false, sizeof(LineStripEnd)
, 2 * sizeof(LineStripEnd) + offsetof(LineStripEnd, point));
vo.setVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, false, sizeof(LineStripEnd)
, offsetof(LineStripEnd, scale));
} }
vo.setBufferData(pos.data(), 0, pos.size() * sizeof(Vector3f)); vo.setBufferData(pos.data(), 0, pos.size() * sizeof(LineStripEnd));
prog->use(); prog->use();
prog->lineWidthX = renderer->getLineWidthX();
prog->lineWidthY = renderer->getLineWidthY();
prog->setMVPMatrices(*mvp.projection, *mvp.modelview); prog->setMVPMatrices(*mvp.projection, *mvp.modelview);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color); glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
vo.draw(GL_LINE_LOOP, pos.size()); vo.draw(GL_TRIANGLE_STRIP, pos.size() - 2);
vo.unbind(); vo.unbind();
} }
@ -198,17 +207,19 @@ VisibleRegion::render(Renderer* renderer,
Vector3d e_ = e.cwiseProduct(recipSemiAxes); Vector3d e_ = e.cwiseProduct(recipSemiAxes);
double ee = e_.squaredNorm(); double ee = e_.squaredNorm();
vector<Vector3f> pos; vector<LineStripEnd> pos;
pos.reserve(nSections); pos.reserve((nSections + 2) * 2);
for (unsigned i = 0; i < nSections; i++) for (unsigned i = 0; i <= nSections + 1; i++)
{ {
double theta = (double) i / (double) (nSections) * 2.0 * PI; double theta = (double) i / (double) (nSections) * 2.0 * PI;
Vector3d w = cos(theta) * uAxis + sin(theta) * vAxis; Vector3d w = cos(theta) * uAxis + sin(theta) * vAxis;
Vector3d toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee); Vector3d toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee);
toCenter *= maxSemiAxis * scale; toCenter *= maxSemiAxis * scale;
pos.push_back(toCenter.cast<float>()); Vector3f thisPoint = toCenter.cast<float>();
pos.emplace_back(thisPoint, -0.5);
pos.emplace_back(thisPoint, 0.5);
} }
Affine3f transform = Translation3f(position) * qf.conjugate(); Affine3f transform = Translation3f(position) * qf.conjugate();