Support fisheye projection, dumb version
parent
62b5f58351
commit
b465017de8
|
@ -11,5 +11,5 @@ varying float shade;
|
|||
void main(void)
|
||||
{
|
||||
shade = abs(dot(viewDir.xyz, in_Normal.xyz) * brightness * fadeFactor);
|
||||
gl_Position = MVPMatrix * in_Position;
|
||||
set_vp(in_Position);
|
||||
}
|
||||
|
|
|
@ -2,5 +2,5 @@ attribute vec4 in_Position;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = MVPMatrix * in_Position;
|
||||
set_vp(in_Position);
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ attribute vec2 in_Position;
|
|||
void main(void)
|
||||
{
|
||||
vec4 p = vec4(in_Position.x, 0.0, in_Position.y, 1.0);
|
||||
gl_Position = MVPMatrix * p;
|
||||
set_vp(p);
|
||||
}
|
||||
|
|
|
@ -20,5 +20,5 @@ void main(void)
|
|||
float a = in_TexCoord0.w / 65535.0; // [0, 65535] -> [0, 1]
|
||||
color = vec4(texture2D(colorTex, vec2(t, 0.0)).rgb, a);
|
||||
texCoord = in_TexCoord0.st;
|
||||
gl_Position = MVPMatrix * in_Position;
|
||||
set_vp(in_Position);
|
||||
}
|
||||
|
|
|
@ -52,5 +52,5 @@ void main(void)
|
|||
gl_PointSize = s * min(obsDistanceToStarRatio, 1.0);
|
||||
|
||||
color = vec4(in_Color.rgb, min(1.0, br * (1.0 - pixelWeight * relStarDensity())));
|
||||
gl_Position = MVPMatrix * vec4(p, 1.0);
|
||||
set_vp(vec4(p, 1.0));
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
attribute vec3 in_Position;
|
||||
attribute vec2 in_TexCoord0;
|
||||
|
||||
uniform float pointWidth;
|
||||
uniform float pointHeight;
|
||||
uniform vec3 center;
|
||||
|
||||
varying vec2 texCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
texCoord = in_TexCoord0.st;
|
||||
gl_Position = MVPMatrix * vec4(in_Position, 1.0);
|
||||
set_vp(vec4(center, 1.0));
|
||||
vec2 transformed = vec2((texCoord.x - 0.5) * pointWidth, (texCoord.y - 0.5) * pointHeight);
|
||||
gl_Position.xy += transformed * gl_Position.w;
|
||||
}
|
||||
|
|
|
@ -10,5 +10,5 @@ void main(void)
|
|||
float x = in_Position.x * pixelSize;
|
||||
float y = in_Position.y * pixelSize;
|
||||
vec3 pos = (x * c - y * s + x0) * u + (x * s + y * c + y0) * v;
|
||||
gl_Position = MVPMatrix * vec4(pos, 1.0);
|
||||
set_vp(vec4(pos, 1.0));
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ void main(void)
|
|||
{
|
||||
gl_PointSize = in_PointSize;
|
||||
color = in_Color;
|
||||
gl_Position = MVPMatrix * vec4(in_Position, 1.0);
|
||||
set_vp(vec4(in_Position, 1.0));
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ varying vec2 texCoord;
|
|||
void main(void)
|
||||
{
|
||||
vec3 p = viewMat * in_Position.xyz * tidalSize;
|
||||
gl_Position = MVPMatrix * vec4(p, 1.0);
|
||||
|
||||
texCoord = in_TexCoord0.st;
|
||||
set_vp(vec4(p, 1.0));
|
||||
}
|
||||
|
|
|
@ -104,7 +104,10 @@ void DSORenderer::process(DeepSkyObject* const &dso,
|
|||
}
|
||||
|
||||
float t = (float)wWidth / (float)wHeight;
|
||||
pr = Perspective(fov, t, nearZ, farZ);
|
||||
if (renderer->getProjectionMode() == Renderer::ProjectionMode::FisheyeMode)
|
||||
pr = Ortho(-t, t, -1.0f, 1.0f, nearZ, farZ);
|
||||
else
|
||||
pr = Perspective(fov, t, nearZ, farZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -225,6 +225,7 @@ void Renderer::renderMarker(MarkerRepresentation::Symbol symbol,
|
|||
ShaderProperties shadprop;
|
||||
shadprop.texUsage = ShaderProperties::VertexColors;
|
||||
shadprop.lightModel = ShaderProperties::UnlitModel;
|
||||
shadprop.fishEyeOverride = ShaderProperties::FisheyeOverrideModeDisabled;
|
||||
auto* prog = shaderManager->getShader(shadprop);
|
||||
if (prog == nullptr)
|
||||
return;
|
||||
|
|
|
@ -1352,6 +1352,21 @@ Vector3f Observer::getPickRay(float x, float y) const
|
|||
return pickDirection.normalized();
|
||||
}
|
||||
|
||||
Vector3f Observer::getPickRayFisheye(float x, float y) const
|
||||
{
|
||||
float r = hypot(x, y);
|
||||
float phi = float(PI) * r;
|
||||
float sin_phi = sin(phi);
|
||||
float theta = atan2(y, x);
|
||||
float newX = sin_phi * cos(theta);
|
||||
float newY = sin_phi * sin(theta);
|
||||
float newZ = cos(phi);
|
||||
Vector3f pickDirection = Vector3f(newX, newY, -newZ);
|
||||
pickDirection.normalize();
|
||||
|
||||
return pickDirection;
|
||||
}
|
||||
|
||||
|
||||
// Internal method to update the position and orientation of the observer in
|
||||
// universal coordinates.
|
||||
|
|
|
@ -135,6 +135,7 @@ public:
|
|||
void update(double dt, double timeScale);
|
||||
|
||||
Eigen::Vector3f getPickRay(float x, float y) const;
|
||||
Eigen::Vector3f getPickRayFisheye(float x, float y) const;
|
||||
|
||||
|
||||
void orbit(const Selection&, const Eigen::Quaternionf &q);
|
||||
|
|
|
@ -171,7 +171,7 @@ void Overlay::drawRectangle(const Rect& r)
|
|||
if (useTexture && r.tex == nullptr)
|
||||
useTexture = false;
|
||||
|
||||
renderer.drawRectangle(r, projection);
|
||||
renderer.drawRectangle(r, ShaderProperties::FisheyeOverrideModeDisabled, projection);
|
||||
}
|
||||
|
||||
void Overlay::setColor(float r, float g, float b, float a)
|
||||
|
|
|
@ -63,5 +63,5 @@ void OverlayImage::render(float curr_time, int width, int height)
|
|||
r.colors[i] = Color(colors[i], colors[i].alpha() * alpha);
|
||||
}
|
||||
r.nColors = 4;
|
||||
renderer->drawRectangle(r, renderer->getOrthoProjectionMatrix());
|
||||
renderer->drawRectangle(r, ShaderProperties::FisheyeOverrideModeDisabled, renderer->getOrthoProjectionMatrix());
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ void PointStarVertexBuffer::startPoints()
|
|||
if (prog == nullptr)
|
||||
return;
|
||||
prog->use();
|
||||
prog->setMVPMatrices(renderer.getProjectionMatrix(), renderer.getModelViewMatrix());
|
||||
|
||||
unsigned int stride = sizeof(StarVertex);
|
||||
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
|
||||
|
|
|
@ -244,6 +244,7 @@ Renderer::Renderer() :
|
|||
screenDpi(96),
|
||||
corrFac(1.12f),
|
||||
faintestAutoMag45deg(8.0f), //def. 7.0f
|
||||
projectionMode(ProjectionMode::PerspectiveMode),
|
||||
#ifndef GL_ES
|
||||
renderMode(GL_FILL),
|
||||
#endif
|
||||
|
@ -668,6 +669,8 @@ void Renderer::resize(int width, int height)
|
|||
|
||||
float Renderer::calcPixelSize(float fovY, float windowHeight)
|
||||
{
|
||||
if (getProjectionMode() == ProjectionMode::FisheyeMode)
|
||||
return 2.0f / windowHeight;
|
||||
return 2 * (float) tan(degToRad(fovY / 2.0)) / (float) windowHeight;
|
||||
}
|
||||
|
||||
|
@ -683,6 +686,16 @@ int Renderer::getScreenDpi() const
|
|||
return screenDpi;
|
||||
}
|
||||
|
||||
int Renderer::getWindowWidth() const
|
||||
{
|
||||
return windowWidth;
|
||||
}
|
||||
|
||||
int Renderer::getWindowHeight() const
|
||||
{
|
||||
return windowHeight;
|
||||
}
|
||||
|
||||
void Renderer::setScreenDpi(int _dpi)
|
||||
{
|
||||
screenDpi = _dpi;
|
||||
|
@ -765,6 +778,18 @@ void Renderer::setLabelMode(int _labelMode)
|
|||
markSettingsChanged();
|
||||
}
|
||||
|
||||
Renderer::ProjectionMode Renderer::getProjectionMode() const
|
||||
{
|
||||
return projectionMode;
|
||||
}
|
||||
|
||||
void Renderer::setProjectionMode(ProjectionMode _projectionMode)
|
||||
{
|
||||
projectionMode = _projectionMode;
|
||||
shaderManager->setFisheyeEnabled(projectionMode == ProjectionMode::FisheyeMode);
|
||||
markSettingsChanged();
|
||||
}
|
||||
|
||||
int Renderer::getOrbitMask() const
|
||||
{
|
||||
return orbitMask;
|
||||
|
@ -867,7 +892,9 @@ void Renderer::addAnnotation(vector<Annotation>& annotations,
|
|||
{
|
||||
GLint view[4] = { 0, 0, windowWidth, windowHeight };
|
||||
Vector3f win;
|
||||
if (Project(pos, m_MVPMatrix, view, win))
|
||||
bool fisheye = projectionMode == ProjectionMode::FisheyeMode;
|
||||
bool success = fisheye ? ProjectFisheye(pos, m_modelMatrix, m_projMatrix, view, win) : ProjectPerspective(pos, m_MVPMatrix, view, win);
|
||||
if (success)
|
||||
{
|
||||
float depth = pos.x() * m_modelMatrix(2, 0) +
|
||||
pos.y() * m_modelMatrix(2, 1) +
|
||||
|
@ -1357,9 +1384,13 @@ static Vector3d astrocentricPosition(const UniversalCoord& pos,
|
|||
|
||||
void Renderer::autoMag(float& faintestMag)
|
||||
{
|
||||
float fieldCorr = 2.0f * FOV/(fov + FOV);
|
||||
faintestMag = (float) (faintestAutoMag45deg * sqrt(fieldCorr));
|
||||
saturationMag = saturationMagNight * (1.0f + fieldCorr * fieldCorr);
|
||||
float fieldCorr;
|
||||
if (getProjectionMode() == ProjectionMode::FisheyeMode)
|
||||
fieldCorr = 2.0f - 2000.0f / (windowHeight / (screenDpi / 25.4f / 3.78f) + 1000.0f); // larger window height = more stars to display
|
||||
else
|
||||
fieldCorr= 2.0f * FOV / (fov + FOV);
|
||||
faintestMag = (float) (faintestAutoMag45deg * sqrt(fieldCorr));
|
||||
saturationMag = saturationMagNight * (1.0f + fieldCorr * fieldCorr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1587,7 +1618,11 @@ void Renderer::draw(const Observer& observer,
|
|||
|
||||
// Set up the projection and modelview matrices.
|
||||
// We'll usethem for positioning star and planet labels.
|
||||
m_projMatrix = Perspective(fov, getAspectRatio(), NEAR_DIST, FAR_DIST);
|
||||
float aspectRatio = getAspectRatio();
|
||||
if (getProjectionMode() == Renderer::ProjectionMode::FisheyeMode)
|
||||
m_projMatrix = Ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, NEAR_DIST, FAR_DIST);
|
||||
else
|
||||
m_projMatrix = Perspective(fov, aspectRatio, NEAR_DIST, FAR_DIST);
|
||||
m_modelMatrix = Affine3f(getCameraOrientation()).matrix();
|
||||
m_MVPMatrix = m_projMatrix * m_modelMatrix;
|
||||
|
||||
|
@ -1827,51 +1862,46 @@ void renderPoint(const Renderer &renderer,
|
|||
#endif
|
||||
}
|
||||
|
||||
void renderLargePoint(const Renderer &renderer,
|
||||
void renderLargePoint(Renderer &renderer,
|
||||
const Vector3f &position,
|
||||
const Color &color,
|
||||
float size,
|
||||
float pixelSize,
|
||||
const Matrix3f &cameraOrientation,
|
||||
const Matrices &mvp)
|
||||
{
|
||||
auto *prog = renderer.getShaderManager().getShader("largestar");
|
||||
if (prog == nullptr)
|
||||
return;
|
||||
|
||||
// Draw billboard for large points
|
||||
prog->use();
|
||||
prog->samplerParam("starTex") = 0;
|
||||
prog->setMVPMatrices(*mvp.projection, *mvp.modelview);
|
||||
prog->vec4Param("color") = color.toVector4();
|
||||
prog->vec3Param("center") = position;
|
||||
prog->floatParam("pointWidth") = size / renderer.getWindowWidth() * 2.0f;
|
||||
prog->floatParam("pointHeight") = size / renderer.getWindowHeight() * 2.0f;
|
||||
|
||||
float distanceAdjust = pixelSize * position.norm() * 0.5f;
|
||||
size *= distanceAdjust;
|
||||
auto &vo = renderer.getVertexObject(VOType::LargeStar, GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
|
||||
vo.bind();
|
||||
if (!vo.initialized())
|
||||
{
|
||||
const float texCoords[] = {
|
||||
// texCoords
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
auto m = renderer.getCameraOrientation().conjugate().toRotationMatrix();
|
||||
Vector3f v0 = position + (cameraOrientation * Vector3f(-1, -1, 0) * size);
|
||||
Vector3f v1 = position + (cameraOrientation * Vector3f( 1, -1, 0) * size);
|
||||
Vector3f v2 = position + (cameraOrientation * Vector3f( 1, 1, 0) * size);
|
||||
Vector3f v3 = position + (cameraOrientation * Vector3f(-1, 1, 0) * size);
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 1.0f
|
||||
};
|
||||
vo.allocate(sizeof(texCoords), texCoords);
|
||||
vo.setVertices(3, GL_FLOAT, false, 5 * sizeof(float), 0); // Vertices are useless, but required to set somehow on Mac...
|
||||
vo.setTextureCoords(2, GL_FLOAT, false, 5 * sizeof(float), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
float quadVertices[] = {
|
||||
// positions // texCoords
|
||||
v0.x(), v0.y(), v0.z(), 0.0f, 0.0f,
|
||||
v1.x(), v1.y(), v1.z(), 1.0f, 0.0f,
|
||||
v2.x(), v2.y(), v2.z(), 1.0f, 1.0f,
|
||||
v3.x(), v3.y(), v3.z(), 0.0f, 1.0f
|
||||
};
|
||||
|
||||
static GLubyte indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||
|
||||
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
|
||||
glEnableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
|
||||
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
|
||||
3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), quadVertices);
|
||||
glVertexAttribPointer(CelestiaGLProgram::TextureCoord0AttributeIndex,
|
||||
2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), quadVertices + 3);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
|
||||
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
|
||||
glDisableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
|
||||
vo.draw(GL_TRIANGLES, 6);
|
||||
vo.unbind();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1974,7 +2004,7 @@ void Renderer::renderObjectAsPoint(const Vector3f& position,
|
|||
if (useSprites)
|
||||
gaussianDiscTex->bind();
|
||||
if (pointSize > gl::maxPointSize)
|
||||
renderLargePoint(*this, center, {color, alpha}, pointSize, pixelSize, m, mvp);
|
||||
renderLargePoint(*this, center, {color, alpha}, pointSize, mvp);
|
||||
else
|
||||
renderPoint(*this, center, {color, alpha}, pointSize, useSprites, mvp);
|
||||
|
||||
|
@ -1988,7 +2018,7 @@ void Renderer::renderObjectAsPoint(const Vector3f& position,
|
|||
{
|
||||
gaussianGlareTex->bind();
|
||||
if (glareSize > gl::maxPointSize)
|
||||
renderLargePoint(*this, center, {color, glareAlpha}, glareSize, pixelSize, m, mvp);
|
||||
renderLargePoint(*this, center, {color, glareAlpha}, glareSize, mvp);
|
||||
else
|
||||
renderPoint(*this, center, {color, glareAlpha}, glareSize, true, mvp);
|
||||
}
|
||||
|
@ -5032,15 +5062,19 @@ Renderer::renderAnnotations(vector<Annotation>::iterator startIter,
|
|||
// Precompute values that will be used to generate the normalized device z value;
|
||||
// we're effectively just handling the projection instead of OpenGL. We use an orthographic
|
||||
// projection matrix in order to get the label text position exactly right but need to mimic
|
||||
// the depth coordinate generation of a perspective projection.
|
||||
float d1 = -(farDist + nearDist) / (farDist - nearDist);
|
||||
float d2 = -2.0f * nearDist * farDist / (farDist - nearDist);
|
||||
// the depth coordinate generation of a perspective projection. For fisheye, just apply a
|
||||
// linear transformation since fisheye uses orthographic projection already.
|
||||
float d0 = farDist - nearDist;
|
||||
float d1 = -(farDist + nearDist) / d0; // Used in perspective projection
|
||||
float d2 = -2.0f * nearDist * farDist / d0; // Used in perspective projection
|
||||
bool fisheye = projectionMode == ProjectionMode::FisheyeMode;
|
||||
|
||||
vector<Annotation>::iterator iter = startIter;
|
||||
for (; iter != endIter && iter->position.z() > nearDist; iter++)
|
||||
{
|
||||
// Compute normalized device z
|
||||
float ndc_z = clamp(d1 + d2 / -iter->position.z(), -1.0f, 1.0f);
|
||||
float z = fisheye ? (1.0f - (iter->position.z() - nearDist) / d0 * 2.0f) : (d1 + d2 / -iter->position.z());
|
||||
float ndc_z = clamp(z, -1.0f, 1.0f);
|
||||
|
||||
// Offsets to left align label
|
||||
int labelHOffset = 0;
|
||||
|
@ -5400,7 +5434,7 @@ bool Renderer::captureFrame(int x, int y, int w, int h, Renderer::PixelFormat fo
|
|||
return glGetError() == GL_NO_ERROR;
|
||||
}
|
||||
|
||||
void Renderer::drawRectangle(const Rect &r, const Eigen::Matrix4f& p, const Eigen::Matrix4f& m)
|
||||
void Renderer::drawRectangle(const Rect &r, int fishEyeOverrideMode, const Eigen::Matrix4f& p, const Eigen::Matrix4f& m)
|
||||
{
|
||||
ShaderProperties shadprop;
|
||||
shadprop.lightModel = ShaderProperties::UnlitModel;
|
||||
|
@ -5410,6 +5444,8 @@ void Renderer::drawRectangle(const Rect &r, const Eigen::Matrix4f& p, const Eige
|
|||
if (r.tex != nullptr)
|
||||
shadprop.texUsage |= ShaderProperties::DiffuseTexture;
|
||||
|
||||
shadprop.fishEyeOverride = fishEyeOverrideMode;
|
||||
|
||||
auto *prog = getShaderManager().getShader(shadprop);
|
||||
if (prog == nullptr)
|
||||
return;
|
||||
|
@ -6062,11 +6098,16 @@ Renderer::renderSolarSystemObjects(const Observer &observer,
|
|||
|
||||
// Set up a perspective projection using the current interval's near and
|
||||
// far clip planes.
|
||||
Matrix4f proj = Perspective(fov, getAspectRatio(), nearPlaneDistance, farPlaneDistance);
|
||||
float aspectRatio = getAspectRatio();
|
||||
Matrix4f proj;
|
||||
if (getProjectionMode() == Renderer::ProjectionMode::FisheyeMode)
|
||||
proj = Ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, nearPlaneDistance, farPlaneDistance);
|
||||
else
|
||||
proj = Perspective(fov, aspectRatio, nearPlaneDistance, farPlaneDistance);
|
||||
Matrices m = { &proj, &m_modelMatrix };
|
||||
|
||||
Frustum intervalFrustum(degToRad(fov),
|
||||
getAspectRatio(),
|
||||
aspectRatio,
|
||||
nearPlaneDistance,
|
||||
farPlaneDistance);
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ enum class VOType
|
|||
AxisArrow = 1,
|
||||
Rectangle = 2,
|
||||
Terminator = 3,
|
||||
Count = 4
|
||||
LargeStar = 4,
|
||||
Count = 5
|
||||
};
|
||||
|
||||
enum class RenderMode
|
||||
|
@ -100,6 +101,12 @@ class Renderer
|
|||
double linearFadeFraction;
|
||||
};
|
||||
|
||||
enum class ProjectionMode
|
||||
{
|
||||
PerspectiveMode = 0,
|
||||
FisheyeMode = 1
|
||||
};
|
||||
|
||||
#ifdef USE_GLCONTEXT
|
||||
bool init(GLContext*, int, int, DetailOptions&);
|
||||
#else
|
||||
|
@ -233,6 +240,8 @@ class Renderer
|
|||
void setRenderFlags(uint64_t);
|
||||
int getLabelMode() const;
|
||||
void setLabelMode(int);
|
||||
ProjectionMode getProjectionMode() const;
|
||||
void setProjectionMode(ProjectionMode);
|
||||
float getAmbientLightLevel() const;
|
||||
void setAmbientLightLevel(float);
|
||||
float getMinimumOrbitSize() const;
|
||||
|
@ -245,6 +254,8 @@ class Renderer
|
|||
void setOrbitMask(int);
|
||||
int getScreenDpi() const;
|
||||
void setScreenDpi(int);
|
||||
int getWindowWidth() const;
|
||||
int getWindowHeight() const;
|
||||
|
||||
// GL wrappers
|
||||
void getViewport(int* x, int* y, int* w, int* h) const;
|
||||
|
@ -268,7 +279,7 @@ class Renderer
|
|||
void enableDepthTest() noexcept;
|
||||
void disableDepthTest() noexcept;
|
||||
|
||||
void drawRectangle(const Rect& r, 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);
|
||||
|
||||
const ColorTemperatureTable* getStarColorTable() const;
|
||||
|
@ -758,6 +769,7 @@ class Renderer
|
|||
float faintestAutoMag45deg;
|
||||
TextureFont* font[FontCount];
|
||||
|
||||
ProjectionMode projectionMode;
|
||||
int renderMode;
|
||||
int labelMode;
|
||||
uint64_t renderFlags;
|
||||
|
|
|
@ -72,6 +72,28 @@ uniform mat4 MVPMatrix;
|
|||
invariant gl_Position;
|
||||
)glsl";
|
||||
|
||||
static const char *VPFunction =
|
||||
"#ifdef FISHEYE\n"
|
||||
"void set_vp(vec4 in_Position) {\n"
|
||||
" float PID2 = 1.570796326794896619231322;\n"
|
||||
" vec4 inPos = ModelViewMatrix * in_Position;\n"
|
||||
" float l = length(inPos.xy);\n"
|
||||
" if (l != 0.0)\n{\n"
|
||||
" float phi = atan(l, -inPos.z);\n"
|
||||
" float lensR = phi / PID2;\n"
|
||||
" inPos.xy *= (lensR / l);\n"
|
||||
" }\n"
|
||||
" gl_Position = ProjectionMatrix * inPos;\n"
|
||||
"}\n"
|
||||
"#else\n"
|
||||
"void set_vp(vec4 in_Position) {\n"
|
||||
" gl_Position = MVPMatrix * in_Position;\n"
|
||||
"}\n"
|
||||
"#endif\n";
|
||||
|
||||
static const char* VertexPosition =
|
||||
"set_vp(in_Position);\n";
|
||||
|
||||
static const char* FragmentHeader = "";
|
||||
|
||||
static const char* CommonAttribs = R"glsl(
|
||||
|
@ -295,6 +317,11 @@ bool operator<(const ShaderProperties& p0, const ShaderProperties& p1)
|
|||
if (p1.effects < p0.effects)
|
||||
return false;
|
||||
|
||||
if (p0.fishEyeOverride < p1.fishEyeOverride)
|
||||
return true;
|
||||
if (p1.fishEyeOverride < p0.fishEyeOverride)
|
||||
return false;
|
||||
|
||||
return (p0.lightModel < p1.lightModel);
|
||||
}
|
||||
|
||||
|
@ -1807,6 +1834,11 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
|
|||
if (props.hasShadowMap())
|
||||
source += "uniform mat4 ShadowMatrix0;\n";
|
||||
|
||||
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
|
||||
source += "#define FISHEYE\n";
|
||||
|
||||
source += VPFunction;
|
||||
|
||||
// Begin main() function
|
||||
source += "\nvoid main(void)\n{\n";
|
||||
if (props.isViewDependent() || props.hasScattering())
|
||||
|
@ -2022,7 +2054,7 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
|
|||
if (props.hasShadowMap())
|
||||
source += "shadowTexCoord0 = ShadowMatrix0 * vec4(in_Position.xyz, 1.0);\n";
|
||||
|
||||
source += "gl_Position = MVPMatrix * in_Position;\n";
|
||||
source += VertexPosition;
|
||||
source += "}\n";
|
||||
|
||||
DumpVSSource(source);
|
||||
|
@ -2532,7 +2564,7 @@ ShaderManager::buildRingsVertexShader(const ShaderProperties& props)
|
|||
}
|
||||
}
|
||||
|
||||
source += "gl_Position = MVPMatrix * in_Position;\n";
|
||||
source += VertexPosition;
|
||||
source += "}\n";
|
||||
|
||||
DumpVSSource(source);
|
||||
|
@ -2647,6 +2679,11 @@ ShaderManager::buildRingsVertexShader(const ShaderProperties& props)
|
|||
if (props.texUsage & ShaderProperties::DiffuseTexture)
|
||||
source += "varying vec2 diffTexCoord;\n";
|
||||
|
||||
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
|
||||
source += "#define FISHEYE\n";
|
||||
|
||||
source += VPFunction;
|
||||
|
||||
source += "\nvoid main(void)\n{\n";
|
||||
|
||||
if (props.texUsage & ShaderProperties::DiffuseTexture)
|
||||
|
@ -2662,7 +2699,7 @@ ShaderManager::buildRingsVertexShader(const ShaderProperties& props)
|
|||
}
|
||||
}
|
||||
|
||||
source += "gl_Position = MVPMatrix * in_Position;\n";
|
||||
source += VertexPosition;
|
||||
source += "}\n";
|
||||
|
||||
DumpVSSource(source);
|
||||
|
@ -2801,6 +2838,11 @@ ShaderManager::buildAtmosphereVertexShader(const ShaderProperties& props)
|
|||
source += "varying vec3 scatterEx;\n";
|
||||
source += "varying vec3 eyeDir_obj;\n";
|
||||
|
||||
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
|
||||
source += "#define FISHEYE\n";
|
||||
|
||||
source += VPFunction;
|
||||
|
||||
// Begin main() function
|
||||
source += "\nvoid main(void)\n{\n";
|
||||
source += "float NL;\n";
|
||||
|
@ -2810,7 +2852,7 @@ ShaderManager::buildAtmosphereVertexShader(const ShaderProperties& props)
|
|||
source += AtmosphericEffects(props);
|
||||
|
||||
source += "eyeDir_obj = eyeDir;\n";
|
||||
source += "gl_Position = MVPMatrix * in_Position;\n";
|
||||
source += VertexPosition;
|
||||
source += "}\n";
|
||||
|
||||
DumpVSSource(source);
|
||||
|
@ -2909,6 +2951,11 @@ ShaderManager::buildEmissiveVertexShader(const ShaderProperties& props)
|
|||
source += DeclareVarying("v_Color", Shader_Vector4);
|
||||
source += DeclareVarying("v_TexCoord0", Shader_Vector2);
|
||||
|
||||
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
|
||||
source += "#define FISHEYE\n";
|
||||
|
||||
source += VPFunction;
|
||||
|
||||
// Begin main() function
|
||||
source += "\nvoid main(void)\n{\n";
|
||||
|
||||
|
@ -2933,8 +2980,7 @@ ShaderManager::buildEmissiveVertexShader(const ShaderProperties& props)
|
|||
if ((props.texUsage & ShaderProperties::PointSprite) != 0)
|
||||
source += PointSizeCalculation();
|
||||
|
||||
source += " gl_Position = MVPMatrix * in_Position;\n";
|
||||
|
||||
source += VertexPosition;
|
||||
source += "}\n";
|
||||
// End of main()
|
||||
|
||||
|
@ -3035,6 +3081,11 @@ ShaderManager::buildParticleVertexShader(const ShaderProperties& props)
|
|||
source << "varying vec3 position_obj;\n";
|
||||
}
|
||||
|
||||
if (props.fishEyeOverride != ShaderProperties::FisheyeOverrideModeDisabled && fisheyeEnabled)
|
||||
source << "#define FISHEYE\n";
|
||||
|
||||
source << VPFunction;
|
||||
|
||||
// Begin main() function
|
||||
source << "\nvoid main(void)\n{\n";
|
||||
|
||||
|
@ -3065,8 +3116,7 @@ ShaderManager::buildParticleVertexShader(const ShaderProperties& props)
|
|||
if ((props.texUsage & ShaderProperties::PointSprite) != 0)
|
||||
source << PointSizeCalculation();
|
||||
|
||||
source << " gl_Position = MVPMatrix * in_Position;\n";
|
||||
|
||||
source << VertexPosition;
|
||||
source << "}\n";
|
||||
// End of main()
|
||||
|
||||
|
@ -3271,8 +3321,7 @@ ShaderManager::buildProgram(const std::string& vs, const std::string& fs)
|
|||
{
|
||||
GLProgram* prog = nullptr;
|
||||
GLShaderStatus status;
|
||||
|
||||
string _vs = fmt::sprintf("%s%s%s\n", CommonHeader, VertexHeader, vs);
|
||||
string _vs = fmt::sprintf("%s%s%s%s%s\n", CommonHeader, VertexHeader, fisheyeEnabled ? "#define FISHEYE\n" : "", VPFunction, vs);
|
||||
string _fs = fmt::sprintf("%s%s%s\n", CommonHeader, FragmentHeader, fs);
|
||||
|
||||
DumpVSSource(_vs);
|
||||
|
@ -3348,6 +3397,11 @@ ShaderManager::buildProgram(const std::string& vs, const std::string& fs)
|
|||
return new CelestiaGLProgram(*prog);
|
||||
}
|
||||
|
||||
void ShaderManager::setFisheyeEnabled(bool enabled)
|
||||
{
|
||||
fisheyeEnabled = enabled;
|
||||
}
|
||||
|
||||
CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program,
|
||||
const ShaderProperties& _props) :
|
||||
program(&_program),
|
||||
|
@ -3383,7 +3437,6 @@ CelestiaGLProgram::intParam(const string& paramName)
|
|||
return IntegerShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
IntegerShaderParameter
|
||||
CelestiaGLProgram::samplerParam(const string& paramName)
|
||||
{
|
||||
|
@ -3788,4 +3841,3 @@ CelestiaGLProgram::setMVPMatrices(const Matrix4f& p, const Matrix4f& m)
|
|||
ModelViewMatrix = m;
|
||||
MVPMatrix = p * m;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#define ADVANCED_CLOUD_SHADOWS 0
|
||||
|
||||
|
||||
class ShaderProperties
|
||||
{
|
||||
public:
|
||||
|
@ -90,6 +89,13 @@ class ShaderProperties
|
|||
VolumetricEmissionEffect = 0x0004,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FisheyeOverrideModeNone = 0,
|
||||
FisheyeOverrideModeEnabled = 1,
|
||||
FisheyeOverrideModeDisabled = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
unsigned short nLights{ 0 };
|
||||
unsigned short texUsage{ 0 };
|
||||
|
@ -106,6 +112,8 @@ class ShaderProperties
|
|||
// Bit 4, on for cloud shadows
|
||||
uint32_t shadowCounts{ 0 };
|
||||
|
||||
int fishEyeOverride { FisheyeOverrideModeNone };
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
@ -292,6 +300,8 @@ class ShaderManager
|
|||
CelestiaGLProgram* getShader(const std::string&);
|
||||
CelestiaGLProgram* getShader(const std::string&, const std::string&, const std::string&);
|
||||
|
||||
void setFisheyeEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
CelestiaGLProgram* buildProgram(const ShaderProperties&);
|
||||
CelestiaGLProgram* buildProgram(const std::string&, const std::string&);
|
||||
|
@ -313,6 +323,8 @@ class ShaderManager
|
|||
|
||||
std::map<ShaderProperties, CelestiaGLProgram*> dynamicShaders;
|
||||
std::map<std::string, CelestiaGLProgram*> staticShaders;
|
||||
|
||||
bool fisheyeEnabled { false };
|
||||
};
|
||||
|
||||
#endif // _CELENGINE_SHADERMANAGER_H_
|
||||
|
|
|
@ -80,7 +80,8 @@ static const float RotationDecay = 2.0f;
|
|||
static const double MaximumTimeRate = 1.0e15;
|
||||
static const double MinimumTimeRate = 1.0e-15;
|
||||
static const float stdFOV = degToRad(45.0f);
|
||||
static const float MaximumFOV = degToRad(120.0f);
|
||||
static const float MaximumFOVPerspective = degToRad(120.0f);
|
||||
static const float MaximumFOVFisheye = degToRad(179.99f);
|
||||
static const float MinimumFOV = degToRad(0.001f);
|
||||
static float KeyRotationAccel = degToRad(120.0f);
|
||||
static float MouseRotationSensitivity = degToRad(1.0f);
|
||||
|
@ -430,7 +431,7 @@ void CelestiaCore::mouseButtonUp(float x, float y, int button)
|
|||
if (isViewportEffectUsed)
|
||||
viewportEffect->distortXY(pickX, pickY);
|
||||
|
||||
Vector3f pickRay = sim->getActiveObserver()->getPickRay(pickX, pickY);
|
||||
Vector3f pickRay = renderer->getProjectionMode() == Renderer::ProjectionMode::FisheyeMode ? sim->getActiveObserver()->getPickRayFisheye(pickX, pickY) : sim->getActiveObserver()->getPickRay(pickX, pickY);
|
||||
|
||||
Selection oldSel = sim->getSelection();
|
||||
Selection newSel = sim->pickObject(pickRay, renderer->getRenderFlags(), pickTolerance);
|
||||
|
@ -450,7 +451,7 @@ void CelestiaCore::mouseButtonUp(float x, float y, int button)
|
|||
if (isViewportEffectUsed)
|
||||
viewportEffect->distortXY(pickX, pickY);
|
||||
|
||||
Vector3f pickRay = sim->getActiveObserver()->getPickRay(pickX, pickY);
|
||||
Vector3f pickRay = renderer->getProjectionMode() == Renderer::ProjectionMode::FisheyeMode ? sim->getActiveObserver()->getPickRayFisheye(pickX, pickY) : sim->getActiveObserver()->getPickRay(pickX, pickY);
|
||||
|
||||
Selection sel = sim->pickObject(pickRay, renderer->getRenderFlags(), pickTolerance);
|
||||
if (!sel.empty())
|
||||
|
@ -632,7 +633,7 @@ void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
|
|||
// Mouse zoom control
|
||||
float amount = dy / height;
|
||||
float minFOV = MinimumFOV;
|
||||
float maxFOV = MaximumFOV;
|
||||
float maxFOV = getMaximumFOV();
|
||||
float fov = sim->getActiveObserver()->getFOV();
|
||||
|
||||
// In order for the zoom to have the right feel, it should be
|
||||
|
@ -1388,7 +1389,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers)
|
|||
|
||||
case '.':
|
||||
addToHistory();
|
||||
if (observer->getFOV() < MaximumFOV)
|
||||
if (observer->getFOV() < getMaximumFOV())
|
||||
{
|
||||
observer->setFOV(observer->getFOV() * 1.05f);
|
||||
setZoomFromFOV();
|
||||
|
@ -2279,13 +2280,26 @@ void CelestiaCore::splitView(View::Type type, View* av, float splitPos)
|
|||
flash(_("Added view"));
|
||||
}
|
||||
|
||||
float CelestiaCore::getMaximumFOV() const
|
||||
{
|
||||
if (renderer->getProjectionMode() == Renderer::ProjectionMode::FisheyeMode)
|
||||
return MaximumFOVFisheye;
|
||||
else
|
||||
return MaximumFOVPerspective;
|
||||
}
|
||||
|
||||
void CelestiaCore::setFOVFromZoom()
|
||||
{
|
||||
for (const auto v : views)
|
||||
if (v->type == View::ViewWindow)
|
||||
{
|
||||
double fov = 2 * atan(height * v->height / (screenDpi / 25.4) / 2. / distanceToScreen) / v->zoom;
|
||||
v->observer->setFOV((float) fov);
|
||||
if (renderer->getProjectionMode() == Renderer::ProjectionMode::FisheyeMode)
|
||||
v->observer->setFOV(MaximumFOVFisheye);
|
||||
else
|
||||
{
|
||||
double fov = 2 * atan(height * v->height / (screenDpi / 25.4) / 2. / distanceToScreen) / v->zoom;
|
||||
v->observer->setFOV((float) fov);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3841,6 +3855,16 @@ bool CelestiaCore::initSimulation(const fs::path& configFileName,
|
|||
}
|
||||
}
|
||||
|
||||
if (!config->projectionMode.empty())
|
||||
{
|
||||
if (config->projectionMode == "perspective")
|
||||
renderer->setProjectionMode(Renderer::ProjectionMode::PerspectiveMode);
|
||||
else if (config->projectionMode == "fisheye")
|
||||
renderer->setProjectionMode(Renderer::ProjectionMode::FisheyeMode);
|
||||
else
|
||||
DPRINTF(LOG_LEVEL_WARNING, "Unknown projection mode %s\n", config->projectionMode);
|
||||
}
|
||||
|
||||
if (!config->viewportEffect.empty() && config->viewportEffect != "none")
|
||||
{
|
||||
if (config->viewportEffect == "passthrough")
|
||||
|
|
|
@ -289,6 +289,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
float getPickTolerance() const;
|
||||
void setPickTolerance(float);
|
||||
|
||||
float getMaximumFOV() const;
|
||||
void setFOVFromZoom();
|
||||
void setZoomFromFOV();
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ CelestiaConfig* ReadCelestiaConfig(const fs::path& filename, CelestiaConfig *con
|
|||
configParams->getString("TitleFont", config->titleFont);
|
||||
configParams->getPath("LogoTexture", config->logoTextureFile);
|
||||
configParams->getString("Cursor", config->cursor);
|
||||
configParams->getString("ProjectionMode", config->projectionMode);
|
||||
configParams->getString("ViewportEffect", config->viewportEffect);
|
||||
configParams->getString("WarpMeshFile", config->warpMeshFile);
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
float SolarSystemMaxDistance;
|
||||
unsigned ShadowMapSize;
|
||||
|
||||
std::string projectionMode;
|
||||
std::string viewportEffect;
|
||||
std::string warpMeshFile;
|
||||
};
|
||||
|
|
|
@ -256,7 +256,7 @@ void View::drawBorder(int gWidth, int gHeight, const Color &color, float linewid
|
|||
r.setColor(color);
|
||||
r.setType(Rect::Type::BorderOnly);
|
||||
r.setLineWidth(linewidth);
|
||||
renderer->drawRectangle(r, renderer->getOrthoProjectionMatrix());
|
||||
renderer->drawRectangle(r, ShaderProperties::FisheyeOverrideModeDisabled, renderer->getOrthoProjectionMatrix());
|
||||
}
|
||||
|
||||
void View::updateFBO(int gWidth, int gHeight)
|
||||
|
|
|
@ -65,10 +65,10 @@ LookAt(const Eigen::Matrix<T, 3, 1>& from, const Eigen::Matrix<T, 3, 1>& to, con
|
|||
/*! Project to screen space
|
||||
*/
|
||||
template<class T> bool
|
||||
Project(const Eigen::Matrix<T, 3, 1>& from,
|
||||
const Eigen::Matrix<T, 4, 4>& modelViewProjectionMatrix,
|
||||
const int viewport[4],
|
||||
Eigen::Matrix<T, 3, 1>& to)
|
||||
ProjectPerspective(const Eigen::Matrix<T, 3, 1>& from,
|
||||
const Eigen::Matrix<T, 4, 4>& modelViewProjectionMatrix,
|
||||
const int viewport[4],
|
||||
Eigen::Matrix<T, 3, 1>& to)
|
||||
{
|
||||
Eigen::Matrix<T, 4, 1> in(from.x(), from.y(), from.z(), T(1.0));
|
||||
Eigen::Matrix<T, 4, 1> out = modelViewProjectionMatrix * in;
|
||||
|
@ -87,16 +87,48 @@ Project(const Eigen::Matrix<T, 3, 1>& from,
|
|||
}
|
||||
|
||||
template<class T> bool
|
||||
Project(const Eigen::Matrix<T, 3, 1>& from,
|
||||
const Eigen::Matrix<T, 4, 4>& modelViewMatrix,
|
||||
const Eigen::Matrix<T, 4, 4>& projMatrix,
|
||||
const int viewport[4],
|
||||
Eigen::Matrix<T, 3, 1>& to)
|
||||
ProjectPerspective(const Eigen::Matrix<T, 3, 1>& from,
|
||||
const Eigen::Matrix<T, 4, 4>& modelViewMatrix,
|
||||
const Eigen::Matrix<T, 4, 4>& projMatrix,
|
||||
const int viewport[4],
|
||||
Eigen::Matrix<T, 3, 1>& to)
|
||||
{
|
||||
Eigen::Matrix<T, 4, 4> m = projMatrix * modelViewMatrix;
|
||||
return Project(from, m, viewport, to);
|
||||
}
|
||||
|
||||
template<class T> bool
|
||||
ProjectFisheye(const Eigen::Matrix<T, 3, 1>& from,
|
||||
const Eigen::Matrix<T, 4, 4>& modelViewMatrix,
|
||||
const Eigen::Matrix<T, 4, 4>& projMatrix,
|
||||
const int viewport[4],
|
||||
Eigen::Matrix<T, 3, 1>& to)
|
||||
{
|
||||
Eigen::Matrix<T, 4, 1> inPos = modelViewMatrix * Eigen::Matrix<T, 4, 1>(from.x(), from.y(), from.z(), T(1.0));
|
||||
T l = hypot(inPos.x(), inPos.y());
|
||||
if (l != T(0.0))
|
||||
{
|
||||
T phi = atan2(l, -inPos.z());
|
||||
T ratio = phi / T(M_PI_2) / l;
|
||||
inPos.x() *= ratio;
|
||||
inPos.y() *= ratio;
|
||||
}
|
||||
|
||||
Eigen::Matrix<T, 4, 1> out = projMatrix * inPos;
|
||||
if (out.w() == T(0.0))
|
||||
return false;
|
||||
|
||||
out = out.array() / out.w();
|
||||
// Map x, y and z to range 0-1
|
||||
out = T(0.5) + out.array() * T(0.5);
|
||||
// Map x,y to viewport
|
||||
out.x() = viewport[0] + out.x() * viewport[2];
|
||||
out.y() = viewport[1] + out.y() * viewport[3];
|
||||
|
||||
to = { out.x(), out.y(), out.z() };
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*! Return an perspective projection matrix
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue