Commit c8e178d1 authored by Dario Seyb's avatar Dario Seyb

polished render passes a bit

parent ba33feff
......@@ -31,10 +31,41 @@ float pow8(float val) {
return val * val;
}
vec2 getDistance(vec3 o, vec3 l, float r) {
float a = -dot(l, o);
float d = a * a - dot(o, o) + r * r;
if (d < 0) {
return vec2(-1, -1);
}
float dsqrt = sqrt(d);
// We are inside the atmosphere, return the distance to the far intersection
return vec2(a + dsqrt, a - dsqrt);
}
vec3 sampleTransmittance(float r, float mu, float Rg, float Rt) {
// Angle is higher than horizon angle, need to sample inverse direction.
float viewZenith = acos(mu);
if ( viewZenith > 1.710422666954442985 /*98°*/) {
vec3 pos = vec3(0, r, 0);
vec3 dir = normalize(vec3( 0, mu + sin(viewZenith), mu - sin(viewZenith)));
float dist = getDistance(pos, dir, Rg).y;
vec3 intersect = pos + dir * dist;
r = length(intersect);
mu = dot(normalize(pos), -dir);
}
float uR = sqrt((r - Rg) / (Rt - Rg));
float uMu = atan((mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5;
return texture(uTexture, vec2(uMu, uR)).rgb;
}
vec4 color() {
float depth = texture(uSamplerDepth, gl_FragCoord.xy*uOneOverScreenSize ).r;
float planetRadius = 6374.1305775862702;
float atmosphereRadius = planetRadius * 1.05;
float planetRadius = 6360;
float atmosphereRadius = 6678;
vec3 camSpaceWorldPos = unpackWorldPosition(depth) - uCameraPosition;
vec3 viewDir = normalize(tePosition - uCameraPosition);
......@@ -59,26 +90,42 @@ vec4 color() {
float distance = totalDistance/steps;
float totalFog = 0;
vec3 Iv = vec3(0);
vec3 Is = vec3(1.0,0.9,0.7);
float fogAmount;
vec3 fogColor;
for(int i = 0; i < steps; i++) {
currentPos += viewDir * distance;
vec3 localPos = currentPos - uObjectPosition + uCameraPosition;
float currentHeight = length(localPos) - planetRadius;
float h = currentHeight/atmosphereThickness;
float cloud = 0; //max(fbm_3d( localPos, 6, 0.0003) + 0.05, 0) * 1000 * (pow8(1-h));
cloud = h > 0.75 ? 0 : cloud;
float atm = 20 * exp(-h/0.25);
float density = ( atm + cloud)/atmosphereRadius;
totalFog += density * distance;
}
float fogAmount = 1.0 - exp(-totalFog);
if(uHasAlbedoMap) {
vec3 localPos = currentPos - uObjectPosition + uCameraPosition;
float currentHeight = length(localPos) - planetRadius;
float h = currentHeight/atmosphereThickness;
fogColor = sampleTransmittance(h, dot(viewDir, normalize(localPos)), planetRadius, atmosphereRadius);
if(depth != 1) {
fogColor = sampleTransmittance( length(worldPos), dot(viewDir, normalize(worldPos)), planetRadius, atmosphereRadius)/fogColor;
}
fogAmount = 0.8;
} else {
vec3 Iv = vec3(0);
vec3 Is = vec3(1.0,0.9,0.7);
for(int i = 0; i < steps; i++) {
currentPos += viewDir * distance;
vec3 localPos = currentPos - uObjectPosition + uCameraPosition;
float currentHeight = length(localPos) - planetRadius;
float h = currentHeight/atmosphereThickness;
float cloud = 0; //max(fbm_3d( localPos, 6, 0.0003) + 0.05, 0) * 1000 * (pow8(1-h));
cloud = h > 0.75 ? 0 : cloud;
float atm = 20 * exp(-h/0.25);
float density = ( atm + cloud)/atmosphereRadius;
totalFog += density * distance;
}
fogAmount = 1.0 - exp(-totalFog);
vec3 fogColor = mix( vec3(0.3,0.4,0.9), // bluish
vec3(1.0,0.9,0.7) * 1.2, // yellowish
pow8(sunAmount) );
fogColor = mix( vec3(0.3,0.4,0.9), // bluish
vec3(1.0,0.9,0.7) * 1.2, // yellowish
pow8(sunAmount) );
}
return vec4(fogColor, fogAmount); //texture(uTexture, teTexCoord).rgba * uTintColor;
}
......
......@@ -5,7 +5,16 @@ in vec2 teTexCoord;
in vec3 tePosition;
uniform sampler2D uSamplerDepth;
uniform bool uHasAlbedoMap;
uniform sampler2D uTexture;
uniform bool uHasNormalMap;
uniform sampler2D uNormalMap;
uniform bool uHasSpecularSmoothnessMap;
uniform sampler2D uSpecularSmoothnessMap;
uniform vec4 uEmissiveColor;
uniform vec4 uTintColor;
uniform float uTime;
......
......@@ -4,7 +4,8 @@
enum class ScreenSpaceSize {
FULL,
HALF,
QUARTER
QUARTER,
EIGHTH
};
struct ScreenSpaceTexture {
......
......@@ -112,14 +112,14 @@ public:
bool startup() override;
void shutdown() override;
void addRenderPass(Entity cam, StringHash name) {
void addRenderPass(Entity cam, StringHash name, ScreenSpaceSize size = ScreenSpaceSize::FULL) {
cam.component<Camera>()->renderPassIndex = m_passes.size();
auto target = SharedFrameBufferObject(new FrameBufferObject());
target->attachColorTexture("oColor", createScreenspaceTexture(ScreenSpaceSize::FULL, GL_RGBA32F));
target->attachColorTexture("oColor", createScreenspaceTexture(size, GL_RGBA32F));
target->validate();
auto txaa = SharedFrameBufferObject(new FrameBufferObject());
txaa->attachColorTexture("oColor", createScreenspaceTexture(ScreenSpaceSize::FULL, GL_RGBA32F));
txaa->attachColorTexture("oColor", createScreenspaceTexture(size, GL_RGBA32F));
txaa->validate();
m_passIds[name] = m_passes.size();
......
......@@ -46,7 +46,7 @@ public:
Geometry playerIconGeometry;
std::map<Entity::Id, Entity> minimapItems;
Entity addPlanet(Transform::Handle sun, std::string n, double m, double r, double e, double a, double i, double N, double P, double T);
Entity addPlanet(Transform::Handle sun, std::string n, double m, double r, double e, double a, double i, double N, double P, double T, bool generateAtmosphereLookups = false);
bool startup() override;
void shutdown() override;
......
......@@ -438,7 +438,7 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
glEnable(GL_BLEND);
glCullFace(GL_BACK);
auto compositingRes = glm::vec2(pass.compositingTarget->getSize());
auto compositingRes = glm::vec2(m_secondaryCompositingBuffer->getSize());
glViewport(0, 0, compositingRes.x, compositingRes.y);
m_deferredCombineProgram->use();
......@@ -516,7 +516,28 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
auto& drawCall = pass.submittedDrawCallsTransparent[i];
drawCall.material.prog->use();
drawCall.material.prog->setTexture("uSamplerDepth", m_depthBuffer, 0);
drawCall.material.prog->setTexture("uTexture", drawCall.material.mainTexture, 1);
if (drawCall.material.mainTexture) {
drawCall.material.prog->setTexture("uTexture", drawCall.material.mainTexture, 1);
drawCall.material.prog->setUniform("uHasAlbedoMap", true);
} else {
drawCall.material.prog->setUniform("uHasAlbedoMap", false);
}
if (drawCall.material.normalTexture) {
drawCall.material.prog->setTexture("uNormalMap", drawCall.material.normalTexture, 2);
drawCall.material.prog->setUniform("uHasNormalMap", true);
} else {
drawCall.material.prog->setUniform("uHasNormalMap", false);
}
if (drawCall.material.specularSmoothnessTexture) {
drawCall.material.prog->setTexture("uSpecularSmoothnessMap", drawCall.material.specularSmoothnessTexture, 3);
drawCall.material.prog->setUniform("uHasSpecularSmoothnessMap", true);
} else {
drawCall.material.prog->setUniform("uHasSpecularSmoothnessMap", false);
}
drawCall.material.prog->setUniform("uFar", cam->far);
drawCall.material.prog->setUniform("uTime", (float)totalTime);
drawCall.material.prog->setUniform("uTintColor", drawCall.material.tintColor);
......@@ -540,12 +561,14 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
glDisable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
// TXAA
glDisable(GL_BLEND);
pass.compositingTarget->bind();
int width = pass.compositingTarget->getSize().x;
int height = pass.compositingTarget->getSize().y;
glViewport(0, 0, width, height);
m_txaaProg->use();
m_txaaProg->setTexture(
......@@ -561,6 +584,7 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // create 2 triangles (defined in shader) with no attributes
if (!pass.renderToTextureOnly) {
glViewport(0, 0, m_primaryCompositingBuffer->getSize().x, m_primaryCompositingBuffer->getSize().y);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
......
......@@ -38,6 +38,7 @@ bool OrbitalSimulationSystem::startup() {
orbitTorus = { vaoCircle };
orbitTorus.vao->setMode(GL_LINES);
glLineWidth(10);
minimapItem = Geometry{ VertexArrayObjectCreator("circle_filled.obj").create() };
playerIconGeometry = Geometry{ VertexArrayObjectCreator("cone.obj").create() };
......@@ -326,7 +327,7 @@ SharedTextureData computeTransmittanceTexture(double atmosphereRadius,
result->setFormat(GL_RGBA);
result->setType(GL_UNSIGNED_BYTE);
stbi_write_png("transmittance.png", WIDTH, HEIGHT, 4, transmittance, 0);
// stbi_write_png("transmittance.png", WIDTH, HEIGHT, 4, transmittance, 0);
return result;
}
......@@ -349,11 +350,32 @@ glm::dvec3 sampleTransmittance(SharedTextureData transmittance, double height,
double viewZenith, double planetRadius, double atmosphereRadius) {
auto data = transmittance->getData();
if (height < planetRadius) {
return{ 0, 0, 0 };
}
// Angle is higher than horizon angle, need to sample inverse direction.
if (viewZenith > 1.710422666954442985 /*98*/) {
return{ 0, 0, 0 };
auto pos = glm::dvec3{ 0, height, 0 };
auto dir = glm::rotateX(glm::dvec3{ 0, 1, 0 }, viewZenith);
auto dist = getDistance(pos, dir, planetRadius).y;
// We'll always hit the planet
assert(dist > 0);
auto intersect = pos + dir * dist;
height = glm::length(intersect) + 1;
viewZenith = glm::acos(glm::dot(glm::normalize(pos), -dir));
}
int h = transmittance->getHeight();
int y = (int)(glm::sqrt((height - planetRadius) / (atmosphereRadius - planetRadius)) * h - 1.0);
int y = (int)(glm::sqrt((height - planetRadius) / (atmosphereRadius - planetRadius)) * h);
viewZenith = glm::cos(viewZenith);
int w = transmittance->getWidth();
int x = (int)(glm::atan((viewZenith * glm::tan(1.5) + 0.15 * tan(1.5)) / 1.15) * w - 1.5 * w - 1.0);
int x = (int)(glm::atan((viewZenith + 0.15) / (1.0 + 0.15) * glm::tan(1.5)) / 1.5 * (w - 1));
//int x = (int)(glm::atan((viewZenith * glm::tan(1.5) + 0.15 * tan(1.5)) / 1.15) * w - 1.5 * w - 1.0);
assert(x >= 0 && x < w);
assert(y >= 0 && y < h);
......@@ -373,6 +395,7 @@ glm::dvec3 computeInscattering(SharedTextureData transmittance,
sunZenith = glm::acos(sunZenith);
viewSun = glm::acos(viewSun);
double startHeight = height;
glm::dvec3 pos = {0, height, 0};
glm::dvec3 dir =
glm::normalize(glm::rotateX(glm::dvec3(0, 1, 0), viewZenith));
......@@ -397,12 +420,12 @@ glm::dvec3 computeInscattering(SharedTextureData transmittance,
glm::dvec3(constBetaMie / 0.9) * opticalDepthMie;
currentTransmittance = glm::exp(-currentTransmittance);
double currentSunZenith = (sunZenith * startHeight + viewSun * i * stepSize) / height;
// Calculate incoming light
glm::dvec3 lightTransmittance =
sampleTransmittance(transmittance, height, glm::cos(sunZenith), planetRadius, atmosphereRadius);
glm::dvec3 lightTransmittance = sampleTransmittance(transmittance, glm::max(planetRadius, height), currentSunZenith, planetRadius, atmosphereRadius);
result += currentTransmittance * lightTransmittance *
(constBetaRayleigh * phaseRayleigh(viewSun) +
glm::dvec3(constBetaMie) * phaseMie(viewSun, g)) *
(constBetaRayleigh +
glm::dvec3(constBetaMie)) *
stepSize;
pos += dir * stepSize;
......@@ -411,7 +434,7 @@ glm::dvec3 computeInscattering(SharedTextureData transmittance,
return result;
}
std::vector<SharedTextureData>
SharedTextureData
computeInscatteringTexture(SharedTextureData transmittance,
double atmosphereRadius, double planetRadius,
glm::dvec3 constBetaRayleigh, double constBetaMie,
......@@ -422,15 +445,20 @@ computeInscatteringTexture(SharedTextureData transmittance,
const int VIEW_SUN_LAYERS = 8;
const int PIXELS_PER_SUN_LAYER = WIDTH / VIEW_SUN_LAYERS;
std::vector<SharedTextureData> result;
auto inscattering = new GLubyte[WIDTH * HEIGHT * DEPTH * 4];
SharedTextureData inscatteringData = std::make_shared<TextureData>();
inscatteringData->setWidth(WIDTH);
inscatteringData->setHeight(HEIGHT);
inscatteringData->setDepth(DEPTH);
inscatteringData->setData(inscattering);
inscatteringData->setFormat(GL_RGBA);
inscatteringData->setType(GL_UNSIGNED_BYTE);
for (int z = 0; z < DEPTH; z++) {
double r = (double(z + 1) / DEPTH);
double r = (double(z) / DEPTH);
double height = r * (atmosphereRadius - planetRadius) + planetRadius;
auto inscattering = new GLubyte[WIDTH * HEIGHT * 4];
auto pixel = inscattering;
auto pixel = inscattering + z * WIDTH * HEIGHT * 4;
for (int y = 0; y < HEIGHT; y++) {
double viewZenith = glm::cos(M_PI * (1.0 - double(y) / HEIGHT));
......@@ -453,27 +481,18 @@ computeInscatteringTexture(SharedTextureData transmittance,
}
}
SharedTextureData inscatteringData = std::make_shared<TextureData>();
inscatteringData->setWidth(WIDTH);
inscatteringData->setHeight(HEIGHT);
inscatteringData->setData(inscattering);
inscatteringData->setFormat(GL_RGBA);
inscatteringData->setType(GL_UNSIGNED_BYTE);
result.push_back(inscatteringData);
stbi_write_png(("inscattering_" + std::to_string(z) + ".png").c_str(), WIDTH, HEIGHT, 4, inscattering, 0);
// stbi_write_png(("inscattering_" + std::to_string(z) + ".png").c_str(), WIDTH, HEIGHT, 4, inscattering + z * WIDTH * HEIGHT * 4, 0);
}
return result;
return inscatteringData;
}
void precomputeAtmosphereLookupTexture(double molecularNumberDensity,
void precomputeAtmosphereLookupTextures(double molecularNumberDensity,
double airIOR, glm::dvec3 rgbWavelengths,
double planetRadius,
double atmosphereRadius,
double averageDensityHeight, double g) {
double averageDensityHeight, double g,
SharedTexture2D& transmittanceText, SharedTexture3D& inscatteringText) {
const double wavelengthIndependentFactor =
(8.0 * glm::pow3(M_PI) * glm::pow2(glm::pow3(airIOR) - 1.0));
const glm::dvec3 constBetaRayleigh =
......@@ -486,13 +505,25 @@ void precomputeAtmosphereLookupTexture(double molecularNumberDensity,
auto transmittance = computeTransmittanceTexture(
atmosphereRadius, planetRadius, constBetaRayleigh, constBetaMie,
averageDensityHeight);
auto inscattering =
computeInscatteringTexture(transmittance, atmosphereRadius, planetRadius,
constBetaRayleigh, constBetaMie, g);
transmittanceText = std::make_shared<Texture2D>(GL_RGBA);
transmittanceText->setMinFilter(GL_LINEAR);
transmittanceText->setMagFilter(GL_LINEAR);
transmittanceText->setImageData(transmittance);
inscatteringText = std::make_shared<Texture3D>(GL_RGBA);
inscatteringText->setMinFilter(GL_LINEAR);
inscatteringText->setMagFilter(GL_LINEAR);
inscatteringText->setImageData(inscattering);
}
// Mass is in solar masses!
Entity OrbitalSimulationSystem::addPlanet(Transform::Handle sun, std::string n, double m, double r, double e, double a, double i, double N, double P, double T) {
Entity OrbitalSimulationSystem::addPlanet(Transform::Handle sun, std::string n, double m, double r, double e, double a, double i, double N, double P, double T, bool generateAtmosphereLookups) {
// Mass, Radius, Eccentricity, Semimajor axis, Inclination, Ascending Node, Arg. of Periapsis, time at perihelion
auto planetEntity = m_scene->create();
......@@ -514,10 +545,22 @@ Entity OrbitalSimulationSystem::addPlanet(Transform::Handle sun, std::string n,
planetEntity.assign<Drawable>(defaultGeom, earthMat, 2, m_renderer->getRenderPassId("Main"_sh));
// Add an atmosphere to the planet
precomputeAtmosphereLookupTexture(2.55 * glm::pow(10.0, -11.0 ), // premultiply by nm^4 => 25 - 4*9
1.000206102, glm::dvec3{ 680, 550, 440 }, // in nm
6360000, 6420000, 8000, 0.76);
if (generateAtmosphereLookups) {
SharedTexture2D transmittance;
SharedTexture3D inscattering;
precomputeAtmosphereLookupTextures(2.55 * glm::pow(10.0, -11.0), // premultiply by nm^4 => 25 - 4*9
1.000206102, glm::dvec3{ 680, 550, 440 }, // in nm
6360000, 6678000, 8000, 0.76, transmittance, inscattering);
atmosphereMat.mainTexture = transmittance;
atmosphereMat.specularSmoothnessTexture = inscattering;
} else {
atmosphereMat.mainTexture = nullptr;
atmosphereMat.specularSmoothnessTexture = nullptr;
}
auto atmosphere = m_scene->create();
auto atmosphereTransform = atmosphere.assign<Transform>();
......@@ -573,7 +616,7 @@ Entity OrbitalSimulationSystem::addPlanet(Transform::Handle sun, std::string n,
auto itemTransform = mmItem.assign<Transform>();
itemTransform->position = { posInAU.x, posInAU.z, posInAU.y - 70 };
itemTransform->scale = { 0.3, 0.3, 0.3 };
itemTransform->scale = { 2.0, 2.0, 2.0 };
itemTransform->rotation = glm::rotate<double>(M_PI/2, glm::dvec3(1, 0, 0));
minimapItems[planetEntity.id()] = mmItem;
......
......@@ -296,18 +296,16 @@ bool PlayerSystem::startup() {
m_renderer->addRenderPass(m_skyboxCamera, "Skybox"_sh);
m_renderer->addRenderPass(m_mainCamera, "Main"_sh);
m_renderer->addRenderPass(m_cockpitCamera, "Cockpit"_sh);
m_renderer->addRenderPass(m_minimapCamera, "Minimap"_sh);
//m_renderer->setRenderPassOnlyTexture("Minimap"_sh, true);
m_renderer->addRenderPass(m_minimapCamera, "Minimap"_sh, ScreenSpaceSize::QUARTER);
m_renderer->setRenderPassOnlyTexture("Minimap"_sh, true);
playerIcon = m_scene->create();
playerIcon.assign<Drawable>(m_orbitals->playerIconGeometry, m_orbitals->playerIconMaterial, 0, m_renderer->getRenderPassId("Minimap"_sh));
auto itemTransform = playerIcon.assign<Transform>();
itemTransform->scale = { 0.4, 0.4, 0.4 };
itemTransform->scale = { 3.0, 3.0, 3.0 };
itemTransform->position = glm::dvec3(0, 0, -70);
m_audio->setListener(m_mainCamera);
m_events->subscribe<KeyboardEvent>([this](const KeyboardEvent& e) { handleKeyboard(e); });
......
......@@ -43,6 +43,8 @@ void AtmosphereTestScene::switchConsole() {
m_renderer->setRenderPassActive("Minimap"_sh, true);
cockpitSoundSource->setVolume(0);
cockpitSoundSource->play();
m_renderer->setRenderPassActive("Console"_sh, false);
} else {
// TODO: Fix returning to console!
return;
......@@ -79,7 +81,7 @@ bool AtmosphereTestScene::startup() {
m_renderer->setRenderPassActive("Skybox"_sh, false);
m_renderer->setRenderPassActive("Minimap"_sh, false);
m_renderer->addRenderPass(consoleCamera, "Console"_sh);
m_renderer->addRenderPass(consoleCamera, "Console"_sh, ScreenSpaceSize::HALF);
m_console.m_events = m_events;
......@@ -159,7 +161,6 @@ bool AtmosphereTestScene::startup() {
m_player->setRotation(glm::mat4_cast(camTargetRot));
isInterpolatingCamera = false;
m_player->setHasControl(true);
m_renderer->setRenderPassActive("Console"_sh, false);
consoleSoundSource->setVolume(0);
cockpitSoundSource->setVolume(1);
}
......@@ -268,7 +269,7 @@ void AtmosphereTestScene::switchToMainScene() {
// a i N w
mercury = m_orbitals->addPlanet(sunTransform, "Mercury", 0.000000165956, 0.003505316091954, 0.205633, 0.387098, 0.1222500, 0.84153, 0.50768, 0);
venus = m_orbitals->addPlanet(sunTransform, "Venus", 0.00000243522, 0.008695402298851, 0.006778, 0.723330, 0.0592500, 1.33679, 0.95717, 0);
earth = m_orbitals->addPlanet(sunTransform, "Earth", 0.000002988, 0.009153735632184, 0.016713, 1.000000, 0.0000000, 0.00000, 4.93533, 0);
earth = m_orbitals->addPlanet(sunTransform, "Earth", 0.000002988, 0.009153735632184, 0.016713, 1.000000, 0.0000000, 0.00000, 4.93533, 0, false);
mars = m_orbitals->addPlanet(sunTransform, "Mars", 0.000000319716, 0.004870689655172, 0.093396, 1.523688, 0.0322851, 0.02333, 4.99858, 0);
jupiter = m_orbitals->addPlanet(sunTransform, "Jupiter", 0.000954265748, 0.1004468390805, 0.048482, 5.202560, 0.0227500, 1.75150, 4.77905, 0);
saturn = m_orbitals->addPlanet(sunTransform, "Saturn", 0.00028386, 0.08366666666667, 0.055580, 9.554750, 0.0434412, 1.98230, 5.92169, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment