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

View File

@ -37,7 +37,7 @@ constexpr const float headRadius = 0.025f;
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 size_t count = 0; // number of vertices in the arrow
@ -122,31 +122,9 @@ static size_t initArrowAndLetters(VertexObject &vo)
#endif
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;
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;
vo.allocate(size);
@ -167,16 +145,88 @@ static size_t initArrowAndLetters(VertexObject &vo)
vo.setBufferData(head.data(), offset, s);
offset += s;
vo.setBufferData(lettersVtx, offset, sizeof(lettersVtx));
vo.setVertices(3, GL_FLOAT, GL_FALSE, 0, 0);
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)
{
auto count = initArrowAndLetters(vo);
auto count = initArrow(vo);
vo.draw(GL_TRIANGLES, count);
vo.unbind();
}
@ -184,8 +234,8 @@ static void RenderArrow(VertexObject& vo)
// Draw letter x in xz plane
static void RenderX(VertexObject& vo)
{
auto offset = initArrowAndLetters(vo);
vo.draw(GL_LINES, 4, offset);
initLetters(vo);
vo.draw(GL_TRIANGLES, 12);
vo.unbind();
}
@ -193,8 +243,8 @@ static void RenderX(VertexObject& vo)
// Draw letter y in xz plane
static void RenderY(VertexObject& vo)
{
auto offset = initArrowAndLetters(vo);
vo.draw(GL_LINES, 6, offset+4);
initLetters(vo);
vo.draw(GL_TRIANGLES, 18, 12);
vo.unbind();
}
@ -202,8 +252,8 @@ static void RenderY(VertexObject& vo)
// Draw letter z in xz plane
static void RenderZ(VertexObject& vo)
{
auto offset = initArrowAndLetters(vo);
vo.draw(GL_LINE_STRIP, 4, offset+10);
initLetters(vo);
vo.draw(GL_TRIANGLES, 18, 30);
vo.unbind();
}
@ -387,35 +437,49 @@ AxesReferenceMark::render(Renderer* renderer,
return;
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);
Matrix4f labelTransformMatrix = labelTransform.matrix();
Matrix4f tModelView;
// 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);
prog->setMVPMatrices(projection, tModelView);
RenderArrow(vo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderX(vo);
prog->setMVPMatrices(projection, xModelView);
RenderArrow(arrowVo);
// 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);
prog->setMVPMatrices(projection, tModelView);
RenderArrow(vo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderY(vo);
prog->setMVPMatrices(projection, yModelView);
RenderArrow(arrowVo);
// 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);
prog->setMVPMatrices(projection, tModelView);
RenderArrow(vo);
prog->setMVPMatrices(projection, tModelView * labelTransformMatrix);
RenderZ(vo);
prog->setMVPMatrices(projection, zModelView);
RenderArrow(arrowVo);
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->setBlendingFactors(GL_SRC_ALPHA, GL_ONE);

View File

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

View File

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

View File

@ -24,38 +24,7 @@ using namespace celmath;
using namespace celestia;
using namespace Eigen;
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 SquareOffset = 0;
constexpr const int SquareCount = 4;
static GLfloat Square[SquareCount * 2] =
{
@ -145,7 +114,7 @@ static GLfloat SelPointer[SelPointerCount * 2] =
constexpr const int CrosshairOffset = SelPointerOffset + SelPointerCount;
constexpr const int CrosshairCount = 3;
static GLfloat Crosshair[CrosshairCount * 2 ] =
static GLfloat Crosshair[CrosshairCount * 2] =
{
0.0f, 0.0f,
1.0f, -1.0f,
@ -155,49 +124,117 @@ static GLfloat Crosshair[CrosshairCount * 2 ] =
constexpr const int StaticVtxCount = CrosshairOffset + CrosshairCount;
constexpr const int SmallCircleOffset = StaticVtxCount;
static int SmallCircleCount = 0;
static int LargeCircleOffset = 0;
static int LargeCircleCount = 0;
static int EclipticOffset = 0;
constexpr const int EclipticCount = 200;
constexpr const int SmallCircleCount = 10;
constexpr const int LargeCircleOffset = SmallCircleOffset + SmallCircleCount;
constexpr const int LargeCircleCount = 60;
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)
{
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;
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);
}
};
vo.allocate((LargeCircleOffset + LargeCircleCount) * sizeof(GLfloat) * 2);
SmallCircleCount = small.size() / 2;
LargeCircleCount = large.size() / 2;
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);
int offset = 0;
#define VOSTREAM(a) bufferVertices(vo, a, a##Count, offset)
VOSTREAM(Square);
VOSTREAM(Triangle);
VOSTREAM(RightArrow);
@ -206,57 +243,162 @@ static void initVO(VertexObject& vo)
VOSTREAM(DownArrow);
VOSTREAM(SelPointer);
VOSTREAM(Crosshair);
VOSTREAM(SmallCircle);
VOSTREAM(LargeCircle);
#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);
}
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,
float size,
const Color &color,
const Matrices &m)
{
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;
shadprop.texUsage = ShaderProperties::VertexColors;
if (!solid)
shadprop.texUsage |= ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
shadprop.fishEyeOverride = ShaderProperties::FisheyeOverrideModeDisabled;
auto* prog = shaderManager->getShader(shadprop);
if (prog == nullptr)
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();
if (!markerVO.initialized())
initVO(markerVO);
solid ? initVO(markerVO) : initLineVO(markerVO);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
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)));
if (!solid)
{
prog->lineWidthX = getLineWidthX();
prog->lineWidthY = getLineWidthY();
}
switch (symbol)
{
case MarkerRepresentation::Diamond:
markerVO.draw(GL_LINE_LOOP, DiamondCount, DiamondOffset);
markerVO.draw(GL_TRIANGLES, DiamondLineCount, DiamondLineOffset);
break;
case MarkerRepresentation::Plus:
markerVO.draw(GL_LINES, PlusCount, PlusOffset);
markerVO.draw(GL_TRIANGLES, PlusLineCount, PlusLineOffset);
break;
case MarkerRepresentation::X:
markerVO.draw(GL_LINES, XCount, XOffset);
markerVO.draw(GL_TRIANGLES, XLineCount, XLineOffset);
break;
case MarkerRepresentation::Square:
markerVO.draw(GL_LINE_LOOP, SquareCount, SquareOffset);
markerVO.draw(GL_TRIANGLES, SquareLineCount, SquareLineOffset);
break;
case MarkerRepresentation::FilledSquare:
@ -264,7 +406,7 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
break;
case MarkerRepresentation::Triangle:
markerVO.draw(GL_LINE_LOOP, TriangleCount, TriangleOffset);
markerVO.draw(GL_TRIANGLES, TriangleLineCount, TriangleLineOffset);
break;
case MarkerRepresentation::RightArrow:
@ -284,14 +426,14 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
break;
case MarkerRepresentation::Circle:
if (s <= 20)
markerVO.draw(GL_LINE_LOOP, SmallCircleCount, SmallCircleOffset);
if (size <= 40.0f) // TODO: this should be configurable
markerVO.draw(GL_TRIANGLES, SmallCircleLineCount, SmallCircleLineOffset);
else
markerVO.draw(GL_LINE_LOOP, LargeCircleCount, LargeCircleOffset);
markerVO.draw(GL_TRIANGLES, LargeCircleLineCount, LargeCircleLineOffset);
break;
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);
else
markerVO.draw(GL_TRIANGLE_FAN, LargeCircleCount, LargeCircleOffset);
@ -365,7 +507,7 @@ void Renderer::renderSelectionPointer(const Observer& observer,
const Vector3f &center = cameraMatrix.col(2);
prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix() * vecgl::translate(Vector3f(-center)));
prog->vec4Param("color") = Color(SelectionCursorColor, 0.6f).toVector4();
prog->floatParam("pixelSize") = pixelSize;
prog->floatParam("pixelSize") = pixelSize * getScaleFactor();
prog->floatParam("s") = s;
prog->floatParam("c") = c;
prog->floatParam("x0") = x0;
@ -390,22 +532,27 @@ void Renderer::renderEclipticLine()
if ((renderFlags & ShowEcliptic) == 0)
return;
assert(shaderManager != nullptr);
auto* prog = shaderManager->getShader("ecliptic");
ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
auto* prog = shaderManager->getShader(shadprop);
if (prog == nullptr)
return;
auto &markerVO = getVertexObject(VOType::Marker, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
markerVO.bind();
if (!markerVO.initialized())
initVO(markerVO);
auto &eclipticVO = getVertexObject(VOType::Ecliptic, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
eclipticVO.bind();
if (!eclipticVO.initialized())
initEclipticVO(eclipticVO);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, EclipticColor);
prog->use();
prog->setMVPMatrices(getProjectionMatrix(), getModelViewMatrix());
prog->vec4Param("color") = EclipticColor.toVector4();
markerVO.draw(GL_LINE_LOOP, EclipticCount, EclipticOffset);
prog->lineWidthX = getLineWidthX();
prog->lineWidthY = getLineWidthY();
eclipticVO.draw(GL_TRIANGLES, EclipticLineCount, 0);
markerVO.unbind();
eclipticVO.unbind();
}
void Renderer::renderCrosshair(float selectionSizeInPixels,
@ -439,8 +586,9 @@ void Renderer::renderCrosshair(float selectionSizeInPixels,
prog->setMVPMatrices(*m.projection, *m.modelview);
prog->vec4Param("color") = color.toVector4();
prog->floatParam("radius") = cursorRadius;
prog->floatParam("width") = minCursorWidth * cursorGrow;
prog->floatParam("h") = 2.0f * cursorGrow;
float scaleFactor = getScaleFactor();
prog->floatParam("width") = minCursorWidth * cursorGrow * scaleFactor;
prog->floatParam("h") = 2.0f * cursorGrow * scaleFactor;
const unsigned int markCount = 4;
for (unsigned int i = 0; i < markCount; i++)

View File

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

View File

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

View File

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

View File

@ -701,6 +701,31 @@ void Renderer::setScreenDpi(int _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)
{
faintestAutoMag45deg = _faintestAutoMag45deg;
@ -1033,7 +1058,7 @@ Renderer::enableSmoothLines()
#ifndef GL_ES
glEnable(GL_LINE_SMOOTH);
#endif
glLineWidth(1.5f * screenDpi / 96.0f);
glLineWidth(1.5f * getScaleFactor());
}
void
@ -1047,7 +1072,7 @@ Renderer::disableSmoothLines()
#ifndef GL_ES
glDisable(GL_LINE_SMOOTH);
#endif
glLineWidth(1.0f * screenDpi / 96.0f);
glLineWidth(1.0f * getScaleFactor());
}
Vector4f renderOrbitColor(const Body *body, bool selected, float opacity)
@ -1117,7 +1142,7 @@ void Renderer::renderOrbit(const OrbitPathListEntry& orbitPath,
const Matrices& m)
{
ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors;
shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = shaderManager->getShader(shadprop);
if (prog == nullptr)
@ -1320,6 +1345,8 @@ void Renderer::renderOrbit(const OrbitPathListEntry& orbitPath,
prog->use();
prog->setMVPMatrices(*m.projection);
prog->lineWidthX = getPointWidth();
prog->lineWidthY = getPointHeight();
if (orbit->isPeriodic())
{
double period = orbit->getPeriod();
@ -1722,9 +1749,7 @@ void Renderer::draw(const Observer& observer,
disableDepthMask();
// Render sky grids first--these will always be in the background
enableSmoothLines();
renderSkyGrids(observer);
disableSmoothLines();
enableBlending();
// Render deep sky objects
@ -3869,9 +3894,7 @@ void Renderer::renderAsterisms(const Universe& universe, float dist, const Matri
(MaxAsterismLinesDist - MaxAsterismLinesConstDist) + 1);
}
enableSmoothLines();
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);
}
enableSmoothLines();
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);
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);
#ifdef OCTREE_DEBUG
@ -4713,8 +4730,6 @@ void Renderer::renderDeepSkyObjects(const Universe& universe,
#endif
// clog << "DSOs processed: " << dsoRenderer.dsosProcessed << endl;
disableSmoothLines();
}
@ -4946,9 +4961,6 @@ void Renderer::renderAnnotations(const vector<Annotation>& annotations,
if (font[fs] == nullptr)
return;
// Enable line smoothing for rendering symbols
enableSmoothLines();
#ifdef USE_HDR
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
#endif
@ -5010,7 +5022,6 @@ void Renderer::renderAnnotations(const vector<Annotation>& annotations,
#endif
font[fs]->unbind();
disableSmoothLines();
}
@ -5444,10 +5455,14 @@ void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen
ShaderProperties shadprop;
shadprop.lightModel = ShaderProperties::UnlitModel;
bool solid = r.type != Rect::Type::BorderOnly;
if (r.nColors > 0)
shadprop.texUsage |= ShaderProperties::VertexColors;
if (r.tex != nullptr)
shadprop.texUsage |= ShaderProperties::DiffuseTexture;
if (!solid)
shadprop.texUsage |= ShaderProperties::LineAsTriangles;
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};
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);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
2, GL_FLOAT, GL_FALSE, 0, vertices.data());
if (solid)
{
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)
{
glEnableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
@ -5482,22 +5542,22 @@ void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen
prog->use();
prog->setMVPMatrices(p, m);
if (r.type != Rect::Type::BorderOnly)
if (solid)
{
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
else
{
if (r.lw != 1.0f)
glLineWidth(r.lw * screenDpi / 96.0f);
glDrawArrays(GL_LINE_LOOP, 0, 4);
if (r.lw != 1.0f)
glLineWidth(1.0f * screenDpi / 96.0f);
prog->lineWidthX = getLineWidthX() * r.lw;
prog->lineWidthY = getLineWidthY() * r.lw;
glDrawElements(GL_TRIANGLES, lineAsTriangleIndcies.size(), GL_UNSIGNED_SHORT, lineAsTriangleIndcies.data());
}
glDisableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
}
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
GLint pointSizeRange[2];
GLfloat lineWidthRange[2];
#ifdef GL_ES
glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
#else
glGetIntegerv(GL_SMOOTH_POINT_SIZE_RANGE, pointSizeRange);
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, lineWidthRange);
#endif
info["PointSizeMin"] = to_string(pointSizeRange[0]);
info["PointSizeMax"] = to_string(pointSizeRange[1]);
info["LineWidthMin"] = to_string(lineWidthRange[0]);
info["LineWidthMax"] = to_string(lineWidthRange[1]);
#ifndef GL_ES
GLfloat pointSizeGran = 0;
@ -6142,8 +6207,6 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
#else
setBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#endif
enableSmoothLines();
// Scan through the list of orbits and render any that overlap this interval
for (const auto& orbit : orbitPathList)
{
@ -6163,8 +6226,6 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
m);
}
}
disableSmoothLines();
}
// Render transparent objects in the second pass
@ -6178,13 +6239,11 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
}
// Render annotations in this interval
enableSmoothLines();
annotation = renderSortedAnnotations(annotation,
nearPlaneDistance,
farPlaneDistance,
FontNormal);
endObjectAnnotations();
disableSmoothLines();
}
// reset the depth range

View File

@ -48,6 +48,21 @@ struct Matrices
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
{
Eigen::Vector3d position;
@ -73,7 +88,10 @@ enum class VOType
Rectangle = 2,
Terminator = 3,
LargeStar = 4,
Count = 5
AxisLetter = 5,
MarkerLine = 6,
Ecliptic = 7,
Count = 8,
};
enum class RenderMode
@ -257,6 +275,12 @@ class Renderer
int getWindowWidth() const;
int getWindowHeight() const;
float getScaleFactor() const;
float getPointWidth() const;
float getPointHeight() const;
float getLineWidthX() const;
float getLineWidthY() const;
// GL wrappers
void getViewport(int* x, int* y, int* w, int* h) const;
void getViewport(std::array<int, 4>& viewport) const;
@ -279,6 +303,9 @@ class Renderer
void enableDepthTest() 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 setRenderRegion(int x, int y, int width, int height, bool withScissor = true);
@ -718,9 +745,6 @@ class Renderer
void createShadowFBO();
void enableSmoothLines();
void disableSmoothLines();
#ifdef USE_HDR
private:
int sceneTexWidth, sceneTexHeight;

View File

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

View File

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

View File

@ -392,7 +392,7 @@ SkyGrid::render(Renderer& renderer,
int windowHeight)
{
ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors;
shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = renderer.getShaderManager().getShader(shadprop);
if (prog == nullptr)
@ -556,14 +556,23 @@ SkyGrid::render(Renderer& renderer,
vecgl::rotate((xrot90 * m_orientation.conjugate() * xrot90.conjugate()).cast<float>()) *
vecgl::scale(1000.0f);
prog->setMVPMatrices(renderer.getProjectionMatrix(), m);
prog->lineWidthX = renderer.getLineWidthX();
prog->lineWidthY = renderer.getLineWidthY();
double arcStep = (maxTheta - minTheta) / (double) ARC_SUBDIVISIONS;
double theta0 = minTheta;
auto buffer = new Vector3f[ARC_SUBDIVISIONS+1];
vector<LineStripEnd> buffer;
buffer.reserve(2 * (ARC_SUBDIVISIONS + 2));
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
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)
{
@ -571,15 +580,17 @@ SkyGrid::render(Renderer& renderer,
double cosPhi = cos(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;
auto x = (float) (cosPhi * std::cos(theta));
auto y = (float) (cosPhi * std::sin(theta));
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
// and the parallels.
@ -646,15 +657,17 @@ SkyGrid::render(Renderer& renderer,
double cosTheta = cos(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;
auto x = (float) (cos(phi) * cosTheta);
auto y = (float) (cos(phi) * sinTheta);
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
// and the meridians.
@ -704,16 +717,47 @@ SkyGrid::render(Renderer& renderer,
}
// Draw crosses indicating the north and south poles
buffer[0] = {-polarCrossSize, 1.0f, 0.0f};
buffer[1] = { polarCrossSize, 1.0f, 0.0f};
buffer[2] = {0.0f, 1.0f, -polarCrossSize};
buffer[3] = {0.0f, 1.0f, polarCrossSize};
buffer[4] = {-polarCrossSize, -1.0f, 0.0f};
buffer[5] = { polarCrossSize, -1.0f, 0.0f};
buffer[6] = {0.0f, -1.0f, -polarCrossSize};
buffer[7] = {0.0f, -1.0f, polarCrossSize};
glDrawArrays(GL_LINES, 0, 8);
array<float, 112> lineAsTriangleVertices = {
-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,
-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);
delete[] buffer;
glDisableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
}

View File

@ -84,7 +84,7 @@ constexpr const unsigned maxSections = 360;
static void
renderTerminator(Renderer* renderer,
const vector<Vector3f>& pos,
const vector<LineStripEnd>& pos,
const Color& color,
const Matrices& mvp)
{
@ -94,8 +94,9 @@ renderTerminator(Renderer* renderer,
* Because of this we make calculations on a CPU and stream results to GPU.
*/
float lineWidth = renderer->getScreenDpi() / 96.0f;
ShaderProperties shadprop;
shadprop.texUsage = ShaderProperties::VertexColors;
shadprop.texUsage = ShaderProperties::VertexColors | ShaderProperties::LineAsTriangles;
shadprop.lightModel = ShaderProperties::UnlitModel;
auto *prog = renderer->getShaderManager().getShader(shadprop);
if (prog == nullptr)
@ -106,18 +107,26 @@ renderTerminator(Renderer* renderer,
vo.bindWritable();
if (!vo.initialized())
{
vo.setBufferSize(maxSections * sizeof(Vector3f));
vo.setBufferSize((maxSections + 2) * 2 * sizeof(LineStripEnd));
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->lineWidthX = renderer->getLineWidthX();
prog->lineWidthY = renderer->getLineWidthY();
prog->setMVPMatrices(*mvp.projection, *mvp.modelview);
glVertexAttrib(CelestiaGLProgram::ColorAttributeIndex, color);
vo.draw(GL_LINE_LOOP, pos.size());
vo.draw(GL_TRIANGLE_STRIP, pos.size() - 2);
vo.unbind();
}
@ -198,17 +207,19 @@ VisibleRegion::render(Renderer* renderer,
Vector3d e_ = e.cwiseProduct(recipSemiAxes);
double ee = e_.squaredNorm();
vector<Vector3f> pos;
pos.reserve(nSections);
vector<LineStripEnd> pos;
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;
Vector3d w = cos(theta) * uAxis + sin(theta) * vAxis;
Vector3d toCenter = ellipsoidTangent(recipSemiAxes, w, e, e_, ee);
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();