mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 09:59:18 +02:00
skydome object
This commit is contained in:
11
Float3d.h
11
Float3d.h
@@ -53,7 +53,10 @@ double inline float3::Length() const
|
||||
{
|
||||
return sqrt(x * x + y * y + z * z);
|
||||
};
|
||||
inline float3 operator/(const float3 &v, double k)
|
||||
inline float3 operator*( float3 const &v, float const k ) {
|
||||
return float3( v.x * k, v.y * k, v.z * k );
|
||||
};
|
||||
inline float3 operator/( float3 const &v, float const k )
|
||||
{
|
||||
return float3(v.x / k, v.y / k, v.z / k);
|
||||
};
|
||||
@@ -67,10 +70,14 @@ inline float3 SafeNormalize(const float3 &v)
|
||||
retVal = v / l;
|
||||
return retVal;
|
||||
};
|
||||
inline float3 CrossProduct(const float3 &v1, const float3 &v2)
|
||||
inline float3 CrossProduct( float3 const &v1, float3 const &v2 )
|
||||
{
|
||||
return float3(v1.y * v2.z - v1.z * v2.y, v2.x * v1.z - v2.z * v1.x, v1.x * v2.y - v1.y * v2.x);
|
||||
}
|
||||
inline float DotProduct( float3 const &v1, float3 const &v2 ) {
|
||||
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
class float4
|
||||
{ // kwaternion obrotu
|
||||
|
||||
@@ -1808,7 +1808,8 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
|
||||
// wczytanie modelu z pliku
|
||||
std::string name = ToLower(FileName);
|
||||
// trim extension if needed
|
||||
if (name.substr(name.rfind('.')) == ".t3d")
|
||||
if( ( name.rfind( '.' ) != std::string::npos )
|
||||
&& ( name.substr( name.rfind( '.' ) ) == ".t3d" ) )
|
||||
{
|
||||
name.erase(name.rfind('.'));
|
||||
}
|
||||
|
||||
97
World.cpp
97
World.cpp
@@ -31,6 +31,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Train.h"
|
||||
#include "Driver.h"
|
||||
#include "Console.h"
|
||||
#include "color.h"
|
||||
|
||||
#define TEXTURE_FILTER_CONTROL_EXT 0x8500
|
||||
#define TEXTURE_LOD_BIAS_EXT 0x8501
|
||||
@@ -1434,11 +1435,12 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
|
||||
void TWorld::Update_Lights() {
|
||||
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
|
||||
if( Global::fMoveLight < 0.0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
// double a=Global::fTimeAngleDeg/180.0*M_PI-M_PI; //kąt godzinny w radianach
|
||||
double a = fmod( Global::fTimeAngleDeg, 360.0 ) / 180.0 * M_PI -
|
||||
M_PI; // kąt godzinny w radianach
|
||||
@@ -1516,32 +1518,7 @@ void TWorld::Update_Lights() {
|
||||
+0.150 * ( Global::diffuseDayLight[ 0 ] + Global::ambientDayLight[ 0 ] ) // R
|
||||
+ 0.295 * ( Global::diffuseDayLight[ 1 ] + Global::ambientDayLight[ 1 ] ) // G
|
||||
+ 0.055 * ( Global::diffuseDayLight[ 2 ] + Global::ambientDayLight[ 2 ] ); // B
|
||||
#else
|
||||
Sun.update();
|
||||
auto const position = Sun.getPosition();
|
||||
Global::DayLight.position[0] = position.x;
|
||||
Global::DayLight.position[1] = position.y;
|
||||
Global::DayLight.position[2] = position.z;
|
||||
auto const direction = -1.0 * Sun.getDirection();
|
||||
Global::DayLight.direction = direction;
|
||||
auto const intensity = std::min( 2.0f * Sun.getIntensity(), 1.25f );
|
||||
|
||||
Global::DayLight.diffuse[ 0 ] = 255.0 / 255.0 * intensity;
|
||||
Global::DayLight.diffuse[ 1 ] = 242.0 / 255.0 * intensity;
|
||||
Global::DayLight.diffuse[ 2 ] = 231.0 / 255.0 * intensity;
|
||||
// Global::DayLight.diffuse[ 3 ] = 1.0f;// std::min( 0.15f + intensity, 1.0f );
|
||||
Global::DayLight.ambient[ 0 ] = 155.0 / 255.0 * intensity * 0.75f;
|
||||
Global::DayLight.ambient[ 1 ] = 192.0 / 255.0 * intensity * 0.75f;
|
||||
Global::DayLight.ambient[ 2 ] = 231.0 / 255.0 * intensity * 0.75f;
|
||||
// Global::DayLight.ambient[ 3 ] = 1.0f;
|
||||
/*
|
||||
// Global::DayLight.ambient[ 3 ] = intensity;
|
||||
GLfloat ambient[] = { 0.1f + 0.5f * intensity, 0.1f + 0.5f * intensity, 0.1f + 0.5f * intensity, 0.5f };
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
|
||||
*/
|
||||
Global::fLuminance = intensity;
|
||||
#endif
|
||||
|
||||
vector3 sky = vector3( Global::AtmoColor[ 0 ], Global::AtmoColor[ 1 ], Global::AtmoColor[ 2 ] );
|
||||
if( Global::fLuminance < 0.25 ) { // przyspieszenie zachodu/wschodu
|
||||
sky *= 4.0 * Global::fLuminance; // nocny kolor nieba
|
||||
@@ -1554,7 +1531,45 @@ void TWorld::Update_Lights() {
|
||||
else {
|
||||
glFogfv( GL_FOG_COLOR, Global::FogColor ); // kolor mgły
|
||||
}
|
||||
glClearColor( sky.x, sky.y, sky.z, 0.0 ); // kolor nieba
|
||||
#else
|
||||
Sun.update();
|
||||
auto const position = Sun.getPosition();
|
||||
// update skydome with current sun position
|
||||
SkyDome.Update( position );
|
||||
auto const skydomecolour = SkyDome.GetAverageColor();
|
||||
auto const skydomehsv = RGBtoHSV( skydomecolour );
|
||||
// update sunlight object
|
||||
Global::DayLight.position[0] = position.x;
|
||||
Global::DayLight.position[1] = position.y;
|
||||
Global::DayLight.position[2] = position.z;
|
||||
|
||||
Global::DayLight.direction = -1.0 * Sun.getDirection();
|
||||
|
||||
auto const intensity = std::min( 0.05f + Sun.getIntensity() + skydomehsv.z, 1.25f );
|
||||
|
||||
Global::DayLight.diffuse[ 0 ] = intensity * 255.0f / 255.0f;
|
||||
Global::DayLight.diffuse[ 1 ] = intensity * 242.0f / 255.0f;
|
||||
Global::DayLight.diffuse[ 2 ] = intensity * 231.0f / 255.0f;
|
||||
// Global::DayLight.diffuse[ 3 ] = 1.0f;// std::min( 0.15f + intensity, 1.0f );
|
||||
Global::DayLight.ambient[ 0 ] = skydomecolour.x;
|
||||
Global::DayLight.ambient[ 1 ] = skydomecolour.y;
|
||||
Global::DayLight.ambient[ 2 ] = skydomecolour.z;
|
||||
/*
|
||||
Global::DayLight.ambient[ 0 ] = 155.0 / 255.0 * intensity * 0.75f;
|
||||
Global::DayLight.ambient[ 1 ] = 192.0 / 255.0 * intensity * 0.75f;
|
||||
Global::DayLight.ambient[ 2 ] = 231.0 / 255.0 * intensity * 0.75f;
|
||||
*/
|
||||
// Global::DayLight.ambient[ 3 ] = 1.0f;
|
||||
|
||||
Global::fLuminance = intensity;
|
||||
|
||||
Global::FogColor[ 0 ] = skydomecolour.x;
|
||||
Global::FogColor[ 1 ] = skydomecolour.y;
|
||||
Global::FogColor[ 2 ] = skydomecolour.z;
|
||||
glFogfv( GL_FOG_COLOR, Global::FogColor ); // kolor mgły
|
||||
#endif
|
||||
|
||||
glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f ); // kolor nieba
|
||||
}
|
||||
|
||||
bool TWorld::Render()
|
||||
@@ -1574,18 +1589,32 @@ bool TWorld::Render()
|
||||
Camera.SetMatrix(); // ustawienie macierzy kamery względem początku scenerii
|
||||
|
||||
if( !Global::bWireFrame ) { // bez nieba w trybie rysowania linii
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_FOG );
|
||||
Clouds.Render();
|
||||
glEnable( GL_FOG );
|
||||
}
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDepthMask( GL_FALSE );
|
||||
glPushMatrix();
|
||||
glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
|
||||
SkyDome.Render();
|
||||
// Clouds.Render();
|
||||
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, Global::lightPos );
|
||||
#else
|
||||
Sun.render( Camera.Pos );
|
||||
Global::DayLight.apply_angle();
|
||||
Global::DayLight.apply_intensity();
|
||||
Sun.render();
|
||||
Global::DayLight.apply_angle();
|
||||
Global::DayLight.apply_intensity();
|
||||
#endif
|
||||
|
||||
glPopMatrix();
|
||||
glDepthMask( GL_TRUE );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_FOG );
|
||||
glEnable( GL_LIGHTING );
|
||||
}
|
||||
|
||||
if (Global::bUseVBO)
|
||||
{ // renderowanie przez VBO
|
||||
if (!Ground.RenderVBO(Camera.Pos))
|
||||
|
||||
2
World.h
2
World.h
@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Ground.h"
|
||||
#include "sky.h"
|
||||
#include "sun.h"
|
||||
#include "skydome.h"
|
||||
#include "mczapkie/mover.h"
|
||||
|
||||
class TWorld
|
||||
@@ -54,6 +55,7 @@ class TWorld
|
||||
GLuint base; // numer DL dla znaków w napisach
|
||||
texture_manager::size_type light; // numer tekstury dla smugi
|
||||
TSky Clouds;
|
||||
CSkyDome SkyDome;
|
||||
cSun Sun;
|
||||
TEvent *KeyEvents[10]; // eventy wyzwalane z klawiaury
|
||||
TMoverParameters *mvControlled; // wskaźnik na człon silnikowy, do wyświetlania jego parametrów
|
||||
|
||||
118
color.h
Normal file
118
color.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "float3d.h"
|
||||
|
||||
inline
|
||||
float3
|
||||
XYZtoRGB( float3 const &XYZ ) {
|
||||
|
||||
// M^-1 for Adobe RGB from http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html
|
||||
// float const mi[ 3 ][ 3 ] = { 2.041369, -0.969266, 0.0134474, -0.5649464, 1.8760108, -0.1183897, -0.3446944, 0.041556, 1.0154096 };
|
||||
// m^-1 for sRGB:
|
||||
float const mi[ 3 ][ 3 ] = { 3.240479, -0.969256, 0.055648, -1.53715, 1.875991, -0.204043, -0.49853, 0.041556, 1.057311 };
|
||||
|
||||
return float3{
|
||||
XYZ.x*mi[ 0 ][ 0 ] + XYZ.y*mi[ 1 ][ 0 ] + XYZ.z*mi[ 2 ][ 0 ],
|
||||
XYZ.x*mi[ 0 ][ 1 ] + XYZ.y*mi[ 1 ][ 1 ] + XYZ.z*mi[ 2 ][ 1 ],
|
||||
XYZ.x*mi[ 0 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] };
|
||||
}
|
||||
|
||||
inline
|
||||
float3
|
||||
RGBtoHSV( float3 const &RGB ) {
|
||||
|
||||
float3 hsv;
|
||||
|
||||
float const max = std::max( std::max( RGB.x, RGB.y ), RGB.z );
|
||||
float const min = std::min( std::min( RGB.x, RGB.y ), RGB.z );
|
||||
float const delta = max - min;
|
||||
|
||||
hsv.z = max; // v
|
||||
if( delta < 0.00001 ) {
|
||||
hsv.y = 0;
|
||||
hsv.x = 0; // undefined, maybe nan?
|
||||
return hsv;
|
||||
}
|
||||
if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
|
||||
hsv.y = ( delta / max ); // s
|
||||
}
|
||||
else {
|
||||
// if max is 0, then r = g = b = 0
|
||||
// s = 0, v is undefined
|
||||
hsv.y = 0.0;
|
||||
hsv.x = NAN; // its now undefined
|
||||
return hsv;
|
||||
}
|
||||
if( RGB.x >= max ) // > is bogus, just keeps compilor happy
|
||||
hsv.x = ( RGB.y - RGB.z ) / delta; // between yellow & magenta
|
||||
else
|
||||
if( RGB.y >= max )
|
||||
hsv.x = 2.0 + ( RGB.y - RGB.x ) / delta; // between cyan & yellow
|
||||
else
|
||||
hsv.x = 4.0 + ( RGB.x - RGB.y ) / delta; // between magenta & cyan
|
||||
|
||||
hsv.x *= 60.0; // degrees
|
||||
|
||||
if( hsv.x < 0.0 )
|
||||
hsv.x += 360.0;
|
||||
|
||||
return hsv;
|
||||
}
|
||||
|
||||
inline
|
||||
float3
|
||||
HSVtoRGB( float3 const &HSV ) {
|
||||
|
||||
float3 rgb;
|
||||
|
||||
if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings
|
||||
rgb.x = HSV.z;
|
||||
rgb.y = HSV.z;
|
||||
rgb.z = HSV.z;
|
||||
return rgb;
|
||||
}
|
||||
float hh = HSV.x;
|
||||
if( hh >= 360.0 ) hh = 0.0;
|
||||
hh /= 60.0;
|
||||
int const i = (int)hh;
|
||||
float const ff = hh - i;
|
||||
float const p = HSV.z * ( 1.0 - HSV.y );
|
||||
float const q = HSV.z * ( 1.0 - ( HSV.y * ff ) );
|
||||
float const t = HSV.z * ( 1.0 - ( HSV.y * ( 1.0 - ff ) ) );
|
||||
|
||||
switch( i ) {
|
||||
case 0:
|
||||
rgb.x = HSV.z;
|
||||
rgb.y = t;
|
||||
rgb.z = p;
|
||||
break;
|
||||
case 1:
|
||||
rgb.x = q;
|
||||
rgb.y = HSV.z;
|
||||
rgb.z = p;
|
||||
break;
|
||||
case 2:
|
||||
rgb.x = p;
|
||||
rgb.y = HSV.z;
|
||||
rgb.z = t;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rgb.x = p;
|
||||
rgb.y = q;
|
||||
rgb.z = HSV.z;
|
||||
break;
|
||||
case 4:
|
||||
rgb.x = t;
|
||||
rgb.y = p;
|
||||
rgb.z = HSV.z;
|
||||
break;
|
||||
case 5:
|
||||
default:
|
||||
rgb.x = HSV.z;
|
||||
rgb.y = p;
|
||||
rgb.z = q;
|
||||
break;
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
@@ -123,6 +123,7 @@
|
||||
<ClCompile Include="ResourceManager.cpp" />
|
||||
<ClCompile Include="Segment.cpp" />
|
||||
<ClCompile Include="sky.cpp" />
|
||||
<ClCompile Include="skydome.cpp" />
|
||||
<ClCompile Include="Sound.cpp" />
|
||||
<ClCompile Include="Spring.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
@@ -149,6 +150,7 @@
|
||||
<ClInclude Include="Button.h" />
|
||||
<ClInclude Include="Camera.h" />
|
||||
<ClInclude Include="Classes.h" />
|
||||
<ClInclude Include="color.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="Console\LPT.h" />
|
||||
<ClInclude Include="Console\MWD.h" />
|
||||
@@ -186,6 +188,7 @@
|
||||
<ClInclude Include="ResourceManager.h" />
|
||||
<ClInclude Include="Segment.h" />
|
||||
<ClInclude Include="sky.h" />
|
||||
<ClInclude Include="skydome.h" />
|
||||
<ClInclude Include="Sound.h" />
|
||||
<ClInclude Include="Spring.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
|
||||
@@ -195,6 +195,9 @@
|
||||
<ClCompile Include="renderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="skydome.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="opengl\glew.h">
|
||||
@@ -377,6 +380,12 @@
|
||||
<ClInclude Include="renderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="skydome.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="color.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
14
sky.cpp
14
sky.cpp
@@ -32,21 +32,11 @@ void TSky::Init()
|
||||
|
||||
void TSky::Render()
|
||||
{
|
||||
#ifndef EU07_USE_OLD_LIGHTING_MODEL
|
||||
return;
|
||||
#endif
|
||||
if (mdCloud)
|
||||
{ // jeśli jest model nieba
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask( GL_FALSE );
|
||||
glPushMatrix();
|
||||
glTranslatef(Global::pCameraPosition.x, Global::pCameraPosition.y,
|
||||
Global::pCameraPosition.z);
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
// TODO: re-implement this
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
|
||||
#else
|
||||
glDisable( GL_LIGHTING );
|
||||
#endif
|
||||
if (Global::bUseVBO)
|
||||
{ // renderowanie z VBO
|
||||
@@ -62,11 +52,7 @@ void TSky::Render()
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
// TODO: re-implement this
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
|
||||
#else
|
||||
glEnable( GL_LIGHTING );
|
||||
#endif
|
||||
glDepthMask( GL_TRUE );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
332
skydome.cpp
Normal file
332
skydome.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
//******************************************************************************//
|
||||
// NightShine Engine //
|
||||
// Sky : Gradient SkyDome Class //
|
||||
//******************************************************************************//
|
||||
// sky gradient based on "A practical analytic model for daylight"
|
||||
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "opengl/glew.h"
|
||||
#include "skydome.h"
|
||||
#include "color.h"
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
float CSkyDome::m_distributionluminance[ 5 ][ 2 ] = { // Perez distributions
|
||||
{ 0.17872f , -1.46303f }, // a = darkening or brightening of the horizon
|
||||
{ -0.35540f , 0.42749f }, // b = luminance gradient near the horizon,
|
||||
{ -0.02266f , 5.32505f }, // c = relative intensity of the circumsolar region
|
||||
{ 0.12064f , -2.57705f }, // d = width of the circumsolar region
|
||||
{ -0.06696f , 0.37027f } // e = relative backscattered light
|
||||
};
|
||||
float CSkyDome::m_distributionxcomp[ 5 ][ 2 ] = {
|
||||
{ -0.01925f , -0.25922f },
|
||||
{ -0.06651f , 0.00081f },
|
||||
{ -0.00041f , 0.21247f },
|
||||
{ -0.06409f , -0.89887f },
|
||||
{ -0.00325f , 0.04517f }
|
||||
};
|
||||
float CSkyDome::m_distributionycomp[ 5 ][ 2 ] = {
|
||||
{ -0.01669f , -0.26078f },
|
||||
{ -0.09495f , 0.00921f },
|
||||
{ -0.00792f , 0.21023f },
|
||||
{ -0.04405f , -1.65369f },
|
||||
{ -0.01092f , 0.05291f }
|
||||
};
|
||||
|
||||
float CSkyDome::m_zenithxmatrix[ 3 ][ 4 ] = {
|
||||
{ 0.00165f, -0.00375f, 0.00209f, 0.00000f },
|
||||
{ -0.02903f, 0.06377f, -0.03202f, 0.00394f },
|
||||
{ 0.11693f, -0.21196f, 0.06052f, 0.25886f }
|
||||
};
|
||||
float CSkyDome::m_zenithymatrix[ 3 ][ 4 ] = {
|
||||
{ 0.00275f, -0.00610f, 0.00317f, 0.00000f },
|
||||
{ -0.04214f, 0.08970f, -0.04153f, 0.00516f },
|
||||
{ 0.15346f, -0.26756f, 0.06670f, 0.26688f }
|
||||
};
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
float clamp( float const Value, float const Min, float const Max ) {
|
||||
|
||||
float value = Value;
|
||||
if( value < Min ) { value = Min; }
|
||||
if( value > Max ) { value = Max; }
|
||||
return value;
|
||||
}
|
||||
|
||||
float interpolate( float const First, float const Second, float const Factor ) {
|
||||
|
||||
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
CSkyDome::CSkyDome (int const Tesselation) :
|
||||
m_tesselation( Tesselation ) {
|
||||
|
||||
// SetSunPosition( Math3D::vector3(75.0f, 0.0f, 0.0f) );
|
||||
SetTurbidity( 3.5f );
|
||||
SetExposure( true, 16.0f );
|
||||
SetOvercastFactor( 0.08f );
|
||||
SetGammaCorrection( 2.2f );
|
||||
Generate();
|
||||
}
|
||||
|
||||
CSkyDome::~CSkyDome() {
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
void CSkyDome::Generate() {
|
||||
// radius of dome
|
||||
float const radius = 1.0f; // 100.0f;
|
||||
|
||||
// create geometry chunk
|
||||
int const latitudes = m_tesselation / 2;
|
||||
int const longitudes = m_tesselation;
|
||||
|
||||
for( int i = 0; i < latitudes; ++i ) {
|
||||
|
||||
float lat0 = M_PI * ( -0.5f + (float)( i ) / latitudes );
|
||||
float z0 = std::sin( lat0 );
|
||||
float zr0 = std::cos( lat0 );
|
||||
|
||||
float lat1 = M_PI * ( -0.5f + (float)( i + 1 ) / latitudes );
|
||||
float z1 = std::sin( lat1 );
|
||||
float zr1 = std::cos( lat1 );
|
||||
|
||||
// quad strip
|
||||
for( int j = 0; j <= longitudes / 2; ++j ) {
|
||||
|
||||
float longitude = 2.0 * M_PI * (float)( j ) / longitudes;
|
||||
float x = std::cos( longitude );
|
||||
float y = std::sin( longitude );
|
||||
|
||||
m_vertices.emplace_back( float3( x * zr0, y * zr0 - 0.1f, z0 ) * radius );
|
||||
// m_normals.emplace_back( float3( -x * zr0, -y * zr0, -z0 ) );
|
||||
m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) );
|
||||
|
||||
m_vertices.emplace_back( float3( x * zr1, y * zr1 - 0.1f, z1 ) * radius );
|
||||
// m_normals.emplace_back( float3( -x * zr1, -y * zr1, -z1 ) );
|
||||
m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
void CSkyDome::Update( Math3D::vector3 const &Sun ) {
|
||||
|
||||
if( true == SetSunPosition( Sun ) ) {
|
||||
// build colors if there's a change in sun position
|
||||
RebuildColors();
|
||||
}
|
||||
}
|
||||
|
||||
// render skydome to screen
|
||||
void CSkyDome::Render() {
|
||||
|
||||
int const latitudes = m_tesselation / 2;
|
||||
int const longitudes = m_tesselation;
|
||||
int idx = 0;
|
||||
|
||||
for( int i = 0; i < latitudes; ++i ) {
|
||||
|
||||
::glBegin( GL_QUAD_STRIP );
|
||||
for( int j = 0; j <= longitudes / 2; ++j ) {
|
||||
|
||||
::glColor3f( m_colours[ idx ].x, m_colours[ idx ].y, m_colours[ idx ].z );
|
||||
// ::glNormal3f( m_normals[ idx ].x, m_normals[ idx ].y, m_normals[ idx ].z );
|
||||
::glVertex3f( m_vertices[ idx ].x, m_vertices[ idx ].y, m_vertices[ idx ].z );
|
||||
++idx;
|
||||
::glColor3f( m_colours[ idx ].x, m_colours[ idx ].y, m_colours[ idx ].z );
|
||||
// ::glNormal3f( m_normals[ idx ].x, m_normals[ idx ].y, m_normals[ idx ].z );
|
||||
::glVertex3f( m_vertices[ idx ].x, m_vertices[ idx ].y, m_vertices[ idx ].z );
|
||||
++idx;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
bool CSkyDome::SetSunPosition( Math3D::vector3 const &Direction ) {
|
||||
|
||||
auto sundirection = SafeNormalize( float3( Direction.x, Direction.y, Direction.z) );
|
||||
if( sundirection == m_sundirection ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sundirection = sundirection;
|
||||
m_thetasun = std::acosf( m_sundirection.y );
|
||||
m_phisun = std::atan2( m_sundirection.z , m_sundirection.x );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CSkyDome::SetTurbidity( float const Turbidity ) {
|
||||
|
||||
m_turbidity = clamp( Turbidity, 1.0f, 512.0f );
|
||||
}
|
||||
|
||||
void CSkyDome::SetExposure( bool const Linearexposure, float const Expfactor ) {
|
||||
|
||||
m_linearexpcontrol = Linearexposure;
|
||||
m_expfactor = 1.0f / clamp( Expfactor, 1.0f, std::numeric_limits<float>::infinity() );
|
||||
}
|
||||
|
||||
void CSkyDome::SetGammaCorrection( float const Gamma ) {
|
||||
|
||||
m_gammacorrection = 1.0f / clamp( Gamma, std::numeric_limits<float>::epsilon(), std::numeric_limits<float>::infinity() );
|
||||
}
|
||||
|
||||
void CSkyDome::SetOvercastFactor( float const Overcast ) {
|
||||
|
||||
m_overcast = clamp( Overcast, 0.0f, 1.0f );
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
void CSkyDome::GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity ) {
|
||||
|
||||
Perez[ 0 ] = Distribution[ 0 ][ 0 ] * Turbidity + Distribution[ 0 ][ 1 ];
|
||||
Perez[ 1 ] = Distribution[ 1 ][ 0 ] * Turbidity + Distribution[ 1 ][ 1 ];
|
||||
Perez[ 2 ] = Distribution[ 2 ][ 0 ] * Turbidity + Distribution[ 2 ][ 1 ];
|
||||
Perez[ 3 ] = Distribution[ 3 ][ 0 ] * Turbidity + Distribution[ 3 ][ 1 ];
|
||||
Perez[ 4 ] = Distribution[ 4 ][ 0 ] * Turbidity + Distribution[ 4 ][ 1 ];
|
||||
}
|
||||
|
||||
float CSkyDome::GetZenith( float Zenithmatrix[ 3 ][ 4 ], const float Theta, const float Turbidity ) {
|
||||
|
||||
const float theta2 = Theta*Theta;
|
||||
const float theta3 = Theta*theta2;
|
||||
|
||||
return ( Zenithmatrix[0][0] * theta3 + Zenithmatrix[0][1] * theta2 + Zenithmatrix[0][2] * Theta + Zenithmatrix[0][3]) * Turbidity * Turbidity +
|
||||
( Zenithmatrix[1][0] * theta3 + Zenithmatrix[1][1] * theta2 + Zenithmatrix[1][2] * Theta + Zenithmatrix[1][3]) * Turbidity +
|
||||
( Zenithmatrix[2][0] * theta3 + Zenithmatrix[2][1] * theta2 + Zenithmatrix[2][2] * Theta + Zenithmatrix[2][3]);
|
||||
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
|
||||
float CSkyDome::PerezFunctionO1( float Perezcoeffs[ 5 ], const float Thetasun, const float Zenithval ) {
|
||||
|
||||
const float val = ( 1.0f + Perezcoeffs[ 0 ] * std::exp( Perezcoeffs[ 1 ] ) ) *
|
||||
( 1.0f + Perezcoeffs[ 2 ] * std::exp( Perezcoeffs[ 3 ] * Thetasun ) + Perezcoeffs[ 4 ] * std::pow( std::cos( Thetasun ), 2 ) );
|
||||
|
||||
return Zenithval / val;
|
||||
}
|
||||
|
||||
float CSkyDome::PerezFunctionO2( float Perezcoeffs[ 5 ], const float Icostheta, const float Gamma, const float Cosgamma2, const float Zenithval ) {
|
||||
// iCosTheta = 1.0f / cosf(theta)
|
||||
// cosGamma2 = SQR( cosf( gamma ) )
|
||||
return Zenithval * ( 1.0f + Perezcoeffs[ 0 ] * std::exp( Perezcoeffs[ 1 ] * Icostheta ) ) *
|
||||
( 1.0f + Perezcoeffs[ 2 ] * std::exp( Perezcoeffs[ 3 ] * Gamma ) + Perezcoeffs[ 4 ] * Cosgamma2 );
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
void CSkyDome::RebuildColors() {
|
||||
|
||||
// get zenith luminance
|
||||
float const chi = ( (4.0f / 9.0f) - (m_turbidity / 120.0f) ) * ( M_PI - (2.0f * m_thetasun) );
|
||||
float zenithluminance = ( (4.0453f * m_turbidity) - 4.9710f ) * std::tan( chi ) - (0.2155f * m_turbidity) + 2.4192f;
|
||||
|
||||
// get x / y zenith
|
||||
float zenithx = GetZenith( m_zenithxmatrix, m_thetasun, m_turbidity );
|
||||
float zenithy = GetZenith( m_zenithymatrix, m_thetasun, m_turbidity );
|
||||
|
||||
// get perez function parametrs
|
||||
float perezluminance[5], perezx[5], perezy[5];
|
||||
GetPerez( perezluminance, m_distributionluminance, m_turbidity );
|
||||
GetPerez( perezx, m_distributionxcomp, m_turbidity );
|
||||
GetPerez( perezy, m_distributionycomp, m_turbidity );
|
||||
|
||||
// make some precalculation
|
||||
zenithx = PerezFunctionO1( perezx, m_thetasun, zenithx );
|
||||
zenithy = PerezFunctionO1( perezy, m_thetasun, zenithy );
|
||||
zenithluminance = PerezFunctionO1( perezluminance, m_thetasun, zenithluminance );
|
||||
|
||||
// start with fresh average for the new pass
|
||||
float3 averagecolor{ 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// trough all vertices
|
||||
float3 vertex;
|
||||
float3 color, colorconverter;
|
||||
|
||||
for ( unsigned int i = 0; i < m_vertices.size(); ++i ) {
|
||||
// grab it
|
||||
vertex = SafeNormalize( m_vertices[ i ] );
|
||||
|
||||
// angle between sun and vertex
|
||||
const float gamma = std::acos( DotProduct( vertex, m_sundirection ) );
|
||||
|
||||
// warning : major hack!!! .. i had to do something with values under horizon
|
||||
//vertex.y = Clamp<float>( vertex.y, 0.05f, 1.0f );
|
||||
if ( vertex.y < 0.05f ) vertex.y = 0.05f;
|
||||
|
||||
// from paper:
|
||||
// const float theta = arccos( vertex.y );
|
||||
// const float iCosTheta = 1.0f / cosf( theta );
|
||||
// optimized:
|
||||
// iCosTheta =
|
||||
// = 1.0f / cosf( arccos( vertex.y ) );
|
||||
// = 1.0f / vertex.y;
|
||||
float const icostheta = 1.0f / vertex.y;
|
||||
float const cosgamma2 = std::pow( std::cos( gamma ), 2 );
|
||||
|
||||
// Compute x,y values
|
||||
float const x = PerezFunctionO2( perezx, icostheta, gamma, cosgamma2, zenithx );
|
||||
float const y = PerezFunctionO2( perezy, icostheta, gamma, cosgamma2, zenithy );
|
||||
|
||||
// luminance(Y) for clear & overcast sky
|
||||
float const yclear = PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance );
|
||||
float const yover = ( 1.0f + 2.0f * vertex.y ) / 3.0f;
|
||||
|
||||
float const Y = interpolate( yclear, yover, m_overcast );
|
||||
float const X = (x / y) * Y;
|
||||
float const Z = ((1.0f - x - y) / y) * Y;
|
||||
|
||||
colorconverter = float3( X, Y, Z );
|
||||
color = XYZtoRGB( colorconverter );
|
||||
|
||||
colorconverter = RGBtoHSV(color);
|
||||
if ( m_linearexpcontrol ) {
|
||||
// linear scale
|
||||
colorconverter.z *= m_expfactor;
|
||||
} else {
|
||||
// exp scale
|
||||
colorconverter.z = 1.0f - exp( -m_expfactor * colorconverter.z );
|
||||
}
|
||||
color = HSVtoRGB(colorconverter);
|
||||
/*
|
||||
// gamma control
|
||||
color.x = std::pow( color.x, m_gammacorrection );
|
||||
color.x = std::pow( color.y, m_gammacorrection );
|
||||
color.x = std::pow( color.z, m_gammacorrection );
|
||||
*/
|
||||
// crude correction for the times where the model breaks (late night)
|
||||
// TODO: use proper night sky calculation for these times instead
|
||||
if( ( color.x <= 0.0f )
|
||||
&& ( color.y <= 0.0f ) ) {
|
||||
// darken the sky as the sun goes deeper below the horizon
|
||||
// 15:50:75 is picture-based night sky colour. it may not be accurate but looks 'right enough'
|
||||
color.z = 0.75f * std::max( color.z + m_sundirection.y, 0.075f );
|
||||
color.x = 0.20f * color.z;
|
||||
color.y = 0.65f * color.z;
|
||||
}
|
||||
|
||||
// save
|
||||
m_colours[ i ] = color;
|
||||
averagecolor += color;
|
||||
}
|
||||
|
||||
m_averagecolour = averagecolor / m_vertices.size();
|
||||
m_averagecolour.x = std::max( m_averagecolour.x, 0.0f );
|
||||
m_averagecolour.y = std::max( m_averagecolour.y, 0.0f );
|
||||
m_averagecolour.z = std::max( m_averagecolour.z, 0.0f );
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
60
skydome.h
Normal file
60
skydome.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "dumb3d.h"
|
||||
#include "float3d.h"
|
||||
|
||||
// sky gradient based on "A practical analytic model for daylight"
|
||||
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
|
||||
|
||||
class CSkyDome {
|
||||
public:
|
||||
CSkyDome( int const Tesselation = 54 );
|
||||
~CSkyDome();
|
||||
void Generate();
|
||||
void RebuildColors();
|
||||
|
||||
bool SetSunPosition( Math3D::vector3 const &Direction );
|
||||
|
||||
void SetTurbidity( const float Turbidity = 5.0f );
|
||||
void SetExposure( const bool Linearexposure, const float Expfactor );
|
||||
void SetOvercastFactor( const float Overcast = 0.0f );
|
||||
void SetGammaCorrection( const float Gamma = 2.2f );
|
||||
|
||||
// update skydome
|
||||
void Update( Math3D::vector3 const &Sun );
|
||||
// render skydome to screen
|
||||
void Render();
|
||||
|
||||
// retrieves average colour of the sky dome
|
||||
float3 GetAverageColor() { return m_averagecolour; }
|
||||
|
||||
private:
|
||||
// shading parametrs
|
||||
float3 m_sundirection;
|
||||
float m_thetasun, m_phisun;
|
||||
float m_turbidity;
|
||||
bool m_linearexpcontrol;
|
||||
float m_expfactor;
|
||||
float m_overcast;
|
||||
float m_gammacorrection;
|
||||
float3 m_averagecolour;
|
||||
|
||||
// data
|
||||
int const m_tesselation;
|
||||
std::vector<float3> m_vertices;
|
||||
std::vector<float3> m_normals;
|
||||
std::vector<float3> m_colours;
|
||||
|
||||
static float m_distributionluminance[ 5 ][ 2 ];
|
||||
static float m_distributionxcomp[ 5 ][ 2 ];
|
||||
static float m_distributionycomp[ 5 ][ 2 ];
|
||||
|
||||
static float m_zenithxmatrix[ 3 ][ 4 ];
|
||||
static float m_zenithymatrix[ 3 ][ 4 ];
|
||||
|
||||
// coloring
|
||||
void GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity );
|
||||
float GetZenith( float Zenithmatrix[ 3 ][ 4 ], const float Theta, const float Turbidity );
|
||||
float PerezFunctionO1( float Perezcoeffs[ 5 ], const float Thetasun, const float Zenithval );
|
||||
float PerezFunctionO2( float Perezcoeffs[ 5 ], const float Icostheta, const float Gamma, const float Cosgamma2, const float Zenithval );
|
||||
};
|
||||
4
sun.cpp
4
sun.cpp
@@ -39,7 +39,7 @@ cSun::update() {
|
||||
}
|
||||
|
||||
void
|
||||
cSun::render( Math3D::vector3 const &Origin ) {
|
||||
cSun::render() {
|
||||
|
||||
/*
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, position.getVector() ); // sun
|
||||
@@ -51,7 +51,7 @@ cSun::render( Math3D::vector3 const &Origin ) {
|
||||
glDisable(GL_FOG);
|
||||
glColor4f( 255.0f/255.0f, 242.0f/255.0f, 231.0f/255.0f, 1.f );
|
||||
// debug line to locate the sun easier
|
||||
Math3D::vector3 position = m_position + Origin;
|
||||
Math3D::vector3 position = m_position;
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( position.x, position.y, position.z );
|
||||
glVertex3f( position.x, 0.0f, position.z );
|
||||
|
||||
Reference in New Issue
Block a user