Skip to content

Commit

Permalink
Reimplement galaxies using shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
375gnu committed Nov 25, 2019
1 parent 02bcf41 commit 39eb715
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 50 deletions.
11 changes: 11 additions & 0 deletions shaders/galaxy_frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#version 120

varying vec4 color;
varying vec2 texCoord;

uniform sampler2D galaxyTex;

void main(void)
{
gl_FragColor = texture2D(galaxyTex, texCoord) * color;
}
21 changes: 21 additions & 0 deletions shaders/galaxy_vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#version 120

uniform sampler2D colorTex;

varying vec4 color;
varying vec2 texCoord;

void main(void)
{
// we pass color index as short int
// reusing gl_MultiTexCoord0.z
// we use 255 only because we have 256 color indices
float t = gl_MultiTexCoord0.z / 255.0f; // [0, 255] -> [0, 1]
// we pass alpha values as as short int
// reusing gl_MultiTexCoord0.w
// we use 65535 for better precision
float a = gl_MultiTexCoord0.w / 65535.0f; // [0, 65535] -> [0, 1]
color = vec4(texture2D(colorTex, vec2(t, 0.0f)).rgb, a);
texCoord = gl_MultiTexCoord0.st;
gl_Position = ftransform();
}
148 changes: 100 additions & 48 deletions src/celengine/galaxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ using namespace std;
using namespace celmath;

static int width = 128, height = 128;
static Vector3f colorTable[256];
static const unsigned int GALAXY_POINTS = 3500;

static bool formsInitialized = false;
Expand All @@ -41,6 +40,7 @@ static GalacticForm** ellipticalForms = nullptr;
static GalacticForm* irregularForm = nullptr;

static Texture* galaxyTex = nullptr;
static Texture* colorTex = nullptr;

static void InitializeForms();
static GalacticForm* buildGalacticForms(const fs::path& filename);
Expand Down Expand Up @@ -106,6 +106,21 @@ static void GalaxyTextureEval(float u, float v, float /*w*/, unsigned char *pixe
pixel[3] = pixVal;
}

static void ColorTextureEval(float u, float v, float /*w*/, unsigned char *pixel)
{
unsigned int i = (u*0.5f + 0.5f)*255.99f; // [-1, 1] -> [0, 255]

// generic Hue profile as deduced from true-color imaging for spirals
// Hue in degrees
float hue = 25 * tanh(0.0615f * (27 - i));
if (i >= 28) hue += 220;
//convert Hue to RGB
float r, g, b;
DeepSkyObject::hsv2rgb(&r, &g, &b, hue, 0.20f, 1.0f);
pixel[0] = (unsigned char) (r * 255.99f);
pixel[1] = (unsigned char) (g * 255.99f);
pixel[2] = (unsigned char) (b * 255.99f);
}

float Galaxy::getDetail() const
{
Expand Down Expand Up @@ -257,28 +272,38 @@ void Galaxy::render(const Vector3f& offset,
const Quaternionf& viewerOrientation,
float brightness,
float pixelSize,
const Renderer* /* unused */)
const Renderer* renderer)
{
if (form == nullptr)
{
//renderGalaxyEllipsoid(offset, viewerOrientation, brightness, pixelSize);
}
else
{
renderGalaxyPointSprites(offset, viewerOrientation, brightness, pixelSize);
renderGalaxyPointSprites(offset, viewerOrientation, brightness, pixelSize, renderer);
}
}

struct GalaxyVertex
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW;

inline void glVertex4(const Vector4f& v)
Vector4f position;
Matrix<GLshort, 4, 1> texCoord; // texCoord.x = x, texCoord.y = y, texCoord.z = color index, texCoord.w = alpha
};

static void draw(const GalaxyVertex *v, size_t count, void *indices)
{
glVertex3fv(v.data());
glVertexPointer(4, GL_FLOAT, sizeof(GalaxyVertex), &v->position);
glTexCoordPointer(4, GL_SHORT, sizeof(GalaxyVertex), &v->texCoord);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indices);
}

void Galaxy::renderGalaxyPointSprites(const Vector3f& offset,
const Quaternionf& viewerOrientation,
float brightness,
float pixelSize)
float pixelSize,
const Renderer* renderer)
{
if (form == nullptr)
return;
Expand All @@ -297,16 +322,28 @@ void Galaxy::renderGalaxyPointSprites(const Vector3f& offset,
if (size < minimumFeatureSize)
return;

auto *prog = renderer->getShaderManager().getShader("galaxy");
if (prog == nullptr)
return;

if (galaxyTex == nullptr)
{
galaxyTex = CreateProceduralTexture(width, height, GL_RGBA,
GalaxyTextureEval);
}
assert(galaxyTex != nullptr);

glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
galaxyTex->bind();

if (colorTex == nullptr)
{
colorTex = CreateProceduralTexture(256, 1, GL_RGBA,
ColorTextureEval);
}
assert(colorTex != nullptr);
glActiveTexture(GL_TEXTURE1);
colorTex->bind();

Matrix3f viewMat = viewerOrientation.conjugate().toRotationMatrix();
Vector4f v0(Vector4f::Zero());
Vector4f v1(Vector4f::Zero());
Expand All @@ -317,20 +354,15 @@ void Galaxy::renderGalaxyPointSprites(const Vector3f& offset,
v2.head(3) = viewMat * Vector3f( 1, 1, 0) * size;
v3.head(3) = viewMat * Vector3f(-1, 1, 0) * size;

//Mat4f m = (getOrientation().toMatrix4() *
// Mat4f::scaling(form->scale) *
// Mat4f::scaling(getRadius()));

Quaternionf orientation = getOrientation().conjugate();

Matrix3f mScale = form->scale.asDiagonal() * size;
Matrix3f mLinear = orientation.toRotationMatrix() * mScale;

Matrix4f m = Matrix4f::Identity();
m.topLeftCorner(3,3) = mLinear;
m.block<3,1>(0, 3) = offset;

int pow2 = 1;
int pow2 = 1;

BlobVector* points = form->blobs;
unsigned int nPoints = (unsigned int) (points->size() * clamp(getDetail()));
Expand All @@ -357,10 +389,22 @@ void Galaxy::renderGalaxyPointSprites(const Vector3f& offset,
glPushMatrix();
glTranslatef(-offset.x(), -offset.y(), -offset.z());

float btot = ((type > SBc) && (type < Irr))? 2.5f: 5.0f;
const float btot = ((type > SBc) && (type < Irr)) ? 2.5f : 5.0f;
const float spriteScaleFactor = 1.0f / 1.55f;

glBegin(GL_QUADS);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

vector<GalaxyVertex, aligned_allocator<GalaxyVertex>> vertices;
vertices.reserve(4096 / sizeof(GalaxyVertex));
vector<short> indices;
indices.reserve(4096 / sizeof(GalaxyVertex) / 4 * 6); // 6 indices per 4 vertices
unsigned short j = 0;

prog->use();
prog->samplerParam("galaxyTex") = 0;
prog->samplerParam("colorTex") = 1;

for (unsigned int i = 0; i < nPoints; ++i)
{
if ((i & pow2) != 0)
Expand All @@ -379,22 +423,52 @@ void Galaxy::renderGalaxyPointSprites(const Vector3f& offset,
Vector4f p = m * b.position;
float br = b.brightness / 255.0f;

Vector3f c = colorTable[b.colorIndex]; // lookup static color table

float screenFrac = size / p.norm();
if (screenFrac < 0.1f)
{
float a = btot * (0.1f - screenFrac) * brightness_corr * brightness * br;
glColor4f(c.x(), c.y(), c.z(), (4.0f * lightGain + 1.0f) * a);
glTexCoord2f(0, 0); glVertex4(p + v0);
glTexCoord2f(1, 0); glVertex4(p + v1);
glTexCoord2f(1, 1); glVertex4(p + v2);
glTexCoord2f(0, 1); glVertex4(p + v3);
float a = (4.0f * lightGain + 1.0f) * btot * (0.1f - screenFrac) * brightness_corr * brightness * br;
short alpha = (short) (a * 65535.99f);
short color = (short)b.colorIndex;
GalaxyVertex vtx;
vtx.position = p + v0;
vtx.texCoord = { 0, 0, color, alpha };
vertices.push_back(vtx);
vtx.position = p + v1;
vtx.texCoord = { 1, 0, color, alpha };
vertices.push_back(vtx);
vtx.position = p + v2;
vtx.texCoord = { 1, 1, color, alpha };
vertices.push_back(vtx);
vtx.position = p + v3;
vtx.texCoord = { 0, 1, color, alpha };
vertices.push_back(vtx);

indices.push_back(j+0);
indices.push_back(j+1);
indices.push_back(j+2);
indices.push_back(j+0);
indices.push_back(j+2);
indices.push_back(j+3);
j += 4;

if ((vertices.size() + 4) * sizeof(GalaxyVertex) > 4096)
{
draw(&vertices[0], indices.size(), indices.data());
vertices.clear();
indices.clear();
j = 0;
}
}
}
glEnd();

if (indices.size() > 0)
draw(&vertices[0], indices.size(), indices.data());

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glUseProgram(0);
glPopMatrix();
glActiveTexture(GL_TEXTURE0);
}


Expand Down Expand Up @@ -495,12 +569,7 @@ float Galaxy::getLightGain()

void Galaxy::setLightGain(float lg)
{
if (lg < 0.0f)
lightGain = 0.0f;
else if (lg > 1.0f)
lightGain = 1.0f;
else
lightGain = lg;
lightGain = clamp(lg);
}


Expand Down Expand Up @@ -601,23 +670,6 @@ GalacticForm* buildGalacticForms(const fs::path& filename)

void InitializeForms()
{
// build color table:

for (unsigned int i = 0; i < 256; i++)
{
float rr, gg, bb;
//
// generic Hue profile as deduced from true-color imaging for spirals
// Hue in degrees

float hue = (i < 28)? 25 * tanh(0.0615f * (27 - i)): 25 * tanh(0.0615f * (27 - i)) + 220;

//convert Hue to RGB

DeepSkyObject::hsv2rgb(&rr, &gg, &bb, hue, 0.20f, 1.0f);
Color c(rr, gg, bb);
colorTable[i] = Vector3f(c.red(), c.green(), c.blue());
}
// Spiral Galaxies, 7 classical Hubble types

spiralForms = new GalacticForm*[7];
Expand Down
5 changes: 3 additions & 2 deletions src/celengine/galaxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Galaxy : public DeepSkyObject
const Eigen::Quaternionf& viewerOrientation,
float brightness,
float pixelSize,
const Renderer* r = nullptr) override;
const Renderer* r) override;

GalacticForm* getForm() const;

Expand Down Expand Up @@ -85,7 +85,8 @@ class Galaxy : public DeepSkyObject
void renderGalaxyPointSprites(const Eigen::Vector3f& offset,
const Eigen::Quaternionf& viewerOrientation,
float brightness,
float pixelSize);
float pixelSize,
const Renderer* r);
#if 0
void renderGalaxyEllipsoid(const Eigen::Vector3f& offset,
const Eigen::Quaternionf& viewerOrientation,
Expand Down

0 comments on commit 39eb715

Please sign in to comment.